blazorboilerplate 的 Startup 类源代码分析
blazorboilerplate 的 Startup 类源代码分析: https://github.com/enkodellc/blazorboilerplate/blob/master/src/BlazorBoilerplate.Server/Startup.cs
--------------------------------------------------------------------
AddIdentity 源代码: 完整扩展方法:其中有一个 Action<IdentityOptions> 参数
public static IdentityBuilder AddIdentity<TUser, TRole>( this IServiceCollection services,
Action<IdentityOptions> setupAction) where TUser : class where TRole : class
下列实现将 :AddIdentity 与 Configure<IdentityOptions> 分开,不是使用带 Action<IdentityOptions> 参数的 AddIdentity。
实际上,带 Action<IdentityOptions> 参数的 AddIdentity 扩展方法,最后 还是 调用了: Configure<IdentityOptions>。如下
if (setupAction != null) { services.Configure(setupAction); }
IdentityBuilder 类定义:https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.identity.identitybuilder?view=aspnetcore-3.1 初始化:IdentityBuilder(Type user , Type role, IServiceCollection)
AddIdentity() 的执行过程:
1)services.AddAuthentication()
2)四次 services.AddCookie() ,使用了 IdentityConstants 类,有四常量值。
3)services.AddHttpContextAccessor();
4)其它
5)if (setupAction != null) { services.Configure(setupAction); }
6)返回 new IdentityBuilder(typeof(TUser), typeof(TRole), services);
1、 services.AddIdentity<ApplicationUser, IdentityRole<Guid>>() 返回:IdentityBuilder
.AddRoles<IdentityRole<Guid>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//在AddIdentity 的源码中已有 services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AdditionalUserClaimsPrincipalFactory>();
############## 从后面移动到此,与 Identity 相关的 配置 ###########################
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
//options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
// Require Confirmed Email User settings
if (Convert.ToBoolean(Configuration["BlazorBoilerplate:RequireConfirmedEmail"] ?? "false"))
{
options.User.RequireUniqueEmail = false;
options.SignIn.RequireConfirmedEmail = true;
}
});
// Adds IdentityServer @@@@@@@@@@@@@@@@@@@
var identityServerBuilder = services.AddIdentityServer(options =>
{
options.IssuerUri = authAuthority;
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = DbContextOptionsBuilder;
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = DbContextOptionsBuilder;
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 3600; //In Seconds 1 hour
})
.AddAspNetIdentity<ApplicationUser>();
2、===========================================
AddAuthentication() 有三个扩展方法:AddAuthentication(IServiceCollection, [ Action<AuthenticationOptions>] )
AddAuthentication(IServiceCollection, String defaultScheme) [ Action<AuthenticationOptions>] 是可选参数。
AuthenticationOptions 有很多 Scheme 及 AuthenticationSchemeBuilder
var authBuilder = services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
})
.AddIdentityServerAuthentication(options =>
{
options.Authority = authAuthority;
options.SupportedTokens = SupportedTokens.Jwt;
options.RequireHttpsMetadata = _environment.IsProduction() ? true : false;
options.ApiName = IdentityServerConfig.ApiName;
});
3、=========================================================
//Add Policies / Claims / Authorization - https://stormpath.com/blog/tutorial-policy-based-authorization-asp-net-core
services.AddAuthorization(options =>
{
options.AddPolicy(Policies.IsAdmin, Policies.IsAdminPolicy());
options.AddPolicy(Policies.IsUser, Policies.IsUserPolicy());
options.AddPolicy(Policies.IsReadOnly, Policies.IsReadOnlyPolicy());
options.AddPolicy(Policies.IsMyDomain, Policies.IsMyDomainPolicy()); // valid only on serverside operations
});
services.AddTransient<IAuthorizationHandler, DomainRequirementHandler>();
4、************************************************************************************
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.ConfigureExternalCookie(options =>
{
// macOS login fix
options.Cookie.SameSite = SameSiteMode.None;
});
services.ConfigureApplicationCookie(options =>
{
// macOS login fix
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.HttpOnly = false;
// Suppress redirect on API URLs in ASP.NET Core -> https://stackoverflow.com/a/56384729/54159
options.Events = new CookieAuthenticationEvents()
{
OnRedirectToAccessDenied = context =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
context.Response.StatusCode = (int)(HttpStatusCode.Unauthorized);
}
return Task.CompletedTask;
},
OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
}
};
});