首页 > 解决方案 > 刷新身份验证 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();
    }
}

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

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

解决方案


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

可能它会以某种方式帮助你。


推荐阅读