我将 ASP.NET Identity 2.0 与我自己的自定义存储一起使用。我注意到多次调用存储操作效率低下,尤其是在登录时。
这是我的登录代码(几乎包含在默认模板中):
[AllowAnonymous]
public async Task<ActionResult> LogIn(LogInModel model)
{
if(model!=null && (!string.IsNullOrEmpty(model.Email) || !string.IsNullOrEmpty(model.Password)))
{
model.DisplayValidationMessages=true;
if(ModelState.IsValid)
{
BaseApplicationUser user=await UserManager.FindAsync(model.Email,model.Password);
if(user!=null)
{
await SignInAsync(user,model.RememberMe);
return Redirect((model.ContinueUrl??"/")+"#"+model.State.UrlEncode());
}
model.ErrorMessage="Those credentials are invalid, please try again";
}
}
return View(model);
}
protected async Task SignInAsync(BaseApplicationUser user,bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
AuthenticationManager.SignIn(
new AuthenticationProperties { IsPersistent=isPersistent },
await user.GenerateUserIdentityAsync(UserManager)
);
}
我的用户扩展如下:
public class BaseApplicationUser:User
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<BaseApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
ClaimsIdentity userIdentity=await manager.CreateIdentityAsync(this,DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
配置身份验证:
public void ConfigureAuth(IAppBuilder app)
{
[...]
// Configure the db context and user manager to use a single instance per request
//app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<BaseApplicationUserManager>((_options,_context) => BaseApplicationUserManager.Create(usersStore,_options,_context));
app.CreatePerOwinContext<BaseApplicationRoleManager>((_options,_context) => BaseApplicationRoleManager.Create(rolesStore,_options,_context));
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType=DefaultAuthenticationTypes.ApplicationCookie,
LoginPath=new PathString("/Authentication/LogIn"),
CookieSecure=CookieSecureOption.Always,
CookieHttpOnly=true,
Provider=new CookieAuthenticationProvider {
OnValidateIdentity=SecurityStampValidator.OnValidateIdentity<BaseApplicationUserManager,BaseApplicationUser>(
TimeSpan.FromMinutes(30),
(_manager,_user) => _user.GenerateUserIdentityAsync(_manager)
)
}
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
[...]
}
问题:
登录后,使用
BaseApplicationUser user=await UserManager.FindAsync(model.Email,model.Password);
绝对正常的方式检索用户。当
ClaimsIdentity userIdentity=await manager.CreateIdentityAsync(this,DefaultAuthenticationTypes.ApplicationCookie);
被调用时,它会传递一个 BaseApplicationUser ,因此它不需要FindByIdAsync
像它那样在用户存储上调用 3 次(!!!)。这是愚蠢的次优。事实上,它甚至应该调用它,因为已经检索到用户对象。