NodeJs基于Token的身份认证

Caleb ... 2020-06-08
  • Node
  • Token
大约 3 分钟

# 传统的Session验证

起初的验证方式是存在于服务器的,用户登录进来以后,服务器判断成功,将数据存进session里面,向用户返回一个sessionID。这样的弊端是,假如用户基数特别大,每登录一个用户,就要存储一条,对服务器的内存压力比较大。

# 基于Token的验证方法

基于Token的验证方法是无状态的,因此我们就不用把信息存在服务器中了。

Token可以通过请求头传输,所以他可以在任何一种http请求中被发送到服务器中。

Token的验证流程

客户端发送用户、密码到服务器。
服务器接收到信息之后和数据库进行比对,验证成功后,生成一段有时效的Token字符串,向客户端返回登陆成功信息以及Token字符串。
客服端接收到信息,将Token存储在Local Storage或者Cookies中。
客服端再向服务器发送请求时,将Token放在请求头中。
服务器先解析请求头中的Token,如果解析成功,那么就进入业务逻辑中,如果不成功返回错误信息。
1
2
3
4
5

# nodeJS(express) + jwt(jsonwebtoken)

首先安装 jsonwebtoken

npm install jsonwebtoken -S

然后在服务器中创建一个js文件,可以自行命名,我在这里命名为jwt.js

// 引入模块依赖
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
// 创建 token 类
class Jwt {
    constructor(data, key, minute) {
        this.data = data;
        this.keyword = key;
        this.minute = minute || 30
    }
    //生成token
    generateToken() {
        let data = this.data;
        let minute = this.minute
        let keyword = this.keyword
        let created = Math.floor(Date.now() / 1000);
        let exp = created + 60 * minute;
        let cert = fs.readFileSync(path.join(__dirname, '../pem/rsa_private_key.pem')); //私钥 可以自己生成        
        let token = jwt.sign({
            data: {
                'id': data,
                "key": keyword
            },
            exp
        }, cert, {
            algorithm: 'RS256'
        });
        return token;
    }

    // 校验token
    verifyToken() {
        let token = this.data
        let cert = fs.readFileSync(path.join(__dirname, '../pem/rsa_public_key.pem')); //公钥 可以自己生成
        let res;
        try {
            let result = jwt.verify(token, cert, {
                algorithms: ['RS256']
            }) || {};
            let {
                exp = 0
            } = result, current = Math.floor(Date.now() / 1000);
            if (current <= exp) {
                res = result.data || {};
            }
            return res;
        } catch (e) {
            res = 'err';
        }
    }
}

module.exports = Jwt;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 解析

# generateToken

jwt.sign(payload, secretOrPrivateKey, [options, callback]);

payload ==> 代指要存进的内容
secretOrPrivateKey ==> 秘钥,我这里使用的是生成的私钥加密,也可以使用不规则字符。
[options, callback] ==> 参数,包括支持的算法等等
1
2
3
4
5

# verifyToken

jwt.verify(token, secretOrPublicKey, [options, callback]);

token ==> sign生成的Token
secretOrPublicKey ==> 使用生成的公钥解密。
[options, callback] ==> 使用相同的解密方式
1
2
3
4
5

# 具体参数

可以查看jsonwebtoken (opens new window)在npm上的详细解释

# 支持的算法

参数值 数字签名或MAC算法
HS256 使用SHA-256哈希算法的HMAC
HS384 使用SHA-384哈希算法的HMAC
HS512 使用SHA-512哈希算法的HMAC
RS256 使用SHA-256哈希算法的RSASSA-PKCS1-v1_5
RS384 使用SHA-384哈希算法的RSASSA-PKCS1-v1_5
RS512 使用SHA-512哈希算法的RSASSA-PKCS1-v1_5
PS256 使用SHA-256哈希算法的RSASSA-PSS(only node ^ 6.12.0 OR> = 8.0.0)
PS384 使用SHA-384哈希算法的RSASSA-PSS(only node ^ 6.12.0 OR> = 8.0.0)
PS512 使用SHA-512哈希算法的RSASSA-PSS(only node ^ 6.12.0 OR> = 8.0.0)
ES256 使用P-256曲线和SHA-256哈希算法的ECDSA
ES384 使用P-384曲线和SHA-384哈希算法的ECDSA
ES512 使用P-521曲线和SHA-512哈希算法的ECDSA
none 不包含数字签名或MAC值

# 前端的实际操作方法

# 怎么存储

因为我比较喜欢使用Cookie来存储的,所以以Cookie为主。

# 封装方法

首先使用一个npm包,js-cookie。

npm install js-cookie -S

在合适的文件夹中创建一个js文件。一般推荐在utils文件夹下

import Cookies from 'js-cookie'

const TokenName = 'XXXXXXXX'

export function getToken() {
  return Cookies.get(TokenName)
}

export function setToken(token) {
  return Cookies.set(TokenName, token, {
    expires: 1,
    path: '/'
  })
}

export function removeToken() {
  return Cookies.remove(TokenName)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 请求封装

以VUE来说,按照我之前关于Axios的文章,封装请求即可。

VUE.JS请求工具Axios的封装

# 完结撒花🎉🎉🎉

打赏