繁体   English   中英

在 ember-cli-mirage(或任何 JavaScript)中生成 jwt web auth 令牌以在您的 ember 应用程序中使用

[英]Generate jwt web auth tokens in ember-cli-mirage (or any JavaScript) for use in your ember app

我在 Ember 团队工作,该团队为我们的 API 安全性实施了 djangorestframework-simplejwt。 这是一个很好的 API 解决方案,但是我们的 Mirage 用户在一段时间后被注销并且无法重新登录我们的应用程序(用于测试、开发)。 我将问题追溯到 jwt 的工作原理,以及我在 Mirage 配置 /login 端点中粘贴静态 jwt 令牌的事实。

jwt 或 JSON Web 令牌包含在服务器上设置的到期日期。 一旦过期日期过去,客户端将无法再通过身份验证进入应用程序,直到服务器发送具有未来过期日期的新令牌。 这对我们的 mirage ENV 来说是一个问题,因为 /login 的 mirage 端点返回了一个静态 jwt 令牌,我从我们的后端响应中复制/粘贴了该令牌。 解决方法是从我们的后端获取新令牌,将它们粘贴到我们的 Mirage 配置中并使用它们直到它们过期,这不是解决此问题的真正永久解决方案。

经过大量的反复试验(以及对 jwt 的了解太多),我想出了这个解决方案,它创建了一个有效的 jwt 令牌,有效期为未来 7 天。 它只需要crypto-js (npm install crypto-js),一个非常轻量级的库,有很多加密函数,但没有依赖:

import CryptoJS from 'CryptoJS';

const generateTokens = function(secretKey) { // fn to generate jwt access and refresh tokens with live date (+7 days) expiration
  let newEpochDate = new Date().valueOf();
  newEpochDate += 6.048e8; // add 7 days padding
  newEpochDate = Math.trunc(newEpochDate / 1000); // convert to Java epoch date value
  let tokenObjBase = {
    'typ': 'JWT',
    'alg': 'HS256'
  };
  let tokenObjAccess = {
    'token_type': 'access',
    'exp': newEpochDate,
    'jti': '83bc20a2fb564aa8937d167586166f67',
    'user_id': 24865
  };
  let tokenObjRefresh = {
    'token_type': 'refresh',
    'exp': newEpochDate,
    'jti': '83bc20a2fb564aa8937d167586166f67',
    'user_id': 24865
  };

  let base64urlEncode = function (obj) {
    let base64url = CryptoJS.enc.Utf8.parse(JSON.stringify(obj)).toString(CryptoJS.enc.Base64);
    base64url = base64url.replace(/=/g, '').replace(/\//g, '_').replace(/\+/g, '-'); // crypto-js doesn't have base64url encoding; we must manually make the tokens URL safe
    return base64url;
  }
  let tokenBase = base64urlEncode(tokenObjBase);
  let tokenAccess = base64urlEncode(tokenObjAccess);
  let tokenRefresh = base64urlEncode(tokenObjRefresh);

  let signatureAccessArray = CryptoJS.HmacSHA256(tokenBase + '.' + tokenAccess, secretKey); // crypto-js returns a "wordarray" which must be stringified back to human readable text with a specific encoding
  let signatureAccess = signatureAccessArray.toString(CryptoJS.enc.Base64).replace(/=+$/, '').replace(/\//g, '_').replace(/\+/g, '-'); // crypto-js doesn't have base64url encoding; we must manually make the tokens URL safe
  let signatureRefreshArray = CryptoJS.HmacSHA256(tokenBase + '.' + tokenRefresh, secretKey);
  let signatureRefresh = signatureRefreshArray.toString(CryptoJS.enc.Base64).replace(/=+$/, '').replace(/\//g, '_').replace(/\+/g, '-'); // crypto-js doesn't have base64url encoding; we must manually make the tokens URL safe

  return {tokenRefresh: tokenBase + '.' + tokenRefresh + '.' + signatureRefresh, tokenAccess: tokenBase + '.' + tokenAccess + '.' + signatureAccess};
}

export default function() { // ...rest of mirage/config.js

// you may also need this in your ember-cli-build:
app.import('node_modules/crypto-js/crypto-js.js', {
  using: [
    { transformation: 'amd', as: 'CryptoJS' }
  ]
});

这个 fn 可以被配置文件中的任何路由调用: let tokens = generateTokens('thisisnotarealsecretkey');

它返回一个带有“访问”令牌和“刷新”令牌的对象,这是我们的 django jwt 设置所需的两种令牌类型。 自定义 tokenObjBase、tokenObjAccess 和 tokenObjRefresh 以满足您的后端设置。

jwt 令牌的基本结构可以在这里找到: https : //jwt.io/

总而言之,jwt 令牌具有三个字符串,由两个句点 (.) 分隔。

第一个字符串是通过 JSON.stringify() 传递的 tokenObjBase,然后转换为 base64URL 值。 URL部分很重要,因为常规 base64 编码不会删除 =、+ 和 / 字符,它们不是“网络安全”。 tokenObjBase 必须包含typalg属性,没有别的。

第二个字符串是您的“有效负载”(此处为 tokenObjAccess 或 tokenObjRefresh),通常包含用户信息(姓名、ID 等),以及表示令牌到期日期的纪元日期值。 该有效负载 obj 与第一个一样,通过 JSON.stringify() 传递,然后转换为 base64URL 值。 不要将敏感数据放在前两个对象中,它们根本没有“加密”。 任何拥有计算机和 Google 的人都可以反转 Base64 编码。

第三个字符串是 jwt “签名”。 它是通过将前两个 base64 字符串与中间的句点 (.) 连接起来,然后将它们传递给 HS256 加密算法 (HMAC-SHA256) 来创建的。

然后连接所有三个字符串(两个 base64URL 字符串和 HS256 加密字符串):base64URL(tokenObjBase) + '.' + base64URL(tokenObjPayload) + '.' + 签名HS256

希望这可以帮助任何遇到 jwt 问题的人将他们的 Mirage 用户从 Ember 应用程序中永久注销!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM