服务器端声称使用Owin身份验证进行缓存

时间:2013-10-04 23:51:59

标签: asp.net authentication claims-based-identity owin

我有一个曾经使用FormsAuthentication的应用程序,不久之前我将其切换为使用IdentityModel中的WindowsIdentityFramework,以便我可以从基于声明的身份验证中受益,但它使用和实施相当丑陋。所以现在我看OwinAuthentication

我正在查看OwinAuthenticationAsp.Net Identity框架。但Asp.Net Identity框架目前唯一的实施方法是使用EntityModel而我正在使用nHibernate。所以现在我想尝试绕过Asp.Net Identity并直接使用Owin Authentication。我终于能够使用“How do I ignore the Identity Framework magic and just use the OWIN auth middleware to get the claims I seek?”提示进行工作登录,但现在我持有声明的cookie相当大。当我使用IdentityModel时,我能够使用服务器端缓存机制来缓存服务器上的声明,而cookie只是为缓存的信息保存了一个简单的令牌。 OwinAuthentication中是否有类似的功能,或者我必须自己实现它?

我希望我会参加其中一艘船......

  1. cookie保持3KB,哦,它有点大。
  2. IdentityModel中启用类似于Owin的SessionCaching的功能,我不知道。
  3. 编写我自己的实现来缓存导致cookie膨胀的信息,看看我是否可以在应用程序启动时配置Owin时将其挂起。
  4. 我这样做是错的,有一种我没有想过的方法,或者我在Owin中滥用了一些东西。

    public class OwinConfiguration
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Application",
                AuthenticationMode = AuthenticationMode.Active,
                CookieHttpOnly = true,
                CookieName = "Application",
                ExpireTimeSpan = TimeSpan.FromMinutes(30),
                LoginPath = "/Login",
                LogoutPath = "/Logout",
                ReturnUrlParameter="ReturnUrl",
                SlidingExpiration = true,
                Provider = new CookieAuthenticationProvider()
                {
                    OnValidateIdentity = async context =>
                    {
                        //handle custom caching here??
                    }
                }
                //CookieName = CookieAuthenticationDefaults.CookiePrefix + ExternalAuthentication.ExternalCookieName,
                //ExpireTimeSpan = TimeSpan.FromMinutes(5),
            });
        }
    }
    
  5. 更新 我使用红叶提供的信息得到了预期的效果,我提出了以下逻辑...

    Provider = new CookieAuthenticationProvider()
    {
        OnValidateIdentity = async context =>
        {
            var userId = context.Identity.GetUserId(); //Just a simple extension method to get the ID using identity.FindFirst(x => x.Type == ClaimTypes.NameIdentifier) and account for possible NULLs
            if (userId == null) return;
            var cacheKey = "MyApplication_Claim_Roles_" + userId.ToString();
            var cachedClaims = System.Web.HttpContext.Current.Cache[cacheKey] as IEnumerable<Claim>;
            if (cachedClaims == null)
            {
                var securityService = DependencyResolver.Current.GetService<ISecurityService>(); //My own service to get the user's roles from the database
                cachedClaims = securityService.GetRoles(context.Identity.Name).Select(role => new Claim(ClaimTypes.Role, role.RoleName));
                System.Web.HttpContext.Current.Cache[cacheKey] = cachedClaims;
            }
            context.Identity.AddClaims(cachedClaims);
        }
    }
    

3 个答案:

答案 0 :(得分:15)

OWIN cookie身份验证中间件不支持类似功能的会话缓存。 #2不是一个选项。

#3是正确的方法。正如Prabu建议的那样,您应该在代码中执行以下操作:

OnResponseSignIn:

  • 使用唯一键(GUID)
  • 保存缓存中的context.Identity
  • 使用唯一键
  • 创建一个新的ClaimsIdentity
  • 将context.Identity替换为新身份

OnValidateIdentity:

  • 从context.Identity获取唯一的关键声明
  • 通过唯一键获取缓存标识
  • 使用缓存标识
  • 调用context.ReplaceIdentity

我打算建议你gzip cookie,但我发现OWIN已经在它的TicketSerializer中做到了。不适合你。

答案 1 :(得分:8)

Provider = new CookieAuthenticationProvider()
{
    OnResponseSignIn = async context =>
    {
        // This is the last chance before the ClaimsIdentity get serialized into a cookie. 
        // You can modify the ClaimsIdentity here and create the mapping here. 
        // This event is invoked one time on sign in. 
    }, 
    OnValidateIdentity = async context => 
    {
        // This method gets invoked for every request after the cookie is converted 
        // into a ClaimsIdentity. Here you can look up your claims from the mapping table. 
    }
}

答案 2 :(得分:1)

您可以实施IAuthenticationSessionStore将Cookie存储到数据库中。

以下用于在redis中存储Cookie的示例。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
SessionStore = new RedisSessionStore(new TicketDataFormat(dataProtector)),
LoginPath = new PathString("/Auth/LogOn"),
LogoutPath = new PathString("/Auth/LogOut"),

});

查看完整示例at here