json-web-token
json-web-token,简称jwt。是服务端开发的认证的一种方式,是一种基于JSON的、用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成: 头信息(header), 消息体/载荷(payload)和签名(signature)。
header
中的内容指定的是jwt的签名算法
1 | { |
payload
这一部分为实体的状态,每个claim包含传输的信息,以及用于服务验证的信息。即里面可以存我们想要自定义验证的信息(如我们可以用户的id等需要使用的数据),可以包含规范定义的claim的信息。
1 | { |
- iss: jwt的发行者(可选)
- sub: 主题(可选)
- aud: jwt的接收者(可选)
- jti: 令牌的唯一标识符(可选)
- exp: 过期时间,numericData类型,Unix时间戳(可选)
- iat: 签发时间,numericData类型,Unix时间戳(可选)
- nbf: 有效起始时间(当前时间在nbf里的时间之前,则Token不被接受),numericData类型,Unix时间戳(可选)
signature
签名
生产token具体步骤
1 | # 先加头部信息的JSON对象进行[base64编码] |
jwt传输到服务端的方式相对传统方式比较灵活的,实际场景中,我们接受到服务端认证后返回的token,可以通过cookie或者http请求中自定义头部信息。在通常情况下,大部分会选择头部方法,由于cookie很容易受安全和跨域的影响。
头部规范
1 | Authorization: Bearer eyJhbGci... |
基于node服务端的实现
所需
- koa2 框架
- koa-jwt 基于koa框架的jwt中间件
- jsonwebtoken 用于生产token令牌和验证token有效性
koa-jwt
用来校验权限和解析token用的
jwt(obj1).unless(obj2)
- obj1
- secret,密钥
- passthrough
- key,附属在ctx.state上的属性,存放解析后的数据
- obj2
- path,数组类型,设置忽略校验的路径
jsonwebtoken
jsonwebtoken是基于node实现jwt功能的一个库
jwt.sign(payload, secretOrPrivateKey, [options, callback])
- payload: 载体,类型为object、buffer、string,对于使用
exp
字段时必须是object。 - secretOrPrivateKey: 密钥。类型可以查看官方github文档
- option
- algorithm (default: HS256)
- expiresIn: expressed in seconds or a string describing a time span zeit/ms. Eg: 60, “2 days”, “10h”, “7d”
- notBefore: expressed in seconds or a string describing a time span zeit/ms. Eg: 60, “2 days”, “10h”, “7d”
- audience
- issuer
- jwtid
- subject
- noTimestamp
- header
- keyid
其中expiresIn
, notBefore
, audience
, subject
, issuer
这些属性也可以设置在payload(object), 在其分别对应的exp
,nbf
,aud
,sub
,iss
。
开发
思路上实现验证的流程大体上几个步骤
- 在应用上配置
koa-jwt
中间件 - 当权限失效的时候,设置拦截的中间件
- 实现注册
- 实现登录
定义权限验证失败中间件
当请求经过koa-jwt
校验时,如果没有token或者token已经失效了,该中间件会给出对应的状态码为401
的错误信息,如果我们没自定义中间件来处理改错误时会直接返回给用户。
1 | this.app.use((ctx, next) => { |
koa-jwt
1 | this.app.use(jwt({ |
其中secret
为密钥,不限字符串,文件也行。unless()
用于设置那些路径不用经过校验,也就是public api
(通常对于注册和登录接口是不需要校验权限的)。当校验成功时,koa-jwt
会在请求的上下文,即ctx
的state
中添加user
属性,该属性的值为解析后的数据,当然你也可以更换键名。
1 | app.use(jwt({ secret: 'shared-secret', key: 'jwtdata' })); |
register
实现用户注册,将用户信息存入数据库。实际项目中需要加密,字段校验等措施。
login
实现用户登录,查询数据库是否该用户,然后将有关数据通过jsonwebtoken
签名生产token并返回给客户端,客户端可以通过localstorage
等方式将token存储在本地存储,在每次的 HTTP 请求中,都将 token 添加在 HTTP Header Authorazition: Bearer token 中。后端每次经过koa-jwt
去验证该token的正确与否。只有token正确后才能访问到对应的资源。
1 | jsonwebtoken.sign({ |
secret
为密钥,记住这里的secret必须要与中间件jwt()
中的secret 一致。
users
实现获取用户信息,我们需要在头部自定义Authorization
字段,就可以获取对应的资源。
1 | Authorization: Bearer ...(token) |
项目地址,运行npm run jwt