1.概念
以下概念從官網整理的,我也是看官網一步一步學習的
官網地址 https://identityserver4.readthedocs.io/en/latest/index.html
1.1 IdentityServer 是將符合規范的 OpenID Connect 和 OAuth 2.0 端點添加到任意 ASP.NET Core 應用程序的中間件。
IdentityServer 是一個 OpenID Connect 提供者——它實現了 OpenID Connect 和 OAuth 2.0 協議。
1.2 IdentityServer 能做什么
- 保護您的資源
- 使用本地帳戶存儲或通過外部身份提供商對用戶進行身份驗證
- 提供會話管理和單點登錄
- 管理和驗證客戶
- 向客戶端頒發身份和訪問令牌
- 驗證令牌
1.3 身份服務器:IdentityServer 是一個 OpenID Connect 提供者——它實現了 OpenID Connect 和 OAuth 2.0 協議。
1.4 用戶:用戶是使用注冊客戶端訪問資源的人。
1.5 客戶:客戶端是一個從 IdentityServer 請求令牌的軟件——用於驗證用戶(請求身份令牌)或訪問資源(請求訪問令牌)。客戶端必須先向 IdentityServer 注冊,然后才能請求令牌。
1.7 資源:資源是您想要使用 IdentityServer 保護的東西——您的用戶的身份數據或 API。
1.8 身份令牌:身份令牌代表身份驗證過程的結果。它至少包含用戶的標識符(稱為sub又名主題聲明)以及有關用戶如何以及何時進行身份驗證的信息。它可以包含額外的身份數據。
1.9 訪問令牌:訪問令牌允許訪問 API 資源。客戶端請求訪問令牌並將它們轉發到 API。訪問令牌包含有關客戶端和用戶(如果存在)的信息。API 使用該信息來授權對其數據的訪問。
2.安裝IdentityServer模板及數據庫遷移
2.1 安裝命令 dotnet new -i IdentityServer4.Templates
2.2 所需依賴包
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="4.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
</ItemGroup>
2.3 創建項目模板 (依次執行以下命令)
創建項目模板
md MyIdentityServer4DataMigration
cd MyIdentityServer4DataMigration
md src
cd src
dotnet new is4empty -n IdentityServerBySqlServer
dotnet new is4empty -n IdentityServerByMySql
cd ../
dotnet new sln -n MyIdentityServer4DataMigration
dotnet sln add .\src\IdentityServerBySqlServer\IdentityServerBySqlServer.csproj
dotnet sln add .\src\IdentityServerByMySql\IdentityServerByMySql.csproj
創建完成后打開,如下如所示
然后安裝依賴包,首先是sqlserver的
把上面的依賴包命令粘貼到IdentityServerBySqlServer.csproj里,control+s保存,會自動安裝依賴包
然后
cd src
dotnet new is4ui
大部分包我是通過Nuget手動安裝的,命令沒有那么全,SqlServer相關依賴包安裝完成后如下圖所示
3. Startup代碼
3.1sqlserver代碼
public class Startup { public IWebHostEnvironment Environment { get; } public Startup(IWebHostEnvironment environment) { Environment = environment; } public void ConfigureServices(IServiceCollection services) { //var serverVersion = new MySqlServerVersion(new Version(8, 0, 21)); //// Replace 'YourDbContext' with the name of your own DbContext derived class. //services.AddDbContext<YourDbContext>( // dbContextOptions => dbContextOptions // .UseMySql(connectionString, serverVersion) // .EnableSensitiveDataLogging() // <-- These two calls are optional but help // .EnableDetailedErrors() // <-- with debugging (remove for production). //); var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; const string connectionString = @"Server=localhost; Port=3306;Stmt=; Database=MyIdentityServer4DB; Uid=root; Pwd=Docimax@123;"; var serverVersion = new MySqlServerVersion(new Version(5, 7, 28)); services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(connectionString,serverVersion)); services.AddIdentity<ApplicationUser, ApplicationRole>(options => { options.User = new UserOptions { RequireUniqueEmail = true, //要求Email唯一 AllowedUserNameCharacters = null //允許的用戶名字符 }; options.Password = new PasswordOptions { RequiredLength = 8, //要求密碼最小長度,默認是 6 個字符 RequireDigit = true, //要求有數字 RequiredUniqueChars = 3, //要求至少要出現的字母數 RequireLowercase = true, //要求小寫字母 RequireNonAlphanumeric = false, //要求特殊字符 RequireUppercase = false //要求大寫字母 }; //options.Lockout = new LockoutOptions //{ // AllowedForNewUsers = true, // 新用戶鎖定賬戶 // DefaultLockoutTimeSpan = TimeSpan.FromHours(1), //鎖定時長,默認是 5 分鍾 // MaxFailedAccessAttempts = 3 //登錄錯誤最大嘗試次數,默認 5 次 //}; //options.SignIn = new SignInOptions //{ // RequireConfirmedEmail = true, //要求激活郵箱 // RequireConfirmedPhoneNumber = true //要求激活手機號 //}; //options.ClaimsIdentity = new ClaimsIdentityOptions //{ // // 這里都是修改相應的Cliams聲明的 // RoleClaimType = "IdentityRole", // UserIdClaimType = "IdentityId", // SecurityStampClaimType = "SecurityStamp", // UserNameClaimType = "IdentityName" //}; }) .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddIdentityServer() //.AddTestUsers(TestUsers.Users) .AddAspNetIdentity<ApplicationUser>() .AddConfigurationStore(options => { options.ConfigureDbContext = b => b.UseMySql(connectionString, serverVersion, sql => sql.MigrationsAssembly(migrationsAssembly)); }) .AddOperationalStore(options => { options.ConfigureDbContext = b => b.UseMySql(connectionString, serverVersion, sql => sql.MigrationsAssembly(migrationsAssembly)); }); } public void Configure(IApplicationBuilder app) { InitializeDatabase(app); if (Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // uncomment if you want to add MVC //app.UseStaticFiles(); //app.UseRouting(); app.UseIdentityServer(); // uncomment, if you want to add MVC //app.UseAuthorization(); //app.UseEndpoints(endpoints => //{ // endpoints.MapDefaultControllerRoute(); //}); } private void InitializeDatabase(IApplicationBuilder app) { using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope()) { serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate(); var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>(); context.Database.Migrate(); if (!context.Clients.Any()) { foreach (var client in Config.Clients) { context.Clients.Add(client.ToEntity()); } context.SaveChanges(); } if (!context.IdentityResources.Any()) { foreach (var resource in Config.IdentityResources) { context.IdentityResources.Add(resource.ToEntity()); } context.SaveChanges(); } if (!context.ApiScopes.Any()) { foreach (var resource in Config.ApiScopes) { context.ApiScopes.Add(resource.ToEntity()); } context.SaveChanges(); } } } }
3.2 Mysql代碼
public class Startup { public IWebHostEnvironment Environment { get; } public Startup(IWebHostEnvironment environment) { Environment = environment; } public void ConfigureServices(IServiceCollection services) { //var serverVersion = new MySqlServerVersion(new Version(8, 0, 21)); //// Replace 'YourDbContext' with the name of your own DbContext derived class. //services.AddDbContext<YourDbContext>( // dbContextOptions => dbContextOptions // .UseMySql(connectionString, serverVersion) // .EnableSensitiveDataLogging() // <-- These two calls are optional but help // .EnableDetailedErrors() // <-- with debugging (remove for production). //); var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; const string connectionString = @"Server=localhost; Port=3306;Stmt=; Database=MyIdentityServer4DB; Uid=root; Pwd=Docimax@123;"; var serverVersion = new MySqlServerVersion(new Version(5, 7, 28)); services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(connectionString,serverVersion)); services.AddIdentity<ApplicationUser, ApplicationRole>(options => { options.User = new UserOptions { RequireUniqueEmail = true, //要求Email唯一 AllowedUserNameCharacters = null //允許的用戶名字符 }; options.Password = new PasswordOptions { RequiredLength = 8, //要求密碼最小長度,默認是 6 個字符 RequireDigit = true, //要求有數字 RequiredUniqueChars = 3, //要求至少要出現的字母數 RequireLowercase = true, //要求小寫字母 RequireNonAlphanumeric = false, //要求特殊字符 RequireUppercase = false //要求大寫字母 }; //options.Lockout = new LockoutOptions //{ // AllowedForNewUsers = true, // 新用戶鎖定賬戶 // DefaultLockoutTimeSpan = TimeSpan.FromHours(1), //鎖定時長,默認是 5 分鍾 // MaxFailedAccessAttempts = 3 //登錄錯誤最大嘗試次數,默認 5 次 //}; //options.SignIn = new SignInOptions //{ // RequireConfirmedEmail = true, //要求激活郵箱 // RequireConfirmedPhoneNumber = true //要求激活手機號 //}; //options.ClaimsIdentity = new ClaimsIdentityOptions //{ // // 這里都是修改相應的Cliams聲明的 // RoleClaimType = "IdentityRole", // UserIdClaimType = "IdentityId", // SecurityStampClaimType = "SecurityStamp", // UserNameClaimType = "IdentityName" //}; }) .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddIdentityServer() //.AddTestUsers(TestUsers.Users) .AddAspNetIdentity<ApplicationUser>() .AddConfigurationStore(options => { options.ConfigureDbContext = b => b.UseMySql(connectionString, serverVersion, sql => sql.MigrationsAssembly(migrationsAssembly)); }) .AddOperationalStore(options => { options.ConfigureDbContext = b => b.UseMySql(connectionString, serverVersion, sql => sql.MigrationsAssembly(migrationsAssembly)); }); } public void Configure(IApplicationBuilder app) { InitializeDatabase(app); if (Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // uncomment if you want to add MVC //app.UseStaticFiles(); //app.UseRouting(); app.UseIdentityServer(); // uncomment, if you want to add MVC //app.UseAuthorization(); //app.UseEndpoints(endpoints => //{ // endpoints.MapDefaultControllerRoute(); //}); } private void InitializeDatabase(IApplicationBuilder app) { using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope()) { serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate(); var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>(); context.Database.Migrate(); if (!context.Clients.Any()) { foreach (var client in Config.Clients) { context.Clients.Add(client.ToEntity()); } context.SaveChanges(); } if (!context.IdentityResources.Any()) { foreach (var resource in Config.IdentityResources) { context.IdentityResources.Add(resource.ToEntity()); } context.SaveChanges(); } if (!context.ApiScopes.Any()) { foreach (var resource in Config.ApiScopes) { context.ApiScopes.Add(resource.ToEntity()); } context.SaveChanges(); } } } }
4.數據遷移
第一種方式(推薦)
1. vs2019 ===> 工具 ===> Nuget 包管理器 ====> 程序包管理器控制台
2. 執行以下命令
add-migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
add-migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
add-migration AppDbMigration -c ApplicationDbContext -o Data
update-database -context PersistedGrantDbContext
update-database -context ConfigurationDbContext
update-database -context ApplicationDbContext
第二種方式
PowerShell執行數據遷移命令,然后運行程序
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
遷移完成后如下圖所示
檢查SqlServer數據庫是否生成表結構
//接下來操作mysql
cd ../
cd IdentityServerByMySql
dotnet new is4ui
dotnet add package IdentityServer4.EntityFramework
mysql的相關依賴包,如下圖所示:
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
MySql遷移完成后檢查MySql數據庫