# 如何为ABP应用程序定制SignIn Manager 在使用[应用程序启动模板](../Startup-Templates/Application.md)创建新项目后,你可能想要扩展或更改SignIn Manager的默认行为,以满足你需要的身份验证和注册流程. ABP[账户模块](../Modules/Account.md)使用[身份管理模块](../Modules/Identity.md)做为SignIn Manager,而[身份管理模块](../Modules/Identity.md)使用默认的[Microsoft Identity SignIn Manager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs)([参阅此处]((https://github.com/abpframework/abp/blob/be32a55449e270d2d456df3dabdc91f3ffdd4fa9/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs#L17))). 编写自定义SignIn Manager,你需要扩展[Microsoft Identity SignIn Manager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs)类并注入到DI容器. 本文介绍了如何为你自己的应用程序自定义SignIn Manager. ## 创建 CustomSignInManager 创建一个类并继承自Microsoft Identity 包的 [SignInMager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs). ````csharp public class CustomSignInManager : Microsoft.AspNetCore.Identity.SignInManager { public CustomSignInManager( Microsoft.AspNetCore.Identity.UserManager userManager, Microsoft.AspNetCore.Http.IHttpContextAccessor contextAccessor, Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory claimsFactory, Microsoft.Extensions.Options.IOptions optionsAccessor, Microsoft.Extensions.Logging.ILogger> logger, Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemes, Microsoft.AspNetCore.Identity.IUserConfirmation confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) { } } ```` > 重点是使用**Volo.Abp.Identity.IdentityUser**做为泛型参数,而不是应用程序的AppUser. 然后你可以覆盖SignIn Manager的任何方法并且为你的身份验证和注册流程添加需要的方法和属性. ## 重写 GetExternalLoginInfoAsync 方法 在这个用例中我们重写第三方身份验证时使用的 `GetExternalLoginInfoAsync` 方法实现. 一个好的开始是从复制[源码](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Identity/Core/src/SignInManager.cs#L638-L674)而不是从零开始. 在这个用例中我们对源码进行较少的修改,为了帮助理解概念它显式显示了方法和属性的命名空间. ````csharp public async override Task GetExternalLoginInfoAsync(string expectedXsrf = null) { var auth = await Context.AuthenticateAsync(Microsoft.AspNetCore.Identity.IdentityConstants.ExternalScheme); var items = auth?.Properties?.Items; if (auth?.Principal == null || items == null || !items.ContainsKey(LoginProviderKey)) { return null; } if (expectedXsrf != null) { if (!items.ContainsKey(XsrfKey)) { return null; } var userId = items[XsrfKey] as string; if (userId != expectedXsrf) { return null; } } var providerKey = auth.Principal.FindFirstValue(ClaimTypes.NameIdentifier); var provider = items[LoginProviderKey] as string; if (providerKey == null || provider == null) { return null; } var providerDisplayName = (await GetExternalAuthenticationSchemesAsync()).FirstOrDefault(p => p.Name == provider)?.DisplayName ?? provider; return new Microsoft.AspNetCore.Identity.ExternalLoginInfo(auth.Principal, provider, providerKey, providerDisplayName) { AuthenticationTokens = auth.Properties.GetTokens() }; } ```` 要使你自定义的SignIn Manager类生效,你需要将其注册[依赖注入系统](../Dependency-Injection.md)中. ## 注册到依赖注入 应该使用 [IdentityBuilder](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Extensions.Core/src/IdentityBuilder.cs) 的 [IdentityBuilderExtensions](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/IdentityBuilderExtensions.cs) 类的 **AddSignInManager** 扩展方法注册 `CustomSignInManager`. 在你的 `.Web` 项目找到 `YourProjectNameWebModule` 的 `PreConfigureServices` 方法添加以下代码替换老的 `SignInManager`: ````csharp PreConfigure(identityBuilder => { identityBuilder.AddSignInManager(); }); ```` ## 本文的源代码 你可以在[这里](https://github.com/abpframework/abp-samples/tree/master/Authentication-Customization)找到已完成的示例源码. ## 另请参阅 * [如何为MVC / Razor页面应用程序自定义登录页面](Customize-Login-Page-MVC.md). * [身份管理模块](../Modules/Identity.md).