本例子使用的是Blazor WebAssembly+IdentityServer4+Sql Server
IdentityServer4的基础知识可以访问官方网站学习:https://identityserver4.readthedocs.io/en/latest/
一.创建IdentityServer4
1.创建名为WebAppSample的空白解决方案。
2.通过命令安装IdentityServer4的模板,VS->工具->命令行->开发者命令提示,执行:dotnet new -i IdentityServer4.Templates,安装成功提示如下:
3.创建IdentityServer4项目,我这里使用的是IdentityServer4+Asp.Net Core Identity,以Asp.Net Core Identity作为IdentityServer4的用户支持。
- 在“开发者命令提示”中执行:dotnet new is4aspid -n WebApp.IdentityServer,其中WebApp.IdentityServer是项目名称。
- 以下提示选否。因为is4aspid模板默认使用的数据库不是Sql Server数据库,后面要修改。
- 项目已创建在解决方案的根目录,添加项目至解决方案。
4.把项目WebApp.IdentityServer的目标框架改为:.NET 5.0。
5.设置数据库上下文,这里我们使用的是SQL Server数据库。
- 给项目添加Microsoft.EntityFrameworkCore.SqlServer包。
- 打开appsettings.json文件设置连接字符串。
{ "ConnectionStrings": { "DefaultConnection": "Server=127.0.0.1;Initial Catalog=WebAppIdentityServerDB;Persist Security Info=False;User id=sa;Password=sa123456;MultipleActiveResultSets=true" } }
- 创建全局变量DbConnectionString用于保存数据库连接字符串。
public class Datas { public static string DbConnectionString { get; set; } = "Server=127.0.0.1;" + "Initial Catalog=WebAppIdentityServerDB;" + "Persist Security Info=False;" + "User id=sa;" + "Password=sa123456;" + "MultipleActiveResultSets=true"; }
- 在Startup类的构造函数中给全局变量DbConnectionString赋值。
public Startup(IConfiguration configuration) { Configuration = configuration; Datas.DbConnectionString = Configuration.GetConnectionString("DefaultConnection"); }
- 在Startup类的ConfigureServices方法中注册数据库上下文。
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
6.配置将客户端(Client)、资源(IdentityResource、ApiResource、ApiScope)、操作数据(codes、tokens、consents)保存至数据库。
- 添加IdentityServer4.EntityFramework包。
- 在Startup类的ConfigureServices方法添加以下代码。
var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html options.EmitStaticAudienceClaim = true; }); #region 保存在内存中的身份资源、API资源、客户端资源 //identityServerBuilder.AddInMemoryIdentityResources(Config.IdentityResources); //identityServerBuilder.AddInMemoryApiScopes(Config.ApiScopes); //identityServerBuilder.AddInMemoryClients(Config.Clients); #endregion #region 保存在数据库中的身份资源、API资源、客户端资源 //配置数据(客户端、资源)至数据库:ConfigurationDbContext //typeof(SeedData).Assembly.FullName builder.AddConfigurationStore(options => { options.ConfigureDbContext = builder => { builder.UseSqlServer(Datas.DbConnectionString, b => b.MigrationsAssembly("WebApp.IdentityServer")); }; }); //配置操作数据(codes、tokens、consents)至数据库:PersistedGrantDbContext builder.AddOperationalStore(options => { options.ConfigureDbContext = builder => { builder.UseSqlServer(Datas.DbConnectionString, b => b.MigrationsAssembly("WebApp.IdentityServer")); }; //启用自动令牌清理,这是可选的;清理时间默认是3600秒。 options.EnableTokenCleanup = true; options.TokenCleanupInterval = 3600; });
7.配置IdentityServer使用Asp.Net Core Identity的用户作为用户支持。
- 在Startup类的ConfigureServices方法添加以下代码。
builder.AddAspNetIdentity<ApplicationUser>();
8.注册自定义用户声明工厂,用于添加自定义用户声明到用户标识,例如用户权限。
- 创建AdditionalUserClaimsPrincipalFactory类,如下:
public class AdditionalUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole> { public AdditionalUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) { } public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user) { var principal = await base.CreateAsync(user); var identity = (ClaimsIdentity)principal.Identity; var claims = new List<Claim>(); claims.Add(new Claim(JwtClaimTypes.PreferredUserName, user.UserName)); //你的代码:从数据库读取用户的权限声明 identity.AddClaims(claims); return principal; } }
- 在Startup类的ConfigureServices方法中注册自定义用户声明工厂。
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AdditionalUserClaimsPrincipalFactory>();
二.创建Blazor WebAssembly