createHash()方法用于创建Hmac实例。HMAC对象不能直接使用new关键字创建。
HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写
使用hmac.update()计算所有传递数据的HMAC摘要。编码可以是’hex’、‘latin
1’或’base64’。如果提供了编码,则返回字符串;否则返回Buffer;
const crypto = require('crypto');
var d = crypto.createHash('md5').update('by'+'121').digest('hex');
console.log('d', d);
module.exports = (str) => {
return crypto
.createHash('md5')
.update('by'+str)
.digest('hex');
}
express 使用md5加密的信息, 调取时是否需要解密 ?
在使用MD5加密存储用户密码的Express应用中,调取时不需要解密。
MD5是一种不可逆的加密算法,意味着一旦数据被MD5加密,就无法直接解密还原成原始数据。在Express框架中,如果用户密码是通过MD5加密后存储在数据库中的,那么在后续的调取过程中,不需要进行解密操作。这是因为MD5加密的特性决定了它只能用于单向验证,即通过输入明文密码与数据库中存储的加密密码进行比对,来验证用户输入的密码是否正确。
$ npm install jsonwebtoken
使用说明:
const { error } = require('console');
const jwt = require('jsonwebtoken');
// var token = jwt.sign({fool: 'hellow'}, '555')
// console.log(token)
// const jmtoken = jwt.verify('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb29sIjoiaGVsbG93IiwiaWF0IjoxNzIwNjg1OTAwfQ.iz4u9FGgcDPRF41xLGxTBVTV6vWkKJQJ3d0tCteCISI', '555')
// console.log('jmtoken', jmtoken);
// 解析token 会自动生成时间戳字段:“iat”
const {promisify} = require('util');
const tojwt = promisify(jwt.sign);
const verify = promisify(jwt.verify);
const {uuid} = require('../config/config.default');
// 创建token
module.exports.creatToken = async (obj)=>{
const token = await tojwt(
{obj}, // 加密对象
uuid,
{
expiresIn: '1h'
} // 过期时间
)
return token;
}
// token校验
module.exports.verifyToken = async (req, res, next)=>{
const header = req.headers;
console.log('header', header)
let token = header?.authorization || '';
token = token ? token.split('Bearer ')[1] : ''; // 获取token
if(!token){
res.status(402).json({
error: '请传入token'
})
}
try {
console.log('uuid', uuid)
const objToken = await verify(token, uuid); // 解析token
req.user = objToken; // 把正确有效的token信息放入请求体user
next() //
} catch (error) {
res.status(402).json({
error: '无效token'
})
}
}
user.js
const { User } = require('../model/index');
exports.register = async (req, res)=>{
console.log(222);
const userModel = new User(req.body);
// 保存数据集合
const dbback = await userModel.save();
let user = dbback.toJSON();
// 不给客户端查看用户密码
delete user.password;
// 返回给客户端注册成功
res.status(201).json(user);
}
exports.list = async (req, res)=>{
console.log(22222222, req.user);
res.send('/list');
}
exports.login = async (req, res)=>{
// 1.客户端验证数据格式校验middle validator
// 2.链接数据库查询 邮箱和密码校验
let dbback = await User.findOne(req.body);
if(!dbback) {
res.status(402).json({
error: "用户名密码不配"
})
}
dbback = dbback.toJSON();
dbback.token = await creatToken(dbback);
res.status(200).json(token);
}
JSON Web Token 是目前最流行的跨域认证解决方案
用户认证的一般流程:
1.客户端向服务器发送账号和密码。
2.服务器通过验证后在当前对话session中存放用户数据信息。
3.服务器向用户端返回session_id 写入用户的cookie。
4.客户端之后所有需要登录之后才能访问的请求都必须要携带 已经写入session_id的cookie,访问服务端。
5.服务器拿到session_id 进行校验得知用户是否登录或者是否登录过期。
一般流程的缺点: 无法实现不同域名网站的跨站登录
解决方案:JWT方案——服务器不保存 session_id 数据,所有数据都保存在客户端,每次请求都发回服务器.
JWT方案原理:
JWT有三个部分:Header(头部)、Payload(负载)、Signature(签名)
Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用”点”(.)分隔
实际写法:Header.Payload.Signature
1.header是json对象
{
"alg": "HS256", //签名的算法(algorithm) 默认是 HMAC SHA256(写成 HS256)
"typ": "JWT" typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
}
2.Payload也是json对象
{
// 内置可选字段
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
// 自定义字段
}
3. Header 和 Payload 串型化的算法是 Base64URL
4. Signature 部分是对前两部分的签名,防止数据篡改, secret 为服务器指定的密钥
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
7.解决跨域
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。 Authorization: Bearer + token
另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。