基于JWT的token认证

in 普通BLOG
0 评论 阅读量:602

关于身份认证

传统的session认证

我们知晓,http协议本身是一种无状态的协议,用户对站点的每次访问,都需要提供凭证(账号密码)。站点需要一个标识来识别用户,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递到浏览器,通知它保存为cookie会话,对应到我们服务器的信息,以便下次请求时核验,这就是传统的基于session认证。
在站点运营日积月累下,基于session认证的问题逐渐暴露。每次记录的session随着用户增多,对应的消耗(IO/内存)增加,服务器的开销明显增大;依赖cookie的机制,使得cookie被截获后容易收到跨站请求伪造的攻击(CSRF);扩展上难度较大,认证的方式在分布式场景不利于同步

基于token的鉴权机制

很多对外开放的API需要识别请求者的身份,并据此判断所请求的资源是否可以返回给请求者。token就是一种用于身份验证的机制,基于这种机制,应用不需要在服务端保留用户的认证信息或者会话信息,可实现无状态、分布式的Web应用授权,为应用的扩展提供了便利。

Json Web Token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准RFC7519。JWT一般可以用作独立的身份验证令牌,可以包含用户标识、用户角色和权限等信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,特别适用于分布式站点的登录场景。

JWT的构成
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
如上面的例子所示,JWT就是一个字符串,由三部分构成:

就是存放关键信息的地方。定义细节如下:

iss:令牌颁发者。表示该令牌由谁创建,该声明是一个字符串

sub:Subject Identifier,iss提供的终端用户的标识,在iss范围内唯一,最长为255个ASCII个字符,区分大小写

aud:Audience(s),令牌的受众,分大小写的字符串数组

exp:Expiration time,令牌的过期时间戳。超过此时间的token会作废, 该声明是一个整数,是1970年1月1日以来的秒数

iat: 令牌的颁发时间,该声明是一个整数,是1970年1月1日以来的秒数

jti: 令牌的唯一标识,该声明的值在令牌颁发者创建的每一个令牌中都是唯一的,为了防止冲突,它通常是一个密码学随机值。这个值相当于向结构化令牌中加入了一个攻击者无法获得的随机熵组件,有利于防止令牌猜测攻击和重放攻击。

另外,也可以新增用户系统需要使用的自定义字段,比如下面的例子添加了name(用户昵称)

{
    "sub": "1234567890",
    "name": "John Doe"
}

然后将其进行Base64编码,得到Jwt的第二部分:

这个部分需要Base64编码后的Header和Base64编码后的Payload使用 '.' 连接组成的字符串,然后通过Header中声明的加密方式进行加密($secret 表示用户的私钥),然后就构成了jwt的第三部分。

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, '$secret');

将这三部分用 . 连接成一个完整的字符串,就构成了xxx.yyy.zzz的JWT。


特性和建议


参考资料

jwt.io Debugger - 解码、验证和生成 JWT

基于JWT的token认证

Comments are closed.