传统的Session验证
起初的验证方式是存在于服务器的,用户登录进来以后,服务器判断成功,将数据存进session里面,向用户返回一个sessionID。这样的弊端是,假如用户基数特别大,每登录一个用户,就要存储一条,对服务器的内存压力比较大。
基于Token的验证方法
基于Token的验证方法是无状态的,因此我们就不用把信息存在服务器中了。
Token可以通过请求头传输,所以他可以在任何一种http请求中被发送到服务器中。
Token的验证流程
客户端发送用户、密码到服务器。
服务器接收到信息之后和数据库进行比对,验证成功后,生成一段有时效的Token字符串,向客户端返回登陆成功信息以及Token字符串。
客服端接收到信息,将Token存储在Local Storage或者Cookies中。
客服端再向服务器发送请求时,将Token放在请求头中。
服务器先解析请求头中的Token,如果解析成功,那么就进入业务逻辑中,如果不成功返回错误信息。
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;
解析
generateToken
jwt.sign(payload, secretOrPrivateKey, [options, callback]);
payload ==> 代指要存进的内容
secretOrPrivateKey ==> 秘钥,我这里使用的是生成的私钥加密,也可以使用不规则字符。
[options, callback] ==> 参数,包括支持的算法等等
verifyToken
jwt.verify(token, secretOrPublicKey, [options, callback]);
token ==> sign生成的Token
secretOrPublicKey ==> 使用生成的公钥解密。
[options, callback] ==> 使用相同的解密方式
具体参数
可以查看jsonwebtoken在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)
}
请求封装
以VUE来说,按照我之前关于Axios的文章,封装请求即可。