.Net6集成IdentityServer4 +AspNetCore Identity读取本地数据表用户 独立鉴 ...

瑞星  金牌会员 | 2022-8-27 16:36:07 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 869|帖子 869|积分 2607

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. 1  public class IdpDbContext : IdentityDbContext<ApplicationUser>
  2. 2     {
  3. 3         public IdpDbContext(DbContextOptions<IdpDbContext> opt) : base(opt)
  4. 4         {
  5. 5
  6. 6         }
  7. 7         protected override void OnModelCreating(ModelBuilder builder)
  8. 8         {
  9. 9             base.OnModelCreating(builder);
  10. 10             builder.Entity<ApplicationUser>().ToTable("ApplicationUsers");
  11. 11             #region #
  12. 12             //builder.Entity<IdentityUserLogin<string>>().ToTable("ApplicationLogins");
  13. 13             //builder.Entity<IdentityUserClaim<string>>().ToTable("ApplicationUserClaims");
  14. 14             //builder.Entity<ApplicationUserRole>().ToTable("ApplicationUserRoles");
  15. 15             //builder.Entity<IdentityUserToken<string>>().ToTable("ApplicationUserTokens");
  16. 16             //builder.Entity<ApplicationRole>().ToTable("ApplicationRoles");
  17. 17             //builder.Entity<IdentityRoleClaim<string>>().ToTable("ApplicationRoleClaims");
  18. 18             //builder.Entity<ApplicationUserRole>().HasKey(t => t.Id).HasName("PK_UserRole_ID_KEY");
  19. 19             #endregion
  20. 20
  21. 21             builder.Entity<ApplicationUser>().HasData(
  22. 22                 new ApplicationUser()
  23. 23                 {
  24. 24                     Id = Guid.NewGuid().ToString(),
  25. 25                     RealName = "alice1",
  26. 26                     UserName = "alice1",
  27. 27                     PasswordHash = "alice1"
  28. 28                 });
  29. 29             #region 初始化用戶与角色的种子数据
  30. 30             //1. 更新用戶与角色的外鍵
  31. 31             builder.Entity<ApplicationUser>(
  32. 32                 u => u.HasMany(x => x.UserRoles).WithOne().HasForeignKey(ur => ur.UserId).IsRequired()
  33. 33                 );
  34. 34             //2. 添加管理员角色
  35. 35             var adminRoleId = "f8df1775-e889-46f4-acdd-421ec8d9ba64";
  36. 36             builder.Entity<IdentityRole>().HasData(
  37. 37                 new IdentityRole()
  38. 38                 {
  39. 39                     Id = adminRoleId,
  40. 40                     Name = "Admin",
  41. 41                     NormalizedName = "Admin".ToUpper()
  42. 42                 }
  43. 43             );
  44. 44             //3. 添加用户
  45. 45             var adminUserId = "f8df1775-e889-46f4-acdd-421ec8d9ba65";
  46. 46             ApplicationUser adminUser = new ApplicationUser
  47. 47             {
  48. 48                 Id = adminUserId,
  49. 49                 UserName = "admin",
  50. 50                 NormalizedUserName= "admin".ToUpper(),
  51. 51                 RealName = "admin",
  52. 52                 NormalizedEmail = "admin@qq.com".ToUpper(),
  53. 53                 Email = "admin@qq.com",
  54. 54                 TwoFactorEnabled = false,
  55. 55                 EmailConfirmed = true,
  56. 56                 PhoneNumber = "123456789",
  57. 57                 PhoneNumberConfirmed = false,
  58. 58
  59. 59             };
  60. 60             MyPasswordHasher ph = new MyPasswordHasher();
  61. 61             adminUser.PasswordHash = ph.HashPassword(adminUser, "123456");
  62. 62             builder.Entity<ApplicationUser>().HasData(adminUser);
  63. 63             //4. 给用户加入管理员角色
  64. 64             builder.Entity<IdentityUserRole<string>>().HasData(
  65. 65                 new IdentityUserRole<string>()
  66. 66                 {
  67. 67                     RoleId = adminRoleId,
  68. 68                     UserId = adminUserId
  69. 69                 }
  70. 70                 );
  71. 71             #endregion
  72. 72
  73. 73         }
  74. 74     }
复制代码
View Code 
3.Program里开始加东西(如果是历史的Net版本,是在StartUp里):
直接代码
  1. 1 using Microsoft.AspNetCore.Identity;
  2. 2 using Microsoft.EntityFrameworkCore;
  3. 3 using MyIDP;
  4. 4 using MyIDP.Models;
  5. 5 using MyIDP.Permission;
  6. 6
  7. 7 var builder = WebApplication.CreateBuilder(args);
  8. 8
  9. 9 // Add services to the container.
  10. 10 builder.Services.AddControllers();
  11. 11 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
  12. 12 builder.Services.AddEndpointsApiExplorer();
  13. 13 builder.Services.AddSwaggerGen();
  14. 14
  15. 15 //由此重要
  16. 16 builder.Services.AddDbContext<IdpDbContext>(opt =>
  17. 17 {
  18. 18     opt.UseMySql("server=127.0.0.1;Port=3306;database=AccountDb;uid=root;pwd=123456;", new MySqlServerVersion(new Version(8,0,29)));
  19. 19 });
  20. 20
  21. 21 builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
  22. 22                 .AddUserManager<MyUserManager>()
  23. 23                 .AddEntityFrameworkStores<IdpDbContext>()
  24. 24                 .AddDefaultTokenProviders();
  25. 25
  26. 26 builder.Services.AddIdentityServer()
  27. 27     .AddDeveloperSigningCredential()
  28. 28
  29. 29     .AddInMemoryIdentityResources(MyIDP.IdpConfig.GetIdentityResources())
  30. 30     .AddInMemoryClients(MyIDP.IdpConfig.GetClients())
  31. 31     .AddInMemoryApiScopes( MyIDP.IdpConfig.GetScope())
  32. 32     .AddInMemoryApiResources( MyIDP.IdpConfig.GetApiResources())    //.AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() //这句可以打开自主验证登录用户
  33. 33     //.AddProfileService<MyProfileService>()
  34. 34     .AddAspNetIdentity<ApplicationUser>()
  35. 35     //.AddTestUsers(new List<IdentityServer4.Test.TestUser>
  36. 36     //{
  37. 37     //    new IdentityServer4.Test.TestUser
  38. 38     //    {
  39. 39     //        SubjectId="123",
  40. 40     //        Username = "alice",
  41. 41     //        Password = "alice",
  42. 42     //        Claims = new List<Claim>() {
  43. 43     //            new Claim(JwtClaimTypes.Role, "superadmin"),
  44. 44     //            new Claim(JwtClaimTypes.Role, "admin")
  45. 45     //        }
  46. 46     //    }
  47. 47     //})
  48. 48     ;
  49. 49
  50. 50 var app = builder.Build();
  51. 51
  52. 52 // Configure the HTTP request pipeline.
  53. 53 if (app.Environment.IsDevelopment())
  54. 54 {
  55. 55     app.UseSwagger();
  56. 56     app.UseSwaggerUI();
  57. 57 }
  58. 58
  59. 59 app.UseIdentityServer();
  60. 60 app.UseAuthorization();
  61. 61 app.MapControllers();
  62. 62 app.Run();
复制代码
因为使用的是内存储存t鉴权信息的方式,所以建立IdentityServer4的配置类IdpConfig
  1. 1  public static class IdpConfig
  2. 2     {
  3. 3         public static IEnumerable<IdentityResource> GetIdentityResources()
  4. 4         {
  5. 5             return new IdentityResource[]
  6. 6             {
  7. 7                 new IdentityResources.OpenId(),
  8. 8                 new IdentityResources.Profile(),
  9. 9                 new IdentityResources.Address(),
  10. 10                 new IdentityResources.Phone(),
  11. 11                 new IdentityResources.Email()
  12. 12             };
  13. 13         }
  14. 14
  15. 15         public static IEnumerable<ApiResource> GetApiResources()
  16. 16         {
  17. 17             //return new ApiResource[]
  18. 18             //{
  19. 19             //    new ApiResource("api1", "My API #1",new List<string>(){JwtClaimTypes.Role})
  20. 20             //};
  21. 21             //新写法
  22. 22             return new[]
  23. 23             {
  24. 24                 new ApiResource("api1", "My API #1")
  25. 25                 {
  26. 26                     Scopes = { "scope1"}
  27. 27                 }
  28. 28             };
  29. 29         }
  30. 30
  31. 31         public static IEnumerable<Client> GetClients()
  32. 32         {
  33. 33             return new[]
  34. 34             {
  35. 35                 #region MyRegion
  36. 36                  //// client credentials flow client
  37. 37                 //new Client
  38. 38                 //{
  39. 39                 //    ClientId = "console client",
  40. 40                 //    ClientName = "Client Credentials Client",
  41. 41
  42. 42                 //    AllowedGrantTypes = GrantTypes.ClientCredentials,
  43. 43
  44. 44                 //    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
  45. 45
  46. 46                 //    AllowedScopes = { "api1" }
  47. 47                 //},
  48. 48
  49. 49     #endregion
  50. 50               
  51. 51                 // wpf client, password grant
  52. 52                 new Client
  53. 53                 {
  54. 54                     ClientId = "client",
  55. 55                     AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
  56. 56                     ClientSecrets =
  57. 57                     {
  58. 58                         new Secret("secret".Sha256())
  59. 59                     },
  60. 60                     AllowedScopes = //允许当访问的资源
  61. 61                     {
  62. 62                         "scope1",
  63. 63                         //"api1",
  64. 64                         IdentityServerConstants.StandardScopes.OpenId,
  65. 65                         IdentityServerConstants.StandardScopes.Email,
  66. 66                         IdentityServerConstants.StandardScopes.Address,
  67. 67                         IdentityServerConstants.StandardScopes.Phone,
  68. 68                         IdentityServerConstants.StandardScopes.Profile }
  69. 69                 }
  70. 70             };
  71. 71         }
  72. 72
  73. 73         public static IEnumerable<ApiScope> GetScope()
  74. 74         {
  75. 75             return new ApiScope[] {
  76. 76                 new ApiScope("scope1"),
  77. 77                 new ApiScope("scope2"),
  78. 78             };
  79. 79         }
  80. 80     }
复制代码
View Code数据库的usernamager
  1. 1 public class MyUserManager : UserManager<ApplicationUser>
  2. 2     {
  3. 3         public MyUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<ApplicationUser> passwordHasher,
  4. 4           IEnumerable<IUserValidator<ApplicationUser>> userValidators, IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<ApplicationUser>> logger)
  5. 5            : base(store, optionsAccessor, new MyPasswordHasher(), userValidators, passwordValidators, keyNormalizer, errors, services, logger)
  6. 6         {
  7. 7             optionsAccessor.Value.Password.RequireDigit = false;
  8. 8             optionsAccessor.Value.Password.RequiredLength = 4;
  9. 9             optionsAccessor.Value.Password.RequireLowercase = false;
  10. 10             optionsAccessor.Value.Password.RequireUppercase = false;
  11. 11             optionsAccessor.Value.Password.RequireNonAlphanumeric = false;
  12. 12         }
  13. 13
  14. 14     }
复制代码
View Code重写验证密码的方法类MyResourceOwnerPasswordValidator,(如果没有打开Program中的AddResourceOwnerValidator() 则不需要)
  1. public class MyResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
  2.     {
  3.         public readonly SignInManager<ApplicationUser> signInManager;
  4.         private readonly MyUserManager userManager;
  5.         //public readonly IEventService service;
  6.         public MyResourceOwnerPasswordValidator(MyUserManager userService, SignInManager<ApplicationUser> signInManager)//, IEventService service)
  7.         {
  8.             userManager = userService;
  9.             this.signInManager = signInManager;
  10.             //this.service = service;
  11.         }
  12.         public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
  13.         {
  14.             if (string.IsNullOrEmpty(context.UserName) || string.IsNullOrEmpty(context.Password))
  15.             {
  16.                 context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "验证被拒绝,用户名或者密码为空。");
  17.                 return;
  18.             }
  19.             var user = await userManager.FindByNameAsync(context.UserName);
  20.             if (user == null)
  21.             {
  22.                 context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "验证失败,不存在当前用户。");
  23.                 return;
  24.             }
  25.             //检验用户密码(虽然我也不知道他的密码是采用什么加密方式得到的,但是我也不需要知道)
  26.             var passwordPass = await userManager.CheckPasswordAsync(user, context.Password);
  27.             if (!passwordPass)
  28.             {
  29.                 context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "验证失败,用户凭证错误");
  30.                 return;
  31.             }
  32.             else
  33.             {
  34.                 try
  35.                 {
  36.                     await userManager.AddLoginAsync(user, new UserLoginInfo(user.Id, "", user.UserName));
  37.                 }
  38.                 catch (Exception ex)
  39.                 {
  40.                     ;
  41.                 }
  42.                 finally
  43.                 {
  44.                     context.Result = new GrantValidationResult(user.Id, GrantType.ResourceOwnerPassword, new List<Claim>() { new Claim("account", user.UserName) });
  45.                 }
  46.             }
  47.             return;
  48.         }
  49.     }
复制代码
View CodeMyPasswordHasher
  1. 1 public class MyPasswordHasher : PasswordHasher<ApplicationUser>
  2. 2     {
  3. 3         public override string HashPassword(ApplicationUser user, string password)
  4. 4         {
  5. 5             //PasswordHasher<ApplicationUser> ph = new PasswordHasher<ApplicationUser>();
  6. 6             //var pstr = ph.HashPassword(new ApplicationUser(), password);
  7. 7             //return pstr;
  8. 8             return password.MD5();
  9. 9         }
  10. 10
  11. 11         public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
  12. 12         {
  13. 13             if (providedPassword.MD5().Equals(hashedPassword))
  14. 14             {
  15. 15                 return PasswordVerificationResult.Success;
  16. 16             }
  17. 17             else
  18. 18             {
  19. 19                 return PasswordVerificationResult.Failed;
  20. 20             }
  21. 21         }
  22. 22     }
复制代码
View Code创建自己的User类 ApplicationUser继承 IdentityUser  复写自带的AspNetUser表
  1.   public class ApplicationUser : IdentityUser
  2.     {
  3.         public string MySomething { get; set; } = "";
  4.         /// <summary>
  5.         /// 创建时间
  6.         /// </summary>
  7.         public DateTime CreateTime { get; set; }
  8.         /// <summary>
  9.         /// 创建人Id
  10.         /// </summary>
  11.         public string CreatorId { get; set; } = "";
  12.         /// <summary>
  13.         /// 否已删除
  14.         /// </summary>
  15.         public bool Deleted { get; set; }
  16.          
  17.         /// <summary>
  18.         /// 姓名
  19.         /// </summary>
  20.         public string RealName { get; set; }
  21.         /// <summary>
  22.         /// 性别
  23.         /// </summary>
  24.         public Sex Sex { get; set; }
  25.         /// <summary>
  26.         /// 出生日期
  27.         /// </summary>
  28.         public DateTime? Birthday { get; set; }
  29.         /// <summary>
  30.         /// 所属部门Id
  31.         /// </summary>
  32.         public string DepartmentId { get; set; } = "";
  33.         public string OtherData { get; set; } = "";
  34.         // 用户角色 用户权限 用户信息 用户登录tokens  重新绑定与父类的关系 命名必须和父类一致
  35.         public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; }
  36.         public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
  37.         public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
  38.         public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
  39.     }
  40.     public enum Sex
  41.     {
  42.         [Description("男")]
  43.         Man = 1,
  44.         [Description("女")]
  45.         Woman = 0
  46.     }
复制代码
View Code至此可以生成数据库迁移后 Postman测试一下

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表