如何在ConfigureAuth之后更改Asp.Net Identity中的Cookie ExpireTimeSpan

Mog*_*og0 5 c# asp.net asp.net-identity-2

我们有一个使用Asp.Net标识的产品,我们希望cookie的到期时间是可配置的.ExpireTimeSpan当前设置在Visual Studio为新项目创建的Startup.ConfigureAuth类中.这是从启动时的配置文件中获取时间,但我们希望能够从webAPI更改此值.目前,webAPI请求可以修改配置文件,但我们需要回收应用程序池才能使其生效.

一旦服务器启动并运行,有没有办法更改此值?

我在这个主题上找到的只是这个问题ASP.NET身份变更ExpireTimeSpan在ConfigureAuth之后,但它要求一种方法来改变它为单个会话,而我想为整个服务器全局更改它.

更新:我通过浏览Katana源找到了选项似乎存储在类的公共属性中Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware但我不知道有什么方法可以从我的应用程序中获取对所使用对象的引用.

Bar*_*rry 2

这花了一些时间来弄清楚,但我相信我已经找到了正确的解决方案。这很有趣,因为我已经有了解决方案,只是没有探索范围内可用的选项。

CookieAuthenticationOptions仅提供一个钩子,即委托属性OnValidateIdentity

OnValidateIdentity每次有人登录(通过 cookie 身份验证提供程序)时都会发生这种情况,这恰好是运行一些自定义逻辑来确定新的到期时间的最佳时机。它还允许您进行全局配置。

我已经对其进行了调试,并且可以确认配置选项的值Sticks ,并保留用于将来的全局登录,直到应用程序池回收。此外,过期值覆盖适用于登录回调后经过身份验证的用户。

因此,由您决定什么逻辑决定该值,以及您是否想要在个人级别或全局级别上设置它。

这是代码示例,可帮助更好地描述这一点。

public void ConfigureAuth(IAppBuilder app) {
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
    app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
    app.CreatePerOwinContext<ApplicationGroupManager>(ApplicationGroupManager.Create);
    app.CreatePerOwinContext<ApplicationDepartmentManager>(ApplicationDepartmentManager.Create);

    app.UseCookieAuthentication(new CookieAuthenticationOptions {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Login"),
        Provider = new CookieAuthenticationProvider {

            OnValidateIdentity = delegate(CookieValidateIdentityContext context) {
                var stampValidator = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
                    validateInterval: TimeSpan.FromMinutes(15),
                    regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                    getUserIdCallback: (id) => (id.GetUserId<int>())
                );
                Task result = stampValidator.Invoke(context);

                bool found_custom_expiration = false;
                int timeout = STATIC_CONFIG.DefaultSessionExpireMinutes;
                DBHelper.Query(delegate (SqlCommand cmd) {
                    cmd.CommandText = @"
                        SELECT [value] 
                        FROM [dbo].[Vars] 
                        WHERE [FK_Department] = (
                            SELECT [Id] FROM [dbo].[ApplicationDepartments] WHERE [title] = 'Default'
                        ) 
                        AND [name]='Session Timeout'
                    ";
                    return cmd;
                }, delegate (SqlDataReader reader) {
                    timeout = reader["value"].ToInt32();
                    found_custom_expiration = true;
                    return false;
                });
                if (found_custom_expiration) {
                    // set it at GLOBAL level for all users.
                    context.Options.ExpireTimeSpan = TimeSpan.FromMinutes(timeout);
                    // set it for the current user only.
                    context.Properties.ExpiresUtc = context.Properties.IssuedUtc.Value.AddMinutes(timeout);
                }
                // store it in a claim, so we can grab the remaining time later.
                // credit: /sf/ask/1616349451/
                var expireUtc = context.Properties.ExpiresUtc;
                var claimType = "ExpireUtc";
                var identity = context.Identity;
                if (identity.HasClaim(c => c.Type == claimType)) {
                    var existingClaim = identity.FindFirst(claimType);
                    identity.RemoveClaim(existingClaim);
                }
                var newClaim = new System.Security.Claims.Claim(claimType, expireUtc.Value.UtcTicks.ToString());
                context.Identity.AddClaim(newClaim);
                return result;
            }
        },
        SlidingExpiration = true,
        // here's the default global config which was seemingly unchangeable.. 
        ExpireTimeSpan = TimeSpan.FromMinutes(STATIC_CONFIG.DefaultSessionExpireMinutes)
    });

    ApplicationHandler.OwinStartupCompleted();

}
Run Code Online (Sandbox Code Playgroud)

这绝对可以改进,仅在尚未更改时才发布更改。而且您不必使用数据库查询,它可以是 XML 读取、web.config appsetting 或其他任何内容。身份已就位...因此您甚至可以访问context.Identity并对其执行某种自定义检查ApplicationUser

所以...相关的位...

OnValidateIdentity = delegate(CookieValidateIdentityContext context) {
            var stampValidator = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                getUserIdCallback: (id) => (id.GetUserId<int>())
            );
            Task result = stampValidator.Invoke(context);

            int my_custom_minutes = 60; // run your logic here.
                // set it at GLOBAL level for all (future) users.
                context.Options.ExpireTimeSpan = TimeSpan.FromMinutes( my_custom_minutes );
                // set it for the current user only.
                context.Properties.ExpiresUtc = context.Properties.IssuedUtc.Value.AddMinutes( my_custom_minutes );

            return result;
}
Run Code Online (Sandbox Code Playgroud)