- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在开发一个使用 JWT token 身份验证的 API。我在其背后创建了一些逻辑来使用验证码等更改用户密码。
一切正常,密码已更改。但这里有一个问题:即使用户密码已更改并且我在验证时获得了新的 JWT token ...旧 token 仍然有效。
关于如何在密码更改后刷新/使 token 无效的任何提示?
编辑:自从我听说您实际上无法使 JWT token 无效后,我就知道如何去做了。我的想法是创建一个新的用户列,其中包含类似“accessCode”的内容,并将该访问代码存储在 token 中。每当我更改密码时,我也会更改 accessCode(类似于 6 位随机数),并且在执行 API 调用时对该 accessCode 进行检查(如果 token 中使用的 accesscode 与数据库中的 accesscode 不匹配 -> 未授权返回)。
你们认为这是一个好方法还是有其他方法?
最佳答案
撤销/无效的最简单方法可能只是删除客户端上的 token 并祈祷没有人会劫持和滥用它。
您使用“accessCode”列的方法可行,但我会担心性能。
另一种可能是更好的方法是将某些数据库中的 token 列入黑名单。我认为 Redis 是最好的选择,因为它支持通过 EXPIRE
超时,因此您只需将其设置为与 JWT token 中相同的值即可。当 token 过期时,它将自动删除。
您将需要快速响应时间,因为您必须在每个需要授权的请求上检查 token 是否仍然有效(不在黑名单或不同的 accessCode 中),这意味着使用无效 token 调用您的数据库每个请求。
有些人建议使用长生命周期的刷新 token 和短生命周期的访问 token 。您可以将访问 token 设置为 10 分钟后过期,当密码更改时, token 仍将有效 10 分钟,但随后将过期,您将必须使用刷新 token 来获取新的访问 token 。就个人而言,我对此有点怀疑,因为刷新 token 也可以被劫持:http://appetere.com/post/how-to-renew-access-tokens然后您还需要一种使它们无效的方法,因此最终您无法避免将它们存储在某个地方。
您使用的是 ASP.NET Core,因此您需要找到一种方法来添加自定义 JWT 验证逻辑以检查 token 是否已失效。这可以通过 extending default JwtSecurityTokenHandler
来完成并且您应该能够从那里调用 Redis。
在配置服务中添加:
services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect("yourConnectionString"));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.SecurityTokenValidators.Clear();
// or just pass connection multiplexer directly, it's a singleton anyway...
opt.SecurityTokenValidators.Add(new RevokableJwtSecurityTokenHandler(services.BuildServiceProvider()));
});
创建你自己的异常:
public class SecurityTokenRevokedException : SecurityTokenException
{
public SecurityTokenRevokedException()
{
}
public SecurityTokenRevokedException(string message) : base(message)
{
}
public SecurityTokenRevokedException(string message, Exception innerException) : base(message, innerException)
{
}
}
public class RevokableJwtSecurityTokenHandler : JwtSecurityTokenHandler
{
private readonly IConnectionMultiplexer _redis;
public RevokableJwtSecurityTokenHandler(IServiceProvider serviceProvider)
{
_redis = serviceProvider.GetRequiredService<IConnectionMultiplexer>();
}
public override ClaimsPrincipal ValidateToken(string token, TokenValidationParameters validationParameters,
out SecurityToken validatedToken)
{
// make sure everything is valid first to avoid unnecessary calls to DB
// if it's not valid base.ValidateToken will throw an exception, we don't need to handle it because it's handled here: https://github.com/aspnet/Security/blob/beaa2b443d46ef8adaf5c2a89eb475e1893037c2/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs#L107-L128
// we have to throw our own exception if the token is revoked, it will cause validation to fail
var claimsPrincipal = base.ValidateToken(token, validationParameters, out validatedToken);
var claim = claimsPrincipal.FindFirst(JwtRegisteredClaimNames.Jti);
if (claim != null && claim.ValueType == ClaimValueTypes.String)
{
var db = _redis.GetDatabase();
if (db.KeyExists(claim.Value)) // it's blacklisted! throw the exception
{
// there's a bunch of built-in token validation codes: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/7692d12e49a947f68a44cd3abc040d0c241376e6/src/Microsoft.IdentityModel.Tokens/LogMessages.cs
// but none of them is suitable for this
throw LogHelper.LogExceptionMessage(new SecurityTokenRevokedException(LogHelper.FormatInvariant("The token has been revoked, securitytoken: '{0}'.", validatedToken)));
}
}
return claimsPrincipal;
}
}
然后在您更改密码或使用 token 的 jti 设置 key 以使其无效时。
限制!JwtSecurityTokenHandler
中的所有方法都是同步的,如果您想要进行一些 IO 绑定(bind)调用,这很糟糕,理想情况下,您可以使用 await db.KeyExistsAsync(claim.Value)
在那里。此处跟踪此问题:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/468不幸的是,自 2016 年以来没有对此进行更新:(
这很有趣,因为验证 token 的函数是异步的:https://github.com/aspnet/Security/blob/beaa2b443d46ef8adaf5c2a89eb475e1893037c2/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs#L107-L128
临时解决方法是扩展 JwtBearerHandler
并将 HandleAuthenticateAsync
的实现替换为 override
而不调用基础,这样它会调用你的异步验证版本。然后使用 this logic添加它。
最受推荐和积极维护的 C# Redis 客户端:
可能会帮助您选择一个:Difference between StackExchange.Redis and ServiceStack.Redis
StackExchange.Redis has no limitations and is under the MIT license.
所以我会选择 StackExchange 的
关于c# - 如何在更改密码后使 token 失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52476325/
我正在开发一个应用程序,它使用 OAuth - 基于 token 的身份验证。 考虑到我们拥有访问和刷新 token ,这就是流程的样子。 Api call -> intercepter append
如何取消标记此代码的输出? 类(class)核心: def __init__(self, user_input): pos = pop(user_input) subject = ""
当我使用命令 kubectl 时与 --token标记并指定 token ,它仍然使用 kubeconfig 中的管理员凭据文件。 这是我做的: NAMESPACE="default" SERVICE
我正在制作 SPA,并决定使用 JWT 进行身份验证/授权,并且我已经阅读了一些关于 Tokens 与 Cookies 的博客。我了解 cookie 授权的工作原理,并了解基本 token 授权的工作
我正在尝试从应用服务获取 Google 的刷新 token ,但无法。 日志说 2016-11-04T00:04:25 PID[500] Verbose Received request: GET h
我正在开发一个项目,只是为了为 java 开发人员测试 eclipse IDE。我是java新手,所以我想知道为什么它不起作用,因为我已经知道该怎么做了。这是代码: public class ecli
我正在尝试使用 JwtSecurityTokenHandler 将 token 字符串转换为 jwt token 。但它出现错误说 IDX12709: CanReadToken() returned
我已阅读文档 Authentication (来自 Facebook 的官方)。我仍然不明白 Facebook 提供的这三种访问 token 之间的区别。网站上给出了一些例子,但我还是不太明白。 每个
我的部署服务器有时有这个问题,这让我抓狂,因为我无法在本地主机中重现,我已经尝试在我的 web.config 中添加机器 key ,但没有成功远。 它只发生在登录页面。 我的布局:
我已经设法获得了一个简单的示例代码,它可以创建一个不记名 token ,还可以通过阅读 stackoverflow 上的其他论坛来通过刷新 token 请求新的不记名 token 。 启动类是这样的
如果我有以前的刷新 token 和使用纯 php 的访问 token ,没有 Google Api 库,是否可以刷新 Google Api token ?我在数据库中存储了许多用户刷新和访问 toke
我通过 Java 应用程序使用 Google 电子表格时遇到了问题。我创建了应用程序,该应用程序运行了 1 年多,没有任何问题,我什至在 Create Spreadsheet using Google
当我有一个有效的刷新 token 时,我正在尝试使用 Keycloak admin REST API 重新创建访问 token 。 我已经通过调用 POST/auth/realms/{realm}/p
我正在尝试让第三方 Java 客户端与我编写的 WCF 服务进行通信。 收到消息时出现如下异常: Cannot find a token authenticator for the 'System.I
在尝试将数据插入到我的 SQl 数据库时,我收到以下错误 System.Data.SqlServerCe.SqlCeException: There was an error parsing the
使用数据库 session token 系统,我可以让用户使用用户名/密码登录,服务器可以生成 token (例如 uuid)并将其存储在数据库中并将该 token 返回给客户端。其上的每个请求都将包
我最近注册了 Microsoft Azure 并设置了认知服务帐户。使用 Text Translation API Documentation 中的说明我能够使用 interactive online
我使用 IAntiforgery API 创建了一个 ASP.Net Core 2 应用程序。 这提供了一种返回 cookie 的方法。 客户端获取该 cookie,并在后续 POST 请求中将该值放
我正在使用 spacy 来匹配某些文本(意大利语)中的特定表达式。我的文本可以多种形式出现,我正在尝试学习编写一般规则的最佳方式。我有如下 4 个案例,我想写一个适用于所有案例的通用模式。像这样的东西
我无法理解 oauth 2.0 token 的原则处理。 我的场景是,我有一个基于 web 的前端后端系统,带有 node.js 和 angular 2。用户应该能够在此站点上上传视频。然后创建一些额
我是一名优秀的程序员,十分优秀!