jwt认证实践

做毕设学了点东西系列

什么是jwt

介绍

jwt全称json web token,是一种流行的跨域认证方案,传统常用的用户认证cookie + session,现在的jwt是服务端不管状态了,把所有数据放在客户端处理,请求的时候带一个。这样服务器就变成了无状态的。
服务器认证完后,发一个json对象给用户,比如{name:'xxx', id; 001, exp: 2020-10-11 07:00},当然是经过加密的数据,之后用户通信的时候再把这个json对象发给服务端。

数据结构

jwt的数据结构有三个部分,header.payload.signature,也就是头部.负载.签名,比如下面这一长串

1
2
3
eyJhbGciOiJIUzI1NsIsInR5cCI6IkpXVCJ9.
eyJpZCI6MSwiaWF0IjoxNjExOTEzOTYxfQ.
Eb5Dt-ICNoq0bECBakI4UC2NdB8ooQXYkfwZ5--fPY4

  • header: 描述jwt的元数据,是一个json对象,包括签名的算法和令牌(token)的类型(JWT),使用base64url算法转成字符串
  • payload:存放实际传递的数据,是一个json对象,包括jwt提供的7个可选字段和用户自己加的字段,使用base64url算法转成字符串
  • signature:对前两部分的签名,防止数据篡改,使用header里面的签名算法,按照下面的公式计算签名
    1
    2
    3
    4
    HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    secret)

最后三个部分用点分隔拼接

在应用中使用jwt

这次项目里使用了node做后端,既然有现存的koa-jwt包,就用了jwt做认证,过程是这样滴:
整体来说:登录成功的话,把这个jwt从服务端发送给客户端,客户端使用localstorage做存储,在之后的所有请求里面,把这个jwt带过去。

安装的包

1
2
npm install koa-jwt // jwt的中间件
npm install jsonwebtoken // 用来生成token或者decode

服务端

在app.js中加入中间件

1
2
3
4
5
const jwt = require('koa-jwt');
const secret = 'jwt_secret'
app.use(jwt({secret}).unless({
path: [/\/register/, /\/login/],
})) // 如果是登录注册的话不需要带认证

服务端处理登录逻辑

1
2
3
4
5
6
7
8
9
10
const jwt = require('jsonwebtoken');
const userToken = {
id: result.dataValues.id
};
const secret = 'jwt_secret'; // 指定密钥
const token = jwt.sign(userToken, secret); // 签发token
ctx.body = {
status:"ok",
token
};

如果想要通过传过来的信息拿用户id做其他操作的话

1
2
3
4
5
const jwt = require('jsonwebtoken');
const data = ctx.request.body;
const token = ctx.request.header['authorization'].split(' ')[1];
const decode = jwt.decode(token); // 解token
const userId = decode.id;

客户端

客户端需要处理的是存储和发送这个token

登录成功后存储

1
2
3
4
if (response.status === 'ok') {
localStorage.setItem('userToken', response.token);
// ...
}

处理统一的请求

因为我用的是umi-request的extend方法,只需要加上这个header

1
2
3
4
5
6
const request = extend({
// ...
headers: {
Authorization: 'Bearer ' + localStorage.getItem('userToken')
}
});

其他的逻辑

除了基本的这个流程,其他的细节比如,

  • 密码加密:bcrypt
  • 自定义401拦截中间件,没有的话,会直接暴露koa-jwt的错误信息