如何在ConfigureAuth

时间:2015-05-11 14:18:09

标签: c# asp.net asp.net-identity-2

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

我已经对其进行了调试,并且可以确认配置选项支持的值,并且在将来登录全局之前保留 。此外,在签名回调后,过期的值覆盖适用于经过身份验证的用户。

因此,由您决定价值的逻辑取决于您,以及您是要在每个人级别还是全局级别设置该值。

以下是帮助描绘更好图片的代码示例..

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: https://stackoverflow.com/questions/23090706/how-to-know-when-owin-cookie-will-expire
                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();

}

只有在尚未更改的情况下才能进行更改。而且您不必使用数据库查询,它可以是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;
}