美文网首页
基于 JWT 接口认证

基于 JWT 接口认证

作者: 娃哈哈喜之郎 | 来源:发表于2020-04-01 22:37 被阅读0次

主流的网站项目,都是前后端完全分离。一个后端提供 restful api 服务,对应多个终端,如 ios, android, h5, web,在这种情况下,是无法使用 cookie + session 进行会话管理的,可以 token 进行用户认证鉴权,因为 token 是无状态的。

JWT 概述

JSON Web Token(JWT)是一个开放标准RFC 7519,它定义了一种紧凑且独立的方式,可以在各方之间作为 JSON 对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

基于 token 认证的优势。基于 token 的身份验证是无状态的,我们不将用户信息存在服务器或缓存中,减轻了服务器的压力;相比原始的 cookie + session 方式,token 更适合分布式系统的用户认证,绕开了传统的分布式 session一致性等问题;安全性高,不依赖 cookie,避免了 CSRF 攻击。

一个 JWT 实际上就是一个字符串,它由三部分组成,如下所示,它们之间以点拼接在一起,如 xxxxx.yyyyy.zzzzz

  • base64UrlEncode(Header)
  • base64UrlEncode(Payload)
  • Signature

Header 有两个部分组成,包括 token 类型和 hash 算法,对 Header 进行 Base64Url 编码,作为 JWT 的第一个部分。

{
  type: 'JWT',
  alg: 'HS256'
}

Payload 中可以添加一些 B/S 之间要传递的信息,如 userId,切记不要写例如密码这样的敏感信息,然后对 Payload 进行 Base64Url 编码,作为 JWT 的第二个部分。

Signature 是需要对 Base64 编码过的 Header, Payload 和密钥,进行算法加密,加密计算过程如下

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

通过签名可以验证 JWT 的有效性,如果被篡改过,就应该返回 401 未授权的错误提示

JWT 认证的实现过程,如下图所示:

image.png

JWT 可以保存在 localStorage 中,每次请求在 HTTP 请求时,在 Header 中加入 JWT 信息,格式如下:

Authorization: token

基于 Node.js 语言的 JWT 应用

首先在项目中安装所需的 jsonwebtoken 依赖包

npm i -S jsonwebtoken

签名和验证 token 语法如下

// 签名
jwt.sign(payload, secret,  [options, callback])
// 验证
jwt.verify(token, secret, [options, callback])

示例代码

// 签名
exports.signToken = userId => jwt.sign({ userId }, config.secret, { expiresIn: '2h' });
// 验证
exports.verifyToken = token => new Promise((resolve, reject) => {
  jwt.verify(token, config.secret, (err, decoded) => {
    if(err) reject(err);
    resolve(decoded.userId);
  });
});

通过 token 验证中间件,保证每次 api 请求,都是带有效 token 的合法请求,并将传递的信息,如 userId 挂载在 req 对象中,然后参与到业务的处理当中。

exports.authToken = function(req, res, next){
  const token = req.headers.authorization;
  utils.verifyToken(token, config.secret)
    .then(userId => {
      req.userId = userId;
      next()
    })
    .catch(err => next(err));
}

客户端对 token 的处理

客户端每次发出 http 请求,可以通过 axois 全局配置响应拦截器,检测到401未授权时,清空本地存储中的 token,重定向至登录页。

axios.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    if (error.response.status === 401) {
      localStorage.removeItem('token');
      location.href = `/login?redirect=${location.href}`;
    }
    return Promise.reject(error.response.data);
  }
);

参考资料

如果这篇文章对您有帮助,记得给作者点个赞,谢谢!

相关文章

网友评论

      本文标题:基于 JWT 接口认证

      本文链接:https://www.haomeiwen.com/subject/rtbzuhtx.html