git仓库地址:
1 身份验证
1.1 传统的身份验证
HTTP是一种无状态的协议,服务器接收一个来自客户端的request,处理完以后返回一个response。但是这个过程中,服务器几乎没有什么信息可以用来判断是哪个客户端(用户)发来的request。此时如果用户使用账户和密码登录,下回再发送请求时,还得再登录一遍。
1.1.1 方案一(cookie)
当用户登录成功后,我们直接把用户信息保存到cookie中,此后客户端的每一次请求都会带上这个cookie。
缺点:用户信息都保存在cookie中,容易被cokkie劫持
1.1.2 方案二(session)
当用户登录成功后,我们在服务端创建一个session对象,session会生成全局唯一标识符(JSESSIONID),把登录后的用户信息都保存在这个session对象中。然后服务端只要把JSESSIONID设置到cookie,此后客户端的每一次请求都会带上这个JSESSIONID。
缺点:系统一旦断电或重启,所有的会话数据都会丢失。特别是后台部署新版本,每次重启tomcat,用户都需要重新登录。
1.2 基于TOKEN的身份验证
使用基于Token的身份验证流程如下:
基于Token的认证,除了能避免传统身份验证的问题外,还有许多额外的优点:
- 无状态:由于Token已经包含了用户的所有信息,所以无需再存储Session
- 解耦:无需被绑定在一个特定的验证方案。作为独立的会话系统,利于实现分布式
- 基于标准:JWT作为Token的标准已经被广泛地接受。主流语言都有相应支持JWT标准的工具包
1.3 JWT
1.3.1 JWT的主要使用场景
- 身份验证
一旦用户完成了登录,在接下来的每个请求中都会包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。目前的单点登录(SSO)比较广泛地使用了该技术。
- 信息交换
在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,所以可以确保发送者发送的信息是没有经过伪造的。
1.3.2 JWT的结构
JWT包含了使用 . 分隔的三部分:头部(Header)、载荷(Payload)与签名(Signature)
其结构看起来是这样的:
eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0OTI3NTgxNDksInN1YiI6IkpXVFRva2VuIiwiYXVkIjoia2xkIiwiaXNzIjo.8izVDNnjr8qA-3twii6O0U3FCt0-tdtNHG6eT3LMiBY |
Header
在header中通常包含了两部分:token类型和采用的加密算法:
{ "typ" : "JWT", "alg" : "HS256" } |
Payload
Payload部分包含了一些跟这个token有关的重要信息。常用的有:
- iss:The issuer of the token,token发行人
- exp:Expiration Time,过期时间戳
- sub:The subject of the token,面向的用户
- aud:to whom the token is intended to be sent,接收方
- iat:签发时间
Payload示例:
{exp=1492771410, sub=org-gateway, aud=kld, iss=dahai, jti=v1, iat=1492767810} |
Signature
签名主要用于验证token是否有效,是否被篡改。签名时可以使用加密算法进行签名,例如希望使用HMACSHA256算法进行签名:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) |
1.3.3 JWT的安全设置
JWT字符串设置到Cookie时必须使用HttpOnly属性来防止Cookie被JavaScript读取,从而避免跨站脚本攻击(XSS攻击)。
参考
- jwt.io
- 基于Token的认证和基于声明的标识
- JSON Web Token (JWT) 简介
- 八幅漫画理解使用JSON Web Token设计单点登录系统
- jpadilla/pyjwt