如何为ABP应用程序定制SignIn Manager

在使用应用程序启动模板创建新项目后,你可能想要扩展或更改SignIn Manager的默认行为,以满足你需要的身份验证和注册流程. ABP账户模块使用身份管理模块做为SignIn Manager,而身份管理模块使用默认的Microsoft Identity SignIn Manager(参阅此处)).

编写自定义SignIn Manager,你需要扩展Microsoft Identity SignIn Manager类并注入到DI容器.

本文介绍了如何为你自己的应用程序自定义SignIn Manager.

创建 CustomSignInManager

创建一个类并继承自Microsoft Identity 包的 SignInMager.

  1. public class CustomSignInManager : Microsoft.AspNetCore.Identity.SignInManager<Volo.Abp.Identity.IdentityUser>
  2. {
  3. public CustomSignInManager(
  4. Microsoft.AspNetCore.Identity.UserManager<Volo.Abp.Identity.IdentityUser> userManager,
  5. Microsoft.AspNetCore.Http.IHttpContextAccessor contextAccessor,
  6. Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory<Volo.Abp.Identity.IdentityUser> claimsFactory,
  7. Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Identity.IdentityOptions> optionsAccessor,
  8. Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Identity.SignInManager<Volo.Abp.Identity.IdentityUser>> logger,
  9. Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemes,
  10. Microsoft.AspNetCore.Identity.IUserConfirmation<Volo.Abp.Identity.IdentityUser> confirmation)
  11. : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation)
  12. {
  13. }
  14. }

重点是使用Volo.Abp.Identity.IdentityUser做为泛型参数,而不是应用程序的AppUser.

然后你可以覆盖SignIn Manager的任何方法并且为你的身份验证和注册流程添加需要的方法和属性.

重写 GetExternalLoginInfoAsync 方法

在这个用例中我们重写第三方身份验证时使用的 GetExternalLoginInfoAsync 方法实现.

一个好的开始是从复制源码而不是从零开始. 在这个用例中我们对源码进行较少的修改,为了帮助理解概念它显式显示了方法和属性的命名空间.

  1. public override async Task<Microsoft.AspNetCore.Identity.ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
  2. {
  3. var auth = await Context.AuthenticateAsync(Microsoft.AspNetCore.Identity.IdentityConstants.ExternalScheme);
  4. var items = auth?.Properties?.Items;
  5. if (auth?.Principal == null || items == null || !items.ContainsKey(LoginProviderKey))
  6. {
  7. return null;
  8. }
  9. if (expectedXsrf != null)
  10. {
  11. if (!items.ContainsKey(XsrfKey))
  12. {
  13. return null;
  14. }
  15. var userId = items[XsrfKey] as string;
  16. if (userId != expectedXsrf)
  17. {
  18. return null;
  19. }
  20. }
  21. var providerKey = auth.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
  22. var provider = items[LoginProviderKey] as string;
  23. if (providerKey == null || provider == null)
  24. {
  25. return null;
  26. }
  27. var providerDisplayName = (await GetExternalAuthenticationSchemesAsync()).FirstOrDefault(p => p.Name == provider)?.DisplayName
  28. ?? provider;
  29. return new Microsoft.AspNetCore.Identity.ExternalLoginInfo(auth.Principal, provider, providerKey, providerDisplayName)
  30. {
  31. AuthenticationTokens = auth.Properties.GetTokens()
  32. };
  33. }

要使你自定义的SignIn Manager类生效,你需要将其注册依赖注入系统中.

注册到依赖注入

应该使用 IdentityBuilderIdentityBuilderExtensions 类的 AddSignInManager 扩展方法注册 CustomSignInManager.

在你的 .Web 项目找到 YourProjectNameWebModulePreConfigureServices 方法添加以下代码替换老的 SignInManager:

  1. PreConfigure<IdentityBuilder>(identityBuilder =>
  2. {
  3. identityBuilder.AddSignInManager<CustomSignInManager>();
  4. });

本文的源代码

你可以在这里找到已完成的示例源码.

另请参阅