2

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

4

3 に答える 3

1

私のソリューションは本当に「実装固有」です (MongoDB 用に独自の ID ストアを実装したため、このレベルでキャッシュを設定しました。これにより、一般的なソリューションよりも適切に制御できます)。ソースコードをhttp://pastebin.com/MV0F4MUAに投稿しました

ConfigureAuth次に、これをメソッドに設定して、リクエストごとにキャッシュを「呼び出し」ます。

app.CreatePerOwinContext<BaseApplicationUserManager>((_options,_context) => BaseApplicationUserManager.Create(new AuthenticationProviderRequestCache<BaseApplicationUser>(authenticationProvider),_options,_context));

警告: 私のコードを単にコピーしてソリューションに貼り付けることはできません。必要に応じて適応させるには、コードを理解する必要があります。

于 2014-08-22T16:25:18.847 に答える