独自のカスタム ストアで 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 回 (!!!) 呼び出す必要はありません。これはばかげて次善です。実際、ユーザー オブジェクトは既に取得されているため、これを呼び出す必要もあります。