JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。其JWT的组成一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
Token 相对于token Auth的优点
- 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
- 无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
- 更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可.
- 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.
- 更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
- CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。
- 性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多.
- 不需要为登录页面做特殊处理: 如果你使用Protractor 做功能测试的时候,不再需要为登录页面做特殊处理.
- 基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft).
安装模块
1 | npm i --save jsonwebtoken |
生成token信息
1 | const jwt = require('jsonwebtoken'); |
载荷(Payload)
1 | { "iss": "Online JWT Builder", |
- iss: 该JWT的签发者,是否使用是可选的;
- sub: 该JWT所面向的用户,是否使用是可选的;
- aud: 接收该JWT的一方,是否使用是可选的;
- exp(expires): 什么时候过期,这里是一个Unix时间戳,是否使用是可选的;
- iat(issued at): 在什么时候签发的(UNIX时间),是否使用是可选的;
其他还有: - nbf (Not Before):如果当前时间在nbf里的时间之前,则Token不被接受;一般都会留一些余地,比如几分钟;,是否使用是可选的;
第三方接入时,请求携带token
1 | var headers = { |
前端页面获取token,并存储记录
认证获取token后,将token存放位置
- localStorage
- sessionStorage
- cookie
- 针对单页面大应用,存放在某个标签上,或者公共的变量
1 | var str = sessionStorage.getItem("userInfo"); |
前端请求时携带token
- Url?token=xxxx
- Post 参数中携带token
- Header 参数中携带token,推荐使用这种方式
1 | function GetInfo(userId) { |
获取页面传入的token信息
1 | var token = req.body.token || req.query.token || req.headers['x-access-token']; |
Bearer 存在的意义?
1 | config.headers.Authorization = `Bearer ${store.state.token}` |
token 中间件校验verify
1 | let token = req.body.token || req.query.token || req.headers.token; //根据需要可以调整顺序 |
是否可以使用session 进行存储?
- 可以通过token获取session中的数据
- 通过session判断token是否存在的方式进行校验
- 但是,这样不安全,并且性能比较低
1 | User.findOne({ |
关于Token,你应该知道的一些事
一、Token 应该被保存起来(放到 local / session stograge
或者 cookies
)
二、Tokens 除了像 cookie 一样有有效期
,而且你可以有更多的操作方法
- cookies 可以在浏览器关闭后删除(session cookies);
- 另外你可以实现服务器端的检查(通常由你使用的 Web 框架完成),还有也可以实现绝对有效期或弹性有效期
- Cookies 可以带有有效期地保存起来(浏览器关闭后也不删除)。
而在 tokens 的使用中,一旦 token 过期,只需要重新获取一个。你可以使用一个接口去刷新 token:
- 让旧的 token 失效;
- 检查这个用户是不是还存在,权限是否被取消或者任何对你的程序来说是有必要的;
- 得到一个更新了有效期的 token。
你甚至可以把 token 原来的发布时间也保存起来,并且强制在两星期后重新登录什么的。
1 | app.post('/refresh_token', function(req, res) { |
如果你需要撤回 tokens(当 token 的生存期比较长的时候这很有必要)那么你需要一个 token 的生成管理器去作检查。
三、每个 CORS(跨域资源共享)请求都会带上预请求(Preflight request)
四、XSS要更容易防范
五、注意 token 的大小
Token 机制在每次请求 API 的时候,都需要带上一个 Authorization的 Http Header 。
Token 的大小其实由你储存在 token 中的信息量所决定,例如可能有 nickname,openid等开发者另外加上的信息。
六、有需要的话,要加密并且签名 token
虽然 TLS/SSL 机制可以隔绝大多数中间人攻击,但是如果 token 中带有了用户的敏感信息,开发者也应该要加密这些信息。
使用 JWT(文中第 9 点) 可以加密 token,但是由于目前大多数 Web 框架还未支持 JWT,所以可以使用 AES-CBC 算法加密 token。
1 | app.post('/authenticate', function(req, res) { |
参考目录:
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts
https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/
https://www.quora.com/Is-JWT-JSON-Web-Token-insecure-by-design
https://github.com/auth0/node-jsonwebtoken/issues/36
http://christhorntonsf.com/secure-your-apis-with-jwt/
https://www.cnblogs.com/xiekeli/p/5607107.html
https://www.jianshu.com/p/f9faeac8bd5e
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章