①原因
HTTP是无状态的协议,一次请求结束后,下次在发送服务器就不知道这个请求是谁发来的了(同一个IP不代表同一个用户),在Web应用中,用户的认证和鉴权是非常重要的一环,实践中有多种可
用方案,且各有千秋。
②Cookie-Session认证
早期,大部分网站采用基于Cookie-Session的会话管理方式。
- 客户端使用用户名、密码进行认证
-
服务端验证用户名、密码正确后生成并存储Session,将SessionID通过Cookie返回给客户端
-
客户端访问需要认证的接口时在Cookie中携带SessionID
-
服务端通过SessionlD查找Session并进行鉴权,返回给客户端需要的数据
这个session实现方式一般使用key, value来实现,key是sessionid, sessionid发放给客户端,客户端请求的时候,查询键值对。
缺点,不足
- 服务端需要存储Session,并且由于Session需要经常快速查找,通常存储在内存或内存数据库中,同时在线用户较多时需要占用大量的服务器资源。
-
当需要扩展时,创建Session的服务器可能不是验证Session的服务器,所以还需要将所有Session单独存储并共享。或者做成一个服务,可能存在一些其他的问题。
-
由于客户端使用Cookie存储SessionID,在跨域场景下需要进行兼容性处理,同时这种方式也难以防范CSRF攻击。
③Token认证
鉴于基于Session的会话管理方式存在很多不足,基于Token的无状态会话管理方式诞生了,所谓无状态,就是服务端可以不再存Session。
- 客户端使用用户名、密码请求服务器进行认证,–》
-
服务端验证用户名、密码正确后生成Token返回给客户端。《–
-
客户端保存Token,访问需要认证的接口时在URL参数或HTTPHeader中加入Token
-
服务端通过解码Token进行鉴权,返回给客户端需要的数据
优缺点
基于Token的会话管理方式有效解决了基于Session的会话管理方式带来的问题。
- 服务端不需要存储和用户鉴权有关的信息,鉴权信息会被加密到Token中,服务端只需要读取Token中包含的鉴权信息即可
-
避免了共享Session导致的不易扩展问题
-
不需要依赖Cookie,有效避免Cookie带来的CSRF攻击问题
-
使用CORS可以快速解决跨域问题
④JWT鉴权
JWT
是JSONWebToken
的缩写,是为了在网络应用环境间传递声明而执行的一种基于ISON的开放标
准(REC7519)
。JWT
本身没有定义任何技术实现,它只是定义了一种基于Token
的会话管理的规则,
涵盖Token
需要包含的标准内容和Token
的生成过程,特别适用于分布式站点的单点登录(SSO)
场景。
JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt
字符串。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
他是由 .
分割的三部分组成,这三部分依次是:
- Header 头部
jwt的头部承载两部分信息:
- 声明类型,这里是jwt
- 声明加密的算法 通常直接使用 HMAC SHA256
{
'typ': 'JWT',
'alg': 'HS256'
}
- Payload 负载
Payload表示负载,也是一个JSON对象,WT规定了7个官方字段供选用,
iss: 签发人
sub: jwt所面向的用户, 主题
aud: 接收jwt的一方
exp: 过期时间
nbf: 生效时间
iat: 签发时间
jti: 编号——jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
用户也可以指定自己的字段和内容
{
"sub": "root",
"name": "xiaosheng",
"admin": true
}
Jwt默认是不加密的,任何人都能看到,不要把重要信息放到这里
头部和负载以JSON形式存在,这就是JWT中的JSON,三部分的内容都分别单独经过了Base64编码,以拼接成JWTToken
。
- Signature 签名
Signature部分是对前两部分的签名,防止数据复改。
HMACSHA256(base64UrlEncode(header)+ "." +
base64UrlEncode(payload),secret)
JWT缺点
JWT
拥有基于Token
的会话管理方式所拥有的一切优势,不依赖Cookie
,使得其可以防止CSRF
攻
击,也能在禁用Cookie
的浏览器环境中正常运行。
而JWT的最大优势是服务端不再需要存储Session
,使得服务端认证鉴权业务可以方便扩展,避免存储
Session
所需要引入的Redis
等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期
存储在Token
中,JWTToken
一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的JWTToken
,如果需要禁用用户,单纯使用JWT
就无法做到
了。
前面写的Token
,都是AccessToken
,也就是访问资源接口时所需要的Token
,还有另外一种Token,RefreshToken
,通常情况下,RefreshToken
的有效期会比较长,而AccessToken
的有效期通常短。
原理可以阅读:https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html