.Net6集成IdentityServer4 +AspNetCore Identity讀取本地數據表用戶 獨立鑒權授權管理API

来源:https://www.cnblogs.com/luosiqizi/archive/2022/07/15/16481057.html
-Advertisement-
Play Games

IdentityServer4 實現鑒權、授權,AspNetCore Identity實現資料庫用戶管理表直接生成。 ps:IdentityServer4文檔上最後給的例子是 // 配置使用記憶體存儲用戶信息,但使用 EF 存儲客戶端和資源信息, 我初步要實現的是 //資料庫存儲用戶信息 記憶體存儲資源 ...


IdentityServer4 實現鑒權、授權,AspNetCore Identity實現資料庫用戶管理表直接生成。

ps:IdentityServer4文檔上最後給的例子是 // 配置使用記憶體存儲用戶信息,但使用 EF 存儲客戶端和資源信息,

  我初步要實現的是 //資料庫存儲用戶信息   記憶體存儲資源   (下一步資源也放資料庫  以後弄好了有機會更)

直接幹活:

1.創建.Net6 API程式,一頓引用,包括

防止圖片掛掉打一遍文字:

IdentityServer4、

IdengtityServer4.AspNetIdentity、

AspNetCore.Identity.EntityFrameWorkCore(生成資料庫表用的)、

EntityFrameWork+Disign+Tool三件套 (缺了不能自動遷移)、

Pomelo.EntityFrameWorkCore.MySql(我是用的MySql,如果是SqlServer 不用這個用一個大概叫EF.Sqlserver的)、

Encrypt (加密MD5用的 不必須)、

下麵那個是自帶的。

2.建立資料庫連接類

 1  public class IdpDbContext : IdentityDbContext<ApplicationUser>
 2     {
 3         public IdpDbContext(DbContextOptions<IdpDbContext> opt) : base(opt)
 4         {
 5 
 6         }
 7         protected override void OnModelCreating(ModelBuilder builder)
 8         {
 9             base.OnModelCreating(builder);
10             builder.Entity<ApplicationUser>().ToTable("ApplicationUsers");
11             #region #
12             //builder.Entity<IdentityUserLogin<string>>().ToTable("ApplicationLogins");
13             //builder.Entity<IdentityUserClaim<string>>().ToTable("ApplicationUserClaims");
14             //builder.Entity<ApplicationUserRole>().ToTable("ApplicationUserRoles");
15             //builder.Entity<IdentityUserToken<string>>().ToTable("ApplicationUserTokens");
16             //builder.Entity<ApplicationRole>().ToTable("ApplicationRoles");
17             //builder.Entity<IdentityRoleClaim<string>>().ToTable("ApplicationRoleClaims");
18             //builder.Entity<ApplicationUserRole>().HasKey(t => t.Id).HasName("PK_UserRole_ID_KEY");
19             #endregion
20 
21             builder.Entity<ApplicationUser>().HasData(
22                 new ApplicationUser()
23                 {
24                     Id = Guid.NewGuid().ToString(),
25                     RealName = "alice1",
26                     UserName = "alice1",
27                     PasswordHash = "alice1"
28                 });
29             #region 初始化用戶與角色的種子數據
30             //1. 更新用戶與角色的外鍵
31             builder.Entity<ApplicationUser>(
32                 u => u.HasMany(x => x.UserRoles).WithOne().HasForeignKey(ur => ur.UserId).IsRequired()
33                 );
34             //2. 添加管理員角色
35             var adminRoleId = "f8df1775-e889-46f4-acdd-421ec8d9ba64";
36             builder.Entity<IdentityRole>().HasData(
37                 new IdentityRole()
38                 {
39                     Id = adminRoleId,
40                     Name = "Admin",
41                     NormalizedName = "Admin".ToUpper()
42                 }
43             );
44             //3. 添加用戶
45             var adminUserId = "f8df1775-e889-46f4-acdd-421ec8d9ba65";
46             ApplicationUser adminUser = new ApplicationUser
47             {
48                 Id = adminUserId,
49                 UserName = "admin",
50                 NormalizedUserName= "admin".ToUpper(),
51                 RealName = "admin",
52                 NormalizedEmail = "[email protected]".ToUpper(),
53                 Email = "[email protected]",
54                 TwoFactorEnabled = false,
55                 EmailConfirmed = true,
56                 PhoneNumber = "123456789",
57                 PhoneNumberConfirmed = false,
58 
59             };
60             MyPasswordHasher ph = new MyPasswordHasher();
61             adminUser.PasswordHash = ph.HashPassword(adminUser, "123456");
62             builder.Entity<ApplicationUser>().HasData(adminUser);
63             //4. 給用戶加入管理員角色
64             builder.Entity<IdentityUserRole<string>>().HasData(
65                 new IdentityUserRole<string>()
66                 {
67                     RoleId = adminRoleId,
68                     UserId = adminUserId
69                 }
70                 );
71             #endregion
72 
73         }
74     }
View Code

 

3.Program里開始加東西(如果是歷史的Net版本,是在StartUp里):

直接代碼

 1 using Microsoft.AspNetCore.Identity;
 2 using Microsoft.EntityFrameworkCore;
 3 using MyIDP;
 4 using MyIDP.Models;
 5 using MyIDP.Permission;
 6 
 7 var builder = WebApplication.CreateBuilder(args);
 8 
 9 // Add services to the container.
10 builder.Services.AddControllers();
11 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
12 builder.Services.AddEndpointsApiExplorer();
13 builder.Services.AddSwaggerGen();
14 
15 //由此重要
16 builder.Services.AddDbContext<IdpDbContext>(opt =>
17 {
18     opt.UseMySql("server=127.0.0.1;Port=3306;database=AccountDb;uid=root;pwd=123456;", new MySqlServerVersion(new Version(8,0,29)));
19 });
20 
21 builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
22                 .AddUserManager<MyUserManager>()
23                 .AddEntityFrameworkStores<IdpDbContext>()
24                 .AddDefaultTokenProviders();
25 
26 builder.Services.AddIdentityServer()
27     .AddDeveloperSigningCredential()
28 
29     .AddInMemoryIdentityResources(MyIDP.IdpConfig.GetIdentityResources())
30     .AddInMemoryClients(MyIDP.IdpConfig.GetClients())
31     .AddInMemoryApiScopes( MyIDP.IdpConfig.GetScope())
32     .AddInMemoryApiResources( MyIDP.IdpConfig.GetApiResources())    //.AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() //這句可以打開自主驗證登錄用戶
33     //.AddProfileService<MyProfileService>()
34     .AddAspNetIdentity<ApplicationUser>()
35     //.AddTestUsers(new List<IdentityServer4.Test.TestUser>
36     //{
37     //    new IdentityServer4.Test.TestUser
38     //    {
39     //        SubjectId="123",
40     //        Username = "alice",
41     //        Password = "alice",
42     //        Claims = new List<Claim>() {
43     //            new Claim(JwtClaimTypes.Role, "superadmin"),
44     //            new Claim(JwtClaimTypes.Role, "admin")
45     //        }
46     //    }
47     //})
48     ;
49 
50 var app = builder.Build();
51 
52 // Configure the HTTP request pipeline.
53 if (app.Environment.IsDevelopment())
54 {
55     app.UseSwagger();
56     app.UseSwaggerUI();
57 }
58 
59 app.UseIdentityServer();
60 app.UseAuthorization();
61 app.MapControllers();
62 app.Run();

因為使用的是記憶體儲存t鑒權信息的方式,所以建立IdentityServer4的配置類IdpConfig

 1  public static class IdpConfig
 2     {
 3         public static IEnumerable<IdentityResource> GetIdentityResources()
 4         {
 5             return new IdentityResource[]
 6             {
 7                 new IdentityResources.OpenId(),
 8                 new IdentityResources.Profile(),
 9                 new IdentityResources.Address(),
10                 new IdentityResources.Phone(),
11                 new IdentityResources.Email()
12             };
13         }
14 
15         public static IEnumerable<ApiResource> GetApiResources()
16         {
17             //return new ApiResource[]
18             //{
19             //    new ApiResource("api1", "My API #1",new List<string>(){JwtClaimTypes.Role})
20             //};
21             //新寫法
22             return new[]
23             {
24                 new ApiResource("api1", "My API #1")
25                 {
26                     Scopes = { "scope1"}
27                 }
28             };
29         }
30 
31         public static IEnumerable<Client> GetClients()
32         {
33             return new[]
34             {
35                 #region MyRegion
36                  //// client credentials flow client
37                 //new Client
38                 //{
39                 //    ClientId = "console client",
40                 //    ClientName = "Client Credentials Client",
41 
42                 //    AllowedGrantTypes = GrantTypes.ClientCredentials,
43 
44                 //    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
45 
46                 //    AllowedScopes = { "api1" }
47                 //},
48 
49     #endregion
50                
51                 // wpf client, password grant
52                 new Client
53                 {
54                     ClientId = "client",
55                     AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
56                     ClientSecrets =
57                     {
58                         new Secret("secret".Sha256())
59                     },
60                     AllowedScopes = //允許當訪問的資源
61                     {
62                         "scope1",
63                         //"api1",
64                         IdentityServerConstants.StandardScopes.OpenId,
65                         IdentityServerConstants.StandardScopes.Email,
66                         IdentityServerConstants.StandardScopes.Address,
67                         IdentityServerConstants.StandardScopes.Phone,
68                         IdentityServerConstants.StandardScopes.Profile }
69                 }
70             };
71         }
72 
73         public static IEnumerable<ApiScope> GetScope()
74         {
75             return new ApiScope[] {
76                 new ApiScope("scope1"),
77                 new ApiScope("scope2"),
78             };
79         }
80     }
View Code

資料庫的usernamager

 1 public class MyUserManager : UserManager<ApplicationUser>
 2     {
 3         public MyUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<ApplicationUser> passwordHasher,
 4           IEnumerable<IUserValidator<ApplicationUser>> userValidators, IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<ApplicationUser>> logger)
 5            : base(store, optionsAccessor, new MyPasswordHasher(), userValidators, passwordValidators, keyNormalizer, errors, services, logger)
 6         {
 7             optionsAccessor.Value.Password.RequireDigit = false;
 8             optionsAccessor.Value.Password.RequiredLength = 4;
 9             optionsAccessor.Value.Password.RequireLowercase = false;
10             optionsAccessor.Value.Password.RequireUppercase = false;
11             optionsAccessor.Value.Password.RequireNonAlphanumeric = false;
12         }
13 
14     }
View Code

重寫驗證密碼的方法類MyResourceOwnerPasswordValidator,(如果沒有打開Program中的AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() 則不需要)

public class MyResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        public readonly SignInManager<ApplicationUser> signInManager;
        private readonly MyUserManager userManager;
        //public readonly IEventService service;
        public MyResourceOwnerPasswordValidator(MyUserManager userService, SignInManager<ApplicationUser> signInManager)//, IEventService service)
        {
            userManager = userService;
            this.signInManager = signInManager;
            //this.service = service;

        }
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            if (string.IsNullOrEmpty(context.UserName) || string.IsNullOrEmpty(context.Password))
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "驗證被拒絕,用戶名或者密碼為空。");
                return;
            }
            var user = await userManager.FindByNameAsync(context.UserName);
            if (user == null)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "驗證失敗,不存在當前用戶。");
                return;
            }
            //檢驗用戶密碼(雖然我也不知道他的密碼是採用什麼加密方式得到的,但是我也不需要知道) 
            var passwordPass = await userManager.CheckPasswordAsync(user, context.Password);
            if (!passwordPass)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "驗證失敗,用戶憑證錯誤");
                return;
            }
            else
            {
                try
                {
                    await userManager.AddLoginAsync(user, new UserLoginInfo(user.Id, "", user.UserName));
                }
                catch (Exception ex)
                {
                    ;
                }
                finally
                {
                    context.Result = new GrantValidationResult(user.Id, GrantType.ResourceOwnerPassword, new List<Claim>() { new Claim("account", user.UserName) }); 
                }
            }
            return;
        }

    }
View Code

MyPasswordHasher

 1 public class MyPasswordHasher : PasswordHasher<ApplicationUser>
 2     {
 3         public override string HashPassword(ApplicationUser user, string password)
 4         {
 5             //PasswordHasher<ApplicationUser> ph = new PasswordHasher<ApplicationUser>();
 6             //var pstr = ph.HashPassword(new ApplicationUser(), password);
 7             //return pstr;
 8             return password.MD5();
 9         }
10 
11         public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
12         {
13             if (providedPassword.MD5().Equals(hashedPassword))
14             {
15                 return PasswordVerificationResult.Success;
16             }
17             else
18             {
19                 return PasswordVerificationResult.Failed;
20             }
21         }
22     }
View Code

創建自己的User類 ApplicationUser繼承 IdentityUser  覆寫自帶的AspNetUser表

  public class ApplicationUser : IdentityUser
    {
        public string MySomething { get; set; } = "";
        /// <summary>
        /// 創建時間
        /// </summary>
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 創建人Id
        /// </summary>
        public string CreatorId { get; set; } = "";

        /// <summary>
        /// 否已刪除
        /// </summary>
        public bool Deleted { get; set; }
         

        /// <summary>
        /// 姓名
        /// </summary>
        public string RealName { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public Sex Sex { get; set; }

        /// <summary>
        /// 出生日期
        /// </summary>
        public DateTime? Birthday { get; set; }

        /// <summary>
        /// 所屬部門Id
        /// </summary>
        public string DepartmentId { get; set; } = "";

        public string OtherData { get; set; } = "";

        // 用戶角色 用戶許可權 用戶信息 用戶登錄tokens  重新綁定與父類的關係 命名必須和父類一致
        public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; }
        public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
        public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
        public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
    }

    public enum Sex
    {
        [Description("")]
        Man = 1,

        [Description("")]
        Woman = 0
    }
View Code

至此可以生成資料庫遷移後 Postman測試一下

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • likeshop單商戶開源商城系統,公眾號商城、H5商城、微信小程式商城、抖音小程式商城、位元組小程式商城、頭條小程式商城、安卓APP商城、蘋果APP商城代碼全開源,免費商用。 適用場景 系統適用於B2C,單商戶,自營商城場景。完美契合私域流量變現閉環交易使用。 系統亮點 LikeShop在電商通用組 ...
  • 一、前言 在項目中有需要對word進行操作的,可以看看哈,本次使用比較強大的spire組件來對word進行操作,免費版支持三頁哦,對於不止三頁的word文件,可以購買收費版,官網:https://www.e-iceblue.cn/tutorials.html#,也可使用其他組件實現,如poi、doc ...
  • MongoDB聚合查詢 什麼是聚合查詢 聚合操作主要用於處理數據並返回計算結果。聚合操作將來自多個文檔的值組合在一起,按條件分組後,再進行一系列操作(如求和、平均值、最大值、最小值)以返回單個結果。 MongoDB的聚合查詢 ​ 聚合是MongoDB的高級查詢語言,它允許我們通過轉化合併由多個文檔的 ...
  • 一、字元串 1、字元串編碼發展: 1)ASCII碼: 一個位元組去表示 (8個比特(bit)作為一個位元組(byte),因此,一個位元組能表示的最大的整數就是255(二進位11111111 = 十進位255)) 2)Unicode:兩個位元組表示(將各國的語言(中文編到GB2312,日文編到Shift_JI ...
  • JetBrAIns RubyMine 2022 for Mac是應用在Mac上的一款強大的Ruby代碼編輯器,可以通過可定製的配色方案,鍵盤方案以及高效開發所需的所有外觀設置,智能導航一鍵導航到聲明,超級方法,測試,用法,實現,是一款功能強大的代碼編輯工具。 詳情:JetBrains RubyMin ...
  • 本文主要介紹crudapi三種API認證方式,基於Spring Security框架實現, 包括Cookie,Basic Auth,JWT令牌Token。 ...
  • 1.mybatis攔截器介紹 攔截器可在mybatis進行sql底層處理的時候執行額外的邏輯,最常見的就是分頁邏輯、對結果集進行處理過濾敏感信息等。 public ParameterHandler newParameterHandler(MappedStatement mappedStatement ...
  • AbpVnext 本地事件匯流排 補充知識 發佈訂閱 概念 應用場景 本地事件匯流排允許服務發佈和訂閱進程內事件,這意味著如果兩個服務>(發佈者和訂閱者)在同一個進程中運行,那麼它是合適的 完整示例 DDD開發規範: 先定義好介面層、後實現層、暴露介面 對於要更新的實體 //領域層的實體 public ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...