传统的身份认证
http是一种无状态链接,这几意味着,你这一次的请求和上一次毫无联系。例如:小明访问了A网站,登录后查看了一篇VIP文章,这可好了,因为http无状态,关闭了这个vip文章后,再次打开,提示小明需要登录!
非常的麻烦,没有人愿意每次访问一个网站都输入一次账号密码。
最初的做法便是服务器保存你的状态,也就是session认证。在用户登录的时候,服务器会为其保留一个状态并将关键的“身份证”返回给浏览器(可能是一串数字,一串字符串,总而言之他将独一无二)。然后告诉浏览器:"小子,好好保存到cookie上,每次请求我就认识你是哪位兄贵了"。
- 最初还是无所谓,随着你的业务的扩展,同时在线的人数不断攀升的情况下,这种方法只会无限的扩大服务器成本。
- 因为是单独服务器做的记录,这就意味着负载均衡成了一个难解决的问题。
token
token是不需要在服务器去专门为其保留会话状态。这就意味着它解决了上述的两个问题。为网页应用提供了极大的便利。 token的请求也非常简单,账号密码输入正确后,服务器为其颁发一个独一无二的加密密钥token。以后的请求token都将放到请求头上。
JWT
jwt应该是主流应用了,它由三段信息构成--每段由“.”分割。以下是一个例子: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
从头到尾按顺序我们称为:头部、载荷、签证。
头部
头部主要是承载了两个信息:
- 是什么类型:jwt
- 是什么加密算法 hmac sha256
{
'typ': 'JWT',
'alg': 'HS256'
}
对这段文字base64编码后形成:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
载荷
这段就是大家存放有效信息的地方了,一般分为三种类型的数据(非标准划分):
- 标准类型:这里有一些约定好的数据类型格式(并不强制使用,你可以都自定义成自己喜欢的,但是建议使用,大家有一套规矩共同开发会使得代码生活更美好)。
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的.
- iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
- 公共类型:添加一些无所谓的变量,例如:用户nickname。
- 私有类型:放一些敏感变量,例如:用户权限。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
对其base编码后形成 :eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 第二部分的数据。
因为base64和明文几乎无区别,不推荐放隐私信息进入载荷。
签证
签证有三部分组成(载荷是三种,这个是三部分):
- 头部(编码后)
- 载荷(编码后)
- 密钥
因为头部包含了加密的方法 hs256。
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
头部与载荷编码后,通过密钥与加密算法得出签证后就可以办法给用户签证了。