【问题标题】:Refresh Identity authentification cookie to avoid logout刷新身份验证 cookie 以避免注销
【发布时间】:2019-04-04 18:02:02
【问题描述】:

我正在开发一个带有 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();
    }
}

您有解决我问题的想法吗?

【问题讨论】:

    标签: c# asp.net-identity asp.net-core-2.0 session-cookies


    【解决方案1】:

    这是我在 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;
                                    }
                                }
                            }
                        };
                    })
    

    也许它会以某种方式帮助你。

    【讨论】:

    • 是的,解决我的问题似乎是个好主意。但是我没有IdentiyServer,所以Visual Studio 找不到DiscoveryClient 和TokenClient。使用您的解决方案,我尝试了if (timeElapsed &gt; timeRemaining) { await x.HttpContext.RefreshLoginAsync(); } 之类的方法,我不知道它是否会起作用,但我会像这样测试它。
    • 你可以使用你想重新发行的token。 IdentityServer 只是变体之一。
    猜你喜欢
    • 2022-08-09
    • 1970-01-01
    • 2015-05-25
    • 2017-08-20
    • 2011-06-03
    • 2010-11-07
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多