c# - 刷新身份验证 cookie 以避免注销
问题描述
我正在开发一个带有 Identity 的 ASP.NET Core 2.0 应用程序来管理用户连接。
我有一些自定义 Manager、Store 和 Providers 来满足我的应用程序的需要:
services.AddIdentity<Utilisateur, Profil>().AddUserManager<CustomUserManager<Utilisateur>>().AddRoleManager<CustomRoleManager>().AddDefaultTokenProviders();
services.AddTransient<IUserStore<Utilisateur>, UserStore>();
services.AddTransient<IRoleStore<Profil>, ProfileStore>();
services.AddTransient<IPermissionProvider, PermissionProvider>();
我已经为身份验证设置了应用程序 cookie:
app.UseAuthentication();
和
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
// If the LoginPath isn't set, ASP.NET Core defaults the path to /Account/Login.
options.LoginPath = new PathString("/Connexion/Login");
options.LogoutPath = new PathString("/Connexion/SignedOut");
// If the AccessDeniedPath isn't set, ASP.NET Core defaults the path to /Account/AccessDenied.
options.AccessDeniedPath = new PathString("/Connexion/AccessDenied");
options.SlidingExpiration = true;
});
问题是用户在30分钟后自动断开连接,即使他没有空闲并且此时正在使用该应用程序。
如何刷新或重新创建身份验证 cookie 以避免此问题?
我试图创建一种方法来刷新 cookie,但它似乎不能很好地工作......即使这样,用户也会断开连接。
[HttpPost]
[RefreshLogin]
[RequiresPermission("Pages.Modification")]
public IActionResult SavePagesOrder()
{...}
和方法:
public class RefreshLoginAttribute : Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute
{
public override async Task OnActionExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext context, Microsoft.AspNetCore.Mvc.Filters.ActionExecutionDelegate next)
{
await context.HttpContext.RefreshLoginAsync();
await next();
}
}
你有想法解决我的问题吗?
解决方案
这是我与 IdentityServer 4 一起使用的解决方案。对不起,它可能很乱,但我希望你能抓住重点。每次验证主体时,您都可以将访问和刷新令牌重写为 cookie。
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = async x =>
{
var now = DateTimeOffset.UtcNow;
var timeElapsed = now.Subtract(x.Properties.IssuedUtc.Value);
var timeRemaining = x.Properties.ExpiresUtc.Value.Subtract(now);
if (timeElapsed > timeRemaining)
{
var discoveryResponse = await DiscoveryClient.GetAsync(gatewaySettings.IdentitySeverAddress);
if (discoveryResponse.IsError)
{
throw new Exception(discoveryResponse.Error);
}
var identity = (ClaimsIdentity) x.Principal.Identity;
var accessTokenClaim = identity.FindFirst("access_token");
var refreshTokenClaim = identity.FindFirst("refresh_token");
var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, "MyApi", "secret");
var refreshToken = refreshTokenClaim.Value;
var tokenResponse = await tokenClient.RequestRefreshTokenAsync(refreshToken);
if (!tokenResponse.IsError)
{
identity.RemoveClaim(accessTokenClaim);
identity.RemoveClaim(refreshTokenClaim);
identity.AddClaims(new[]
{
new Claim("access_token", tokenResponse.AccessToken),
new Claim("refresh_token", tokenResponse.RefreshToken)
});
x.ShouldRenew = true;
}
}
}
};
})
可能它会以某种方式帮助你。
推荐阅读
- python - 根据值/数据类型(并保留范围)在 matplotlib 颜色图上设置特定的像素颜色
- x509certificate - 使用非对称密钥的安全消息传输
- amazon-web-services - 如何通过 Application Load Balancer 异步调用 Lambda?(AWS)
- python - 仅返回尚未成为患者关系一部分的用户
- javascript - 如何从javascript中删除只读属性
- angular - 角度类型“未定义”不可分配给类型
- html - 如何在 Flutter 中解析带有行跨度的 HTML 表格?
- collections - 删除 ATL ATLAS 转换语言中每个集合的重复项
- arduino - 由 ESP32 (Arduino) 控制的电机驱动
- apache-kafka - 将 confluent.cloud(Kafka) 中的工作转换为弹性云