前言
小编一直使用的是服务器的session,最近的项目,小编做成了前后端分离,遇到了一些问题:
- 前后端项目分属于两个域名,如果要使用session,则需要解决跨域问题
- 如果接口存在多个服务器的话,session小编就不建议使用了
所以这时候,小编就想到了使用token,来验证用户的合法性。
Token和session的区别
- 跨域问题:token没有跨域问题,session有跨域问题;
- 容易扩展:token不储存于服务器中,适用于服务器的分布式应用;
- CSRF:不依赖与cookie,不会受到跨站请求伪造的攻击;
- 性能:相对于session,少了一次sessionid的计算;
以上是小编认为Token和session之间的一些不同之处,所以小编觉得使用token比较方便。
JWT Token(JSON WEB TOKEN)
小编对于token的使用,是基于JWT的,因为这个标准也是比较主流的一种使用规范。JWT主要由三部分组成:
- 头部(header)
- 载荷(payload)
- 签证(sign)
头部(header)
JWT的头部主要由两部分信息组成:
- 声明类型,这里上jwt
- 声明加密算法,如:HMAC、SHA256、HS256
下边的json,就是一个完整的头部信息:
{ \"typ\": \"JWT\", \"alg\": \"HS256\" }
我们将这个头部信息使用base64加密,就得到了我们JWT的第一部分信息了:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
载荷(payload)
主要有三部分组成:标准中注册的声明、公共的声明、私有的声明。
标准中注册的声明:
- iss:jwt签发者
- sub:jwt所面向的用户
- aud:接收jwt的一方
- exp:jwt的过期时间,这个过期时间必须大于签发时间
- nbf:定义在什么时间之前,该token都是不可用的
- iat:jwt的签发时间
- jti:jwt的唯一身份标识,避免重复
自定义的声明
用户自己添加的一些信息,比如用户姓名、手机号等一些不敏感信息。
我们来看看一个完整的载荷(payload)的json数据:
{ \"iss\": \'jwt\' \"sub\": \"13011912019\", \"exp\": \"1530000000\", \"iat\": \"1529000000\", \"jti\": \"638069ab7a97771edcb91180f491d01e\", \"nickname\": \"kafei\", \"avatar\": \"http://oy98jbaeo.bkt.clouddn.com/avatar-1532401501\" }
我们继续将这个载荷(payload)信息使用base64加密,就得到了我们JWT的第二部分信息了:
eyJpc3MiOiJqd3QiLCJzdWIiOiIxMzAxMTkxMjAxOSIsImV4cCI6IjE1MzAwMDAwMDAiLCJpYXQiOiIxNTI5MDAwMDAwIiwianRpIjoiNjM4MDY5YWI3YTk3NzcxZWRjYjkxMTgwZjQ5MWQwMWUiLCJuaWNrbmFtZSI6ImthZmVpIiwiYXZhdGFyIjoiaHR0cDovL295OThqYmFlby5ia3QuY2xvdWRkbi5jb20vYXZhdGFyLTE1MzI0MDE1MDEifQ
签证(sign)
前边我们已经获取到了头部信息的base64和载荷的base64的信息了,现在我们需要用这两个信息,生成一个签证(sign),这就是我们需要的第三部分信息了:
<?php $header = \'{\"typ\": \"JWT\",\"alg\": \"HS256\"}\'; $payload= \'{\"iss\": \"jwt\",\"sub\": \"13011912019\",\"exp\": \"1530000000\",\"iat\": \"1529000000\",\"jti\": \"638069ab7a97771edcb91180f491d01e\",\"nickname\": \"kafei\",\"avatar\": \"http://oy98jbaeo.bkt.clouddn.com/avatar-1532401501\"}\'; // 使用.拼接,header在前,payload在后 $encodedString = base64UrlEncode($header) . \'.\' . base64UrlEncode($payload); // 私密字符 $salt = \'kafei\'; // 签名 $sign= HS256($encodedString . $salt); // 这里使用随机一段字符代替 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 // 注意,PHP小编没找到HS256的加密,都是sha256的加密,后面小编有时间的话,会去写写这个 // 网上有现成的 JWT 库,大家可以去下载看看 // PHP 的 JWT 库的 GIT 地址:https://github.com/lcobucci/jwt ?>
最后,我们将这三部分连接起来,就是我们需要的JWT了:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqd3QiLCJzdWIiOiIxMzAxMTkxMjAxOSIsImV4cCI6IjE1MzAwMDAwMDAiLCJpYXQiOiIxNTI5MDAwMDAwIiwianRpIjoiNjM4MDY5YWI3YTk3NzcxZWRjYjkxMTgwZjQ5MWQwMWUiLCJuaWNrbmFtZSI6ImthZmVpIiwiYXZhdGFyIjoiaHR0cDovL295OThqYmFlby5ia3QuY2xvdWRkbi5jb20vYXZhdGFyLTE1MzI0MDE1MDEifQ.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
前端请求
将token放入到header里边的Authorization中,作为验证,如:
fetch(\'api/user/1\', { headers: { \'Authorization\': \'Bearer \' + token } })
优点
- 不需要储存在服务器的session中,更容易扩展服务器
- 由于用户信息可以放入token中,所以可以少了一次数据库 / 缓存的查询操作,有更好的性能
- 不需要预防CSRF的攻击
不足
- token一经泄露或者被盗取,将会暴露该用户
建议
- 设置token的过期时间,不宜过长
- 非常重要的操作,需要手机验证码,支付密码等二次验证作为保险
- 尽量使用 https
本文来自投稿,不代表重蔚自留地立场,如若转载,请注明出处https://www.cwhello.com/265719.html
如有侵犯您的合法权益请发邮件951076433@qq.com联系删除