express中实现加密JWT(JSON Web Token)

本文致力于用最简单、最少的代码完成用express实现加密(MD5)JWT功能,用于登陆验证。javascript

JWT(JSON Web Token)

JWT(json web token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。(json格式传token) JWT的声明通常被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。好比用在用户登陆上。前端

JWT数据结构

JWT的三个部分:JWT头、有效载荷和签名。java

JWT头

JWT头部分是一个描述JWT元数据的JSON对象,一般以下所示。ios

{web

“alg”: “HS256”,算法

“typ”: “JWT”express

} 上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。json

有效荷载

Payload 部分也是一个 JSON 对象,用来存放实际须要传递的数据。JWT 规定了7个官方字段,供选用。axios

iss (issuer):签发人 exp (expiration time):过时时间 sub (subject):主题 aud (audience):受众 nbf (Not Before):生效时间 iat (Issued At):签发时间 jti (JWT ID):编号 除此以外,你还能够自定义字段,如:api

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
复制代码

签名

Signature 部分是对前两部分的签名,防止数据篡改。

首先,须要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。而后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
复制代码

算出签名之后,把 Header、Payload、Signature 三个部分拼成一个字符串,每一个部分之间用"点"(.)分隔,就能够返回给用户。

JWT工做过程

工做过程: 1.前端向服务端发送用户名和密码。

2.服务端生成JWT。

3.将生成的JWT发送到前端,相关数据(如用户角色,登陆时间等)将保存在当前会话中。

4.前端向服务端请求数据时,将JWT放到Header中,发送给服务端。

5.服务端收到JWT,进行验证,确认用户信息。

6.验证成功,返回数据给前端。

express实现过程

express部分

一、下载express-jwt (生成 token)+ jsonwebtoken(验证 token)两个包 二、设置了密码盐值以及token的secretKey(JWT默认是不加密的,这里用到了MD5加密,并用salt对密码进行了复杂化)

// /constant.js
var crypto = require('crypto');
module.exports = {
    MD5_SUFFIX: 'houyuping', //固定长度的盐值salt
    md5: function (pwd) {
        var md5 = crypto.createHash('md5');
        return md5.update(pwd).digest('hex');
    },
    secretKey: 'yichen_qingting_jwttoken'
};
复制代码

三、在登陆环节生成token

// /routes/user.js
var token = jwt.sign(data, constant.secretKey, {
    expiresIn: 60 * 60 * 24 // 受权时效24小时
})
res.json({
    success: true,
    message: 'success',
    token: token
})
复制代码

四、设置拦截token的中间件,包括token的验证以及错误信息的返回:

// /jwt.js
const expressJwt = require("express-jwt");
const secretKey  = require('./constant');
// express-jwt中间件帮咱们自动作了token的验证以及错误处理,因此通常状况下咱们按照格式书写就没问题,其中unless放的就是你想要不检验token的api。
const jwtAuth = expressJwt({secret: secretKey.secretKey}).unless({path: ["/users/login","/users/query"]});
module.exports = jwtAuth;
复制代码

五、最后在路由中间件前面放上jwt中间件

var express = require('express');
var router = express.Router();
var jwtAuth = require('./jwt')
// 全部请求过来都会进行身份验证
router.use(jwtAuth);
// 路由中间件
router.use(function (req, res, next) {
    // 任何路由信息都会执行这里面的语句
    console.log('this is a api request!');
// 把它交给下一个中间件,注意中间件的注册顺序是按序执行
    next();
});
复制代码

前端部分 一、将获取的token保存到localstorage中

let token = window.localStorage.getItem("wyg_token");
复制代码

二、每次请求带上token,将token放入header中

this.$axios.post('http://127.0.0.1:3000/users/modifyPwd',
    {data: data},
{headers: {'Authorization': `Bearer ${token}`}}
)
复制代码

JWT优缺点

优势:

  1. 不易被攻击,安全性高
  2. 利用Authorization首部传输token,无跨域问题
  3. 额外信息存储在客户端,服务端占用资源很少,也不存在session共享问题

缺点:

  1. 登陆状态信息续签问题。一旦发放令牌,在过时时间内没法修改注销。
  2. 占用内存比cookies要大。
相关文章
相关标签/搜索