我在 .Net5 应用程序上实现了 Identity Core,以处理 4 个端点的登录、注销、注册和刷新。
当我调用注销端点并发送刷新令牌时,它会从数据库中删除刷新令牌,以便用户无法刷新访问令牌。
问题是我仍然可以使用访问令牌来调用应用程序的端点并获取授权,直到其定期到期。
我想知道是否有一种方法可以在注销后使访问令牌失效,而无需等待过期。
这是我在启动时的配置服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "AuthenticationAndAuthorizationAPI", Version = "v1" });
});
services.AddIdentityCore<User>(o =>
{
o.User.RequireUniqueEmail = true;
o.Password.RequireDigit = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequireUppercase = false;
o.Password.RequiredLength = 0;
}).AddEntityFrameworkStores<AuthenticationDbContext>();
AuthenticationConfiguration authenticationConfiguration = new();
_configuration.Bind("Authentication", authenticationConfiguration);
services.AddSingleton(authenticationConfiguration);
services.AddEntityFrameworkNpgsql().AddDbContext<AuthenticationDbContext>(options =>
options.UseNpgsql(_configuration.GetConnectionString("DBConnection")));
services.AddSingleton<AccessTokenGenerator>();
services.AddSingleton<RefreshTokenGenerator>();
services.AddSingleton<RefreshTokenValidator>();
services.AddScoped<Authenticator>();
services.AddSingleton<TokenGenerator>();
services.AddScoped<IRefreshTokenRepository, DatabaseRefreshTokenRepository>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authenticationConfiguration.AccessTokenSecret)),
ValidIssuer = authenticationConfiguration.Issuer,
ValidAudience = authenticationConfiguration.Audience,
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ClockSkew = TimeSpan.Zero
};
});
}
您不能“使”JWT 令牌“无效” - 您在这里有几个选项。
有一些解决方法,例如缩短令牌过期时间,以便缩短攻击窗口,或者在应用程序注销时删除客户端令牌,仍然可以解决“攻击者”提前窃取密钥的问题。
要强制真正的服务器端失效,您可以使用lastLogoutTs
值,每次注销时都会更新。一旦用户注销,他们的lastLogoutTs
数据库中的值发生更改,这意味着 JWT 令牌不再有效,并且无法验证访问权限。这显然意味着您在每次注销时都会访问数据库,但实际上并不像听起来那么糟糕,因为您可能会访问数据库来加载用户以将其注销。
或者,您可以保留一个,而不是额外的字段blocklist
内存数据库中的表,允许您在 Redis、Memcached 等密钥上设置过期时间。该表将存储已注销、尚未达到令牌过期日期的用户的访问令牌。例如,在 Redis 中,您可以使用EXPIRE https://redis.io/commands/expire自动删除访问令牌,同时速度也非常快(因为它是内存数据库)。
对于不得使用数据库(想不出任何数据库)的解决方案,JWT 不合适,OAuth 2.0 之类的东西会更好(最终将注销逻辑卸载给 Google、Apple 等提供商)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)