我希望能够更改 JWT 密钥,并且不会导致登录用户出现浏览器错误。
目前,如果用户登录并且 JWT 密钥发生更改,他们的浏览器会抛出错误。这只能通过用户手动从浏览器中删除 cookie 来解决。
server.express.use((req, res, next) => {
const { token } = req.cookies;
if (token) {
const { userId } = jwt.verify(token, process.env.APP_SECRET);
req.userId = userId;
}
next();
});
Run Code Online (Sandbox Code Playgroud)
我可以在上面的代码中添加什么,以便如果 jwt.verify 失败,用户被迫再次登录,这将根据新的 jwt 密钥设置新的 cookie?
我正在尝试使用 jsonwebtoken NPM 包来验证 Azure Active Directory 颁发的 JWT 令牌。以下是我编写的node.js代码:
var jwt = require('jsonwebtoken');
var token = '<valid JWT token>';
var x5cString = '<x5cSTring>';
var publicKey = '-----BEGIN CERTIFICATE-----\n' + x5cString + '\n-----END CERTIFICATE-----';
var verifiedToken = jwt.verify(token, publicKey) //, verifyOptions);
Run Code Online (Sandbox Code Playgroud)
请注意,在上面的代码中,我使用了https://login.microsoftonline.com/common/discovery/keys中的实际 x5c 字符串。这工作正常,我得到了预期的结果。但是,作为公钥的 X5C 字符串不断变化。我想了解如何自动获取此公钥。
我在 Jsonwebtoken NPM 包网站上找到了一些示例代码。在此代码中,signingKey 是我想要的。以下是代码。
var jwksClient = require('jwks-rsa');
var client = jwksClient({
jwksUri: 'https://login.microsoftonline.com/common/discovery/keys'
});
function getKey(header, callback){
client.getSigningKey(header.kid, function(err, key) {
var signingKey = key.publicKey || key.rsaPublicKey;
callback(null, signingKey);
}); …Run Code Online (Sandbox Code Playgroud) 我正在创建基于 jwt 令牌的会话,并使用 httpOnly 参数将该令牌传递给客户端,但 cookie 在浏览器中可见,这是照片:
这是代码
const token = jwt.sign({id :payload}, process.env.SECRET, {
expiresIn: 10
})
console.log(token)
res.cookie('token', token, {
httpOnly: true
});
Run Code Online (Sandbox Code Playgroud)
为什么“token cookie”可见是什么问题?
更新我正在尝试使用下面的 x5c / x509 公钥值以编程方式验证 JWT 访问令牌。我可以通过将令牌和 x5c 值插入外部网站来实现此功能,但不能使用 JavaScript / jsrsasign 以编程方式进行。任何建议将不胜感激。
以下是 OIDC 提供商的公共 JSON Web 密钥集。
{
"keys": [
{
"kty": "RSA",
"kid": "server",
"use": "sig",
"alg": "RS256",
"n": "gLZO9w1OT_SWO-KbqiU0k3HevHggiY70XbDqgE1YaqhD-MwFUWNudExzF3oB28NYWYg5v6CJY0F-pUNtgukDM6ARDlh0n4xIvBRlnUnCTCx7pYOjpfXbTv49tlXmh4-ddh8EeQBLrF92u5UYs0tnZd8843mvYWohUNH1X1hM08-hpk7xCiy4XdwbeSlH757D2d5E0J0dGtZ744-dB2ZRCw2Vms_mk4Yyny4ifx2j2gIhikbb7WGmsTR2sWrtuhgZ_EBNUvrD0O54xbhQNTTFQ1pi9UZxo_gYc5Gp5fLcSOK6SDBKXbDS5hhy1vFyoa0xdgFv-xpem7YzmkKqzfjC9w",
"e": "AQAB",
"x5c": [
"MIIDMDCCAhigAwIBAgIEFIopYzANBgkqhkiG9w0BAQsFADBaMQkwBwYDVQQGEwAxCTAHBgNVBAgTADEJMAcGA1UEBxMAMQkwBwYDVQQKEwAxCTAHBgNVBAsTADEhMB8GA1UEAxMYZmNpc2Rldi5pY2UuaWJtY2xvdWQuY29tMB4XDTE4MTAwMTE4MTYyOFoXDTI4MDkyODE4MTYyOFowWjEJMAcGA1UEBhMAMQkwBwYDVQQIEwAxCTAHBgNVBAcTADEJMAcGA1UEChMAMQkwBwYDVQQLEwAxITAfBgNVBAMTGGZjaXNkZXYuaWNlLmlibWNsb3VkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIC2TvcNTk/0ljvim6olNJNx3rx4IImO9F2w6oBNWGqoQ/jMBVFjbnRMcxd6AdvDWFmIOb+giWNBfqVDbYLpAzOgEQ5YdJ+MSLwUZZ1Jwkwse6WDo6X1207+PbZV5oePnXYfBHkAS6xfdruVGLNLZ2XfPON5r2FqIVDR9V9YTNPPoaZO8QosuF3cG3kpR++ew9neRNCdHRrWe+OPnQdmUQsNlZrP5pOGMp8uIn8do9oCIYpG2+1hprE0drFq7boYGfxATVL6w9DueMW4UDU0xUNaYvVGcaP4GHORqeXy3EjiukgwSl2w0uYYctbxcqGtMXYBb/saXpu2M5pCqs34wvcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdtN9znA9a6luPAQurcQn8kJBlllslRWsNPMhPWpMtYaMLx6JhmDICGbaYZBGUboedwnUaEk6tE2b+EVlUE/tnaKVJms2cmCCFExQQrTHmRfFI/Vi/esVqAnz1E2dB61LMnQ2AeebXAZ/C7hRt1uXVboXr5Zokppr4FRS9QsjSK4dhcXxhfglTKJOPZ4dkSexhe6hybpL8XdGhoyf2SyNXCy5iYX0zQ5BmJaLimOcJyasZ/A7/YgsVbQyAe6Ubno6/sIUuOZ+J+snZsBSLViqcftGVPUkIWamv/yNQcEJrDWa4C+sr+9Yb7uFjuj4gDY0jvGkGmu53g0K8Vks+IfAdQ=="
],
"x5t#S256": "nTAGJuFFrm-vNBdkLVNmuePwTmlXr0T87IppgJPRT9k"
}
]
}
Run Code Online (Sandbox Code Playgroud)
这是我用来通过 x5c 验证访问令牌的代码。我的印象是我应该使用 x5c 值,但如果有其他方法对我来说没问题。只需要使用键下的上述值来验证令牌即可。
// break line every 64 characters.
x5cValue = x5cValue.replace(/(.{64})/g, "$1\n");
// base64 decode
var x5cValueAtob = atob(x5cValue);
// Add Begin / END certificate
x5cValue = "-----BEGIN CERTIFICATE-----\n" + x5cValueAtob + "\n-----END …Run Code Online (Sandbox Code Playgroud) 假设我有一个 API 端点,只有拥有有效访问令牌的授权用户才能访问其资源,与此类似:
from flask_restful import Resource
from flask_jwt_extended import jwt_required
class Collection(Resource):
@jwt_required
def get(self):
"""
GET response implementation here.
"""
# Queries and logic here
data = 10
if(is_everythig_ok()):
return {"data": data}, 200
else:
return {"message":"Failed to get data."}, 400
Run Code Online (Sandbox Code Playgroud)
假设有一个 LoginUser 端点返回有效的 access_token,我如何编写一些单元测试来重现两个状态代码(200 表示成功,400 表示失败),同时用户拥有有效的访问令牌,并且用户具有有效的访问令牌时的情况没有有效的 access_token。
我已经用 POSTMAN 测试了我的端点,看起来没问题,但我还需要编写一些单元测试来证明。那么,这样做的正确方法是什么?
我已经尝试阅读文档并尝试更改默认行为https://flask-jwt-extended.readthedocs.io/en/latest/changing_default_behavior.html来处理错误(该链接显示了如何处理过期的令牌)和在谷歌中搜索我能做的每个关键字组合中的所有内容,但似乎没有人有这方面的例子。
我尝试使用 @jwt.revoked_token_loader 来处理 RevokedTokenError 但它似乎不起作用,因为我像这样应用它
@jwt.revoked_token_loader
def revoked_token_response(revoked_token):
jwtkn = revoked_token['jti']
return jsonsify({
'msg': 'token {} already been revoked!'.format(jwtkn)
)}, 401
Run Code Online (Sandbox Code Playgroud)
实际上,我不知道处理过期令牌的链接上的示例如何具有“expired_token”参数,这种自我声明是否像我上面在“revoked_token”上所做的那样?据我所知,“jti”就像flask-jwt-extended包中的默认值,因为每当我不使用它时我都会看到错误(在我的数据库中,它是不同的,但根本没有问题。
我尝试按照本教程进行操作,在我这边效果很好(以及他的原始代码源),但我发现这个在撤销令牌上也没有捕获异常https://codeburst.io/jwt-authorization-烧瓶内-c63c1acf4eeb
我使用邮递员,如果基于教程链接,这就是我如何得到这个
i do login
i use the access token generated to access protected routes ('/secrets')
i do logout
i use again the access token generated to access protected routes
Run Code Online (Sandbox Code Playgroud)
在最后一个之后,我在服务器端(ide)收到此错误:
....flask_jwt_extended\utils.py", line 216, in verify_token_not_blacklisted
raise RevokedTokenError('Token has been revoked')
flask_jwt_extended.exceptions.RevokedTokenError: Token has been revoked
127.0.0.1 -- [02/Jul/2019 22:25:26] "GET /secrets HTTP/1.1" 500 …Run Code Online (Sandbox Code Playgroud) 目前我已经实现了 jwt 防护,它工作得很好,使用 Passport,jwt 正在验证颁发的令牌,我可以通过 @Request 通过 req.user 查看用户,在实现基于角色的身份验证作为已经工作的附加组件后出现问题JWT 的守卫。
我遵循了 Nestjs.com 提供的指导,但没有帮助。 https://docs.nestjs.com/guards
基本角色配置:
角色装饰器.ts
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
Run Code Online (Sandbox Code Playgroud)
角色.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = …Run Code Online (Sandbox Code Playgroud) eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjIsImlhdCI6MTU2ODY1NjI1OX0.E2TNtWjqyPC-4myEom6leLJgE96ZlQOq0-mcBr3p5QU
如果我们将使用 JsonWebToken 从我的代码生成的令牌放置在 Jwt.io 站点中,即使我没有提供要验证的秘密,它也会立即解码。我不知道为什么会显示。有人能解释一下原因吗?
--那么Jwt中SECRET的目的是什么?
我从 Web 服务获取 json Web 令牌,解码后返回如下内容:
\n{\n "exp": 1572468916,\n "iat": 1572468316,\n "iss": "https://ccc/auth/realms/yyy",\n "aud": "xxx-api",\n [...]\nRun Code Online (Sandbox Code Playgroud)\n根据第 2 节终端学, NumericDate 数据类型对应于“自纪元以来的秒数”
\n所以我将它转换为 JavaScript 日期,如下所示:
\nnew Date(1572468316 * 1000)\nDate Wed Oct 30 2019 17:45:16 GMT-0300 (Argentina Standard Time)\nRun Code Online (Sandbox Code Playgroud)\n问题是我当前的时间是:
\nnew Date()\nDate Wed Oct 30 2019 14:45:19 GMT-0300 (Argentina Standard Time)\nRun Code Online (Sandbox Code Playgroud)\n实际上,当前时间是返回的时间new Date()(即 14:45,不是 17:45)
我猜这与 GMT 有关,但我不知道如何处理它。
\n我想将 iat 属性(显然还有 exp 属性)转换为当前时间,以便将其进行比较以new Date()查明令牌是否已过期。
那么如何将 NumericDate 从 …
切换到新的开发系统后出现依赖错误(使用轮廓播放应用程序)。
sbt.版本=1.3.3
在build.sbt中:
resolvers += Resolver.jcenterRepo
resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
Run Code Online (Sandbox Code Playgroud)
[error] Error downloading com.atlassian.jwt:jwt-api:2.0.5
[error] Not found
[error] Not found
[error] not found: /Users/robert/.ivy2/local/com.atlassian.jwt/jwt-api/2.0.5/ivys/ivy.xml
[error] not found: https://repo1.maven.org/maven2/com/atlassian/jwt/jwt-api/2.0.5/jwt-api-2.0.5.pom
Run Code Online (Sandbox Code Playgroud) jwt ×10
node.js ×4
javascript ×3
cookies ×2
bearer-token ×1
datetime ×1
encryption ×1
express ×1
flask ×1
gmt ×1
jwk ×1
nestjs ×1
python ×1
sbt ×1
silhouette ×1
token ×1
unit-testing ×1
x509 ×1