ASP.NET 5 Identity 3用户在一段时间后退出

Dmi*_*try 2 asp.net-identity-3 asp.net-core

我使用RC1位和外部(Google)身份验证,没有Identity.EntityFramework.

在登录期间,我设置了"记住我"标志.

登录用户幸存浏览器重启(我看到cookie设置为14天后过期)和网站重启.

但是经过一段时间不活动(大约15分钟)后,无论浏览器/站点是否重​​启,刷新页面都会导致退出,日志说:

info: Microsoft.AspNet.Authentication.Cookies.CookieAuthenticationMiddleware:
    AuthenticationScheme: Microsoft.AspNet.Identity.Application signed out.
    AuthenticationScheme: Microsoft.AspNet.Identity.External signed out.
    AuthenticationScheme: Microsoft.AspNet.Identity.TwoFactorUserId signed out.
Run Code Online (Sandbox Code Playgroud)

这看起来像以前的ASP中的"会话",但我不在这里使用任何会话.

这是我的本地开发者机器,没有IIS,直接将Kestrel连接到5000端口,所以这不是数据保护问题

为什么用户被迫退出?

更新:我的Startup.cs文件:

public void ConfigureServices(IServiceCollection services) 
{
    ....
    var identityBuilder = services
        .AddIdentity<User, UserRole>(options =>
        {
            options.User.AllowedUserNameCharacters = null;
            options.Cookies.ApplicationCookie.LoginPath = "/user/login";
            options.Cookies.ApplicationCookie.LogoutPath = "/user/logout";
        });
    identityBuilder.Services
        .AddScoped<IUserStore<User>, SportCmsDb>(serviceProvider => serviceProvider.GetService<SportCmsDb>())
        .AddScoped<IRoleStore<UserRole>, SportCmsDb>(serviceProvider => serviceProvider.GetService<SportCmsDb>());
    identityBuilder
        .AddDefaultTokenProviders();
    ....

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{
    ....
    app.UseIdentity();
    app.UseGoogleAuthentication(options =>
    {
        options.ClientId = Configuration["OAuth:Google:ClientId"];
        options.ClientSecret = Configuration["OAuth:Google:Secret"];
    });
    ....
Run Code Online (Sandbox Code Playgroud)

SportCmsDbDbContext,也实现了IUserStore<User>,IUserLoginStore<User>,IUserEmailStore<User>,IRoleStore<UserRole>,IUserClaimStore<User>

更新2

我启用了详细的(调试)日志记录,并发现当用户退出时 - 在此之前我IUserStore<User>.FindByIdAsync被调用.使用实际/现有用户ID,并返回正确的非空用户函数.一切似乎都很好.但我的db-db User被"拒绝"并被迫退出.没有其他日志消息可以揭示原因/何处.

Dmi*_*try 7

哇,我解决了!

TL; DR

我需要IUserSecurityStampStore<User>在我的自定义UserManager(aka SportCmsDb)上实现.

细节

AddIdentity调用期间(在Startup.cs ConfigureServices方法中)IdentityOptions配置默认实例IdentityCookieOptions.在(of)类型的IdentityCookieOptions实例的构造函数中创建使用设置为静态方法的处理程序.ApplicationCookieCookieAuthenticationOptionsCookieAuthenticationEvents.OnValidatePrincipal SecurityStampValidator.ValidatePrincipalAsync

UseIdentity呼叫(在Startup.cs Configure方法)CookieAuthenticationMiddleware配置成与IdentityOptions.Cookies.ApplicationCookie选项.

CookieAuthenticationHandler(由...创建CookieAuthenticationMiddleware)在其HandleAuthenticateAsync方法中从cookie读取票证并调用Options.Events.ValidatePrincipal处理程序进行验证.

有效地,SecurityStampValidator.ValidatePrincipalAsync被称为.此方法检查自cookie发出以来已经过足够的时间(默认为30分钟)并调用ISecurityStampValidator.validateAsync(第81-82行).

默认实现ISecurityStampValidatorSecurityStampValidator<TUser>.它调用SignInManager<TUser>.ValidateSecurityStampAsync并返回null时- 拒绝主体并强制用户注销(第30-40行).

SignInManager<TUser>在其ValidateSecurityStampAsync方法中尝试从中读取安全标记,User如果不能(如果UserManager<User>不支持此接口)或者标记与保存的标记(在cookie中)不匹配则返回null .

我的自定义UserManager没有实现IUserSecurityStampStore<User>.答对了.