我有一个曾经使用FormsAuthentication
的应用程序,不久前我将其切换为使用WindowsIdentityFramework
的IdentityModel
,以便我可以从基于声明的身份验证中受益,但是使用和实现起来相当丑陋。所以现在我正在看OwinAuthentication
.
我正在研究OwinAuthentication
和Asp.Net Identity
框架。但是Asp.Net Identity
框架目前唯一的实现使用EntityModel
而我正在使用nHibernate
。所以现在我想尝试绕过Asp.Net Identity
,直接使用Owin Authentication
。我终于能够使用"我如何忽略身份框架魔法,只使用 OWIN 身份验证中间件来获取我寻求的声明?"中的提示获得工作登录,但现在我的 cookie 保存声明相当大。当我使用IdentityModel
时,我能够使用服务器端缓存机制,该机制在服务器上缓存声明,并且cookie只是保存缓存信息的简单令牌。OwinAuthentication
中是否有类似的功能,还是我必须自己实现它?
我希望我会在其中一条船上...
- 饼干保持为3KB,哦,它有点大。
- 启用类似于我不知道的
Owin
IdentityModel
的会话缓存的功能。 - 编写我自己的实现来缓存导致 cookie 膨胀的信息,看看当我在应用程序启动时配置
Owin
时是否可以挂接它。 -
我做错了这一切,有一种我没有想到的方法,或者我在
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), }); } }
更新我能够使用宏业提供的信息获得所需的效果,我想出了以下逻辑......
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);
}
}
OWIN cookie 身份验证中间件尚不支持会话缓存之类的功能。 #2 不是一个选项。
#3 是正确的方法。正如 Prabu 所建议的,您应该在代码中执行以下操作:
OnResponseSignIn:
- 保存上下文。缓存中具有唯一键 (GUID( 的标识
- 创建嵌入唯一键的新声明标识
- 替换上下文。使用新身份标识
OnValidateIdentity:
- 从上下文中获取唯一键声明。身份
- 通过唯一键获取缓存的标识
- 调用上下文。将标识替换为缓存的标识
我打算建议你压缩cookie,但我发现OWIN已经在其TicketSerializer中这样做了。不适合您。
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.
}
}
您可以实现 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"),
});
在此处查看完整示例