![](/img/trans.png)
[英]Ember destroyRecord (or deleteRecord then save) using ember-cli-mirage failing
[英]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 必须包含typ
和alg
属性,没有别的。
第二个字符串是您的“有效负载”(此处为 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.