Open Hibop opened 5 years ago
from: https://auth0.com/blog/cookies-vs-tokens-definitive-guide/要点翻译
cookie 验证是用于长时间用户验证,cookie 验证是有状态的,意味着验证记录或者会话需要一直在服务端和客户端保持。服务器需要保持对数据库活动会话的追踪,当在前端创建了一个 cookie,cookie 中包含了一个 session 标识符。传统 cookie 会话的验证流程:
用户登录,输入账号密码
服务器验证用户账号密码正确,创建一个 session 存储在数据库(或者 redis)
将 session ID 放进 cookie 中,被存储在用户浏览器中。
再次发起请求,服务器直接通过 session ID 对用户进行验证
一旦用户登出,则 session 在客户端和服务器端都被销毁
token 验证是无状态的,服务器不记录哪些用户登录了或者哪些 JWT 被发布了,而是每个请求都带上了服务器需要验证的 token,token 放在了 Authorization header 中,形式是 Bearer { JWT },但是也可以在 post body 里发送,甚至作为 query parameter。 验证流程:
用户输入登录信息
服务器判断登录信息正确,返回一个 token
token 存储在客户端,大多数通常在 local storage,但是也可以存储在 session storage 或者 cookie 中。
接着发起请求的时候将 token 放进 Authorization header,或者同样可以通过上面的方式。
服务器端解码 JWT 然后验证 token,如果 token 有效,则处理该请求。
一旦用户登出,token 在客户端被销毁,不需要经过服务器端
无状态。可扩展和解耦
后端无需保持对token的记录,每个token都是独立的,包含了检查其有效性的所有数据, 并通过申明传达了用户信息。 服务器端的工作只需要在登录成功后,生成(或者 sign,签署) token,或者验证传入的 token 是否有效。有时候甚至不需要生成 token,第三方服务比如 Auth0 可以处理 token 的签发,服务器只需要验证 token 的有效性就可以。
跨域和 CORS
cookie 能很好的处理单域和子域,但是遇到跨域的问题就会变得难以处理。而使用 token 的 CORS 可以很好的处理跨域的问题。由于每次发送请求到后端,都需要检查 JWT,只要它们被验证通过就可以处理请求。
移动平台
现代的 API 不仅仅和浏览器交互,正确编写一个 API 可以同时支持浏览器,还有原生移动平台,比如 IOS 或者 Android。原生移动平台并不一定和 cookie 能良好的兼容,在使用中会存在一些限制和需要注意的地方。另一方面,token 更容易在 IOS 和 Android 上实现,Token 也更容易实现物联网应用程序和服务,没有 Cookie 存储的概念。
JWT 大小 token 最大的缺点就是它的大小,最小的它都比 cookie 要大,如果 token 中包含很多声明,那问题就会变得比较严重,毕竟向服务器发送的每个请求都要有这个 token。(意思应该是太大了会导致请求缓慢)
哪里存储 token 通常 JWT 被存储在浏览器的 local storage 中并且能够很好的运用,但是这样存储也会有问题,不像 cookie,local storage 被沙盒化到特定域,其区域不能被任何其他域访问,包括子域。 你可以存储 token 在 cookie 中,但是 cookie 最大的大小也只有 4kb,所以如果你有许多声明的时候可能会存储不够,session storage 就更不用说了,会话断开就被清除掉了。
XSS 和 XSRF 防护 保护用户信息安全和服务器数据始终是首要任务。最常见的网络攻击就是 XSS 和 CSRF。 如果用户输入或提交的信息没有得到过滤的话,如果一些攻击代码可以在你访问的域名下执行,那你的 JWT token 会被泄露。与 CSRF 相比,XSS 会更容易处理(因为 XSS 很容易理解)。许多框架包括 Angular 等等,都会自动过滤掉 input 输入的某些内容且防止任意代码执行。如果框架本身不自带这种过滤机制,可以采用一些插件比如 caja。这种过滤 input 输入框是大部分框架和语言解决 XSS 问题的一个方式。 如果你通过 local storage 使用 JWT,那么可以避免 CSRF,但是另一方面,如果你用 cookie 来存储 JWT,那就需要防护 CSRF,CSRF 并不像 XSS 攻击那么好理解。解释 CSRF 攻击可能会非常耗时。为了避免过度简化,防止 CSRF 攻击,你的服务器会和客户端建立会话后,会生成一个唯一的 token(这不是 JWT)。然后随时将数据提交到你的服务器,隐藏的 input 将会包含这个 token,服务器将会检查这个 token 以确保 token 匹配。不够我们是建议将 JWT 存储在 local storage 中,你也不太需要担心 CSRF 攻击的问题。 其中一个最好的保护用户和服务器的方法就是有一个给 token 一个短期过期时间,这样即使 token 被其他人获取,但是也会很快不能再用。此外,你可以维护一个受攻击的 token 黑名单,不允许这些黑名单的 token 访问系统。最后,还可以统一更改 token 算法,让所有 token 都失效,并让用户重新登录系统,不过这种方法一般不推荐,只有在被攻击比较严重的情况下使用。
一、Basic Auth(HTTP Auth) Basic Auth简单点说明就是每次请求API时都提供用户的username和password。包括:
基于session认证所显露的问题: Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
有两种基于 Token 的认证方案 JWT/Oauth2.0
Basic Auth优点: ①使用非常简单, ②开发和调试工作简单, ③没有复杂的页面跳转逻辑和交互过程; ④更利于发起方控制;
Basic Auth缺点: ①安全性低,每次都需要传递用户名和密码,用户名和密码很大程度上存在被监听盗取的可能; ②同时应用本地还需要保存用户名和密码,在应用本身的安全性来说,也存在很大问题; ③开放平台服务商出于自身安全性的考虑(第三方可以得到该服务商用户的账号密码,对于服务商来说是一种安全隐患),未来也会限制此认证方式(Twitter就计划在6月份停止Basic Auth的支持) ④用户如果更改了用户名和密码,还需要重新进行密码校验的过程。
二、OAuth OAuth为用户资源的授权提供了一个安全、开放的标准,它分为几个交互过程: 1)应用用APP KEY和APP SECRET换取OAuth_token; 2)应用将用户引导到服务商的页面对该OAuth_token进行授权(可能需要输入用户名和密码); 3)服务商的页面跳转回应用,应用再根据参数去服务商获得Access Token; 4)使用这个Access Token就可以访问API了。
OAuth的优点: ①安全性高,用户的账户和密码只需要提供一次,而且是在服务商的页面上提供,防止了Basic Auth反复传输密码带来的安全隐患; ②Access Token访问权限仅限于应用,被窃取不会影响用户在该服务商的其他服务; ③Access Token即使被监听丢失了随时可以撤销,不像密码丢失可能就被别人篡改了; ④用户修改了密码也不会影响该应用的正常使用。
from: https://auth0.com/blog/cookies-vs-tokens-definitive-guide/要点翻译
Cookie
cookie 验证是用于长时间用户验证,cookie 验证是有状态的,意味着验证记录或者会话需要一直在服务端和客户端保持。服务器需要保持对数据库活动会话的追踪,当在前端创建了一个 cookie,cookie 中包含了一个 session 标识符。传统 cookie 会话的验证流程:
用户登录,输入账号密码
服务器验证用户账号密码正确,创建一个 session 存储在数据库(或者 redis)
将 session ID 放进 cookie 中,被存储在用户浏览器中。
再次发起请求,服务器直接通过 session ID 对用户进行验证
一旦用户登出,则 session 在客户端和服务器端都被销毁
Token
token 验证是无状态的,服务器不记录哪些用户登录了或者哪些 JWT 被发布了,而是每个请求都带上了服务器需要验证的 token,token 放在了 Authorization header 中,形式是 Bearer { JWT },但是也可以在 post body 里发送,甚至作为 query parameter。 验证流程:
用户输入登录信息
服务器判断登录信息正确,返回一个 token
token 存储在客户端,大多数通常在 local storage,但是也可以存储在 session storage 或者 cookie 中。
接着发起请求的时候将 token 放进 Authorization header,或者同样可以通过上面的方式。
服务器端解码 JWT 然后验证 token,如果 token 有效,则处理该请求。
一旦用户登出,token 在客户端被销毁,不需要经过服务器端
Token 验证的优势
无状态。可扩展和解耦
跨域和 CORS
移动平台
token遗留的一些问题;
JWT 大小 token 最大的缺点就是它的大小,最小的它都比 cookie 要大,如果 token 中包含很多声明,那问题就会变得比较严重,毕竟向服务器发送的每个请求都要有这个 token。(意思应该是太大了会导致请求缓慢)
哪里存储 token 通常 JWT 被存储在浏览器的 local storage 中并且能够很好的运用,但是这样存储也会有问题,不像 cookie,local storage 被沙盒化到特定域,其区域不能被任何其他域访问,包括子域。 你可以存储 token 在 cookie 中,但是 cookie 最大的大小也只有 4kb,所以如果你有许多声明的时候可能会存储不够,session storage 就更不用说了,会话断开就被清除掉了。
XSS 和 XSRF 防护 保护用户信息安全和服务器数据始终是首要任务。最常见的网络攻击就是 XSS 和 CSRF。 如果用户输入或提交的信息没有得到过滤的话,如果一些攻击代码可以在你访问的域名下执行,那你的 JWT token 会被泄露。与 CSRF 相比,XSS 会更容易处理(因为 XSS 很容易理解)。许多框架包括 Angular 等等,都会自动过滤掉 input 输入的某些内容且防止任意代码执行。如果框架本身不自带这种过滤机制,可以采用一些插件比如 caja。这种过滤 input 输入框是大部分框架和语言解决 XSS 问题的一个方式。 如果你通过 local storage 使用 JWT,那么可以避免 CSRF,但是另一方面,如果你用 cookie 来存储 JWT,那就需要防护 CSRF,CSRF 并不像 XSS 攻击那么好理解。解释 CSRF 攻击可能会非常耗时。为了避免过度简化,防止 CSRF 攻击,你的服务器会和客户端建立会话后,会生成一个唯一的 token(这不是 JWT)。然后随时将数据提交到你的服务器,隐藏的 input 将会包含这个 token,服务器将会检查这个 token 以确保 token 匹配。不够我们是建议将 JWT 存储在 local storage 中,你也不太需要担心 CSRF 攻击的问题。 其中一个最好的保护用户和服务器的方法就是有一个给 token 一个短期过期时间,这样即使 token 被其他人获取,但是也会很快不能再用。此外,你可以维护一个受攻击的 token 黑名单,不允许这些黑名单的 token 访问系统。最后,还可以统一更改 token 算法,让所有 token 都失效,并让用户重新登录系统,不过这种方法一般不推荐,只有在被攻击比较严重的情况下使用。
关于认证,开放平台有两种认证方式,一种是Basic Auth,一种是OAuth。
一、Basic Auth(HTTP Auth) Basic Auth简单点说明就是每次请求API时都提供用户的username和password。包括:
基于session认证所显露的问题: Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
有两种基于 Token 的认证方案 JWT/Oauth2.0
Basic Auth优点: ①使用非常简单, ②开发和调试工作简单, ③没有复杂的页面跳转逻辑和交互过程; ④更利于发起方控制;
Basic Auth缺点: ①安全性低,每次都需要传递用户名和密码,用户名和密码很大程度上存在被监听盗取的可能; ②同时应用本地还需要保存用户名和密码,在应用本身的安全性来说,也存在很大问题; ③开放平台服务商出于自身安全性的考虑(第三方可以得到该服务商用户的账号密码,对于服务商来说是一种安全隐患),未来也会限制此认证方式(Twitter就计划在6月份停止Basic Auth的支持) ④用户如果更改了用户名和密码,还需要重新进行密码校验的过程。
二、OAuth OAuth为用户资源的授权提供了一个安全、开放的标准,它分为几个交互过程: 1)应用用APP KEY和APP SECRET换取OAuth_token; 2)应用将用户引导到服务商的页面对该OAuth_token进行授权(可能需要输入用户名和密码); 3)服务商的页面跳转回应用,应用再根据参数去服务商获得Access Token; 4)使用这个Access Token就可以访问API了。
OAuth的优点: ①安全性高,用户的账户和密码只需要提供一次,而且是在服务商的页面上提供,防止了Basic Auth反复传输密码带来的安全隐患; ②Access Token访问权限仅限于应用,被窃取不会影响用户在该服务商的其他服务; ③Access Token即使被监听丢失了随时可以撤销,不像密码丢失可能就被别人篡改了; ④用户修改了密码也不会影响该应用的正常使用。