• <九>集成ASP.NETCore Identity 作为授权账户持久到数据库


    我们之前都是用Identityserver4的测试类把数据添加到内存了,目的是为了测试方便,

    现在我们把用户的信息利用ASP.NET Identity的方式持久化到数据库中。

    1、引入Identityserver4.AspNetIdentity,然后新建一个ApplicationUser,ApplicationRole的类

    public class ApplicationUser : IdentityUser<string>//不加int的话是默认主键为guid
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public override string Id { get; set; }

    }

    public class ApplicationUserRoles : IdentityRole<string>
    {
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      [Key]
      public override string Id { get; set; }
    }

    2、替换服务端stratup中 .AddTestUsers(Config.GetUsers().ToList()) 换成

    public void ConfigureServices(IServiceCollection services)
    {
    services.Configure<CookiePolicyOptions>(options =>
    {
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
    {
    options.UseSqlServer(Configuration.GetConnectionString("Conn"));
    });

    //配置Identity
    services.AddIdentity<ApplicationUser, ApplicationUserRoles>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();
    //修改Identity密码强度设置配置
    services.Configure<IdentityOptions>(options =>
    {
    options.Password.RequireLowercase = false; //需要小写
    options.Password.RequireNonAlphanumeric = false; //需要字母
    options.Password.RequireUppercase = false; //需要大写
    options.Password.RequiredLength = 6;
    });

    services.AddIdentityServer().AddDeveloperSigningCredential()
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryApiScopes(Config.GetScopes())
    .AddInMemoryClients(Config.GetClients())
    // .AddTestUsers(Config.GetUsers().ToList())
    .AddAspNetIdentity<ApplicationUser>()
    .AddInMemoryIdentityResources(Config.GetIdentityResources());

    services.AddControllersWithViews();
    }

    3、替换登录逻辑,将Testuser的登录逻辑换成Identity的登录逻辑

      public class AccountController : Controller
        {
            // private readonly TestUserStore _testUserStore;
            private readonly UserManager<ApplicationUser> _userManager;
            private readonly SignInManager<ApplicationUser> _signinManager;
            private readonly IIdentityServerInteractionService _InteractionService;
            public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signinManager, IIdentityServerInteractionService identityServerInteractionService)
            {
                _userManager = userManager;
                _signinManager = signinManager;
                _InteractionService = identityServerInteractionService;
            }
            //public AccountController( TestUserStore testUserStore) 
            //{
            //    _testUserStore = testUserStore;       
            //}
            public IActionResult Index()
            {
                return View();
            }
    
    
            public IActionResult Login(string returnUrl = "/Home/Index")
            {
                ViewData["Rurl"] = returnUrl;
                return View();
            }
    
            /// <summary>
            /// post 登录请求
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public async Task<IActionResult> Login(LoginInputModel model)
            {
                if (!ModelState.IsValid)
                {
                    return View();
                }
                var user = await _userManager.FindByNameAsync(model.Name);
                // var user = _testUserStore.FindByUsername(model.Username);
                if (user == null)
                {
                    return View();
                }
                //if (_testUserStore.ValidateCredentials(model.Username, model.Password))
                if (await _userManager.CheckPasswordAsync(user, model.Password))
                {
                    var props = new AuthenticationProperties
                    {
                        IsPersistent = false,     //是否记住。默认不记住。可以根据前端的传值改。
                        ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(1))
                    };
                    // await HttpContext.SignInAsync(user.SubjectId, user.Username, props);
                    //await AuthenticationManagerExtensions.SignInAsync(
                    //    HttpContext,
                    //    new IdentityServerUser(user.SubjectId),
                    //    props
                    //    );
    
                    await _signinManager.SignInAsync(user, props);
                    if (!string.IsNullOrEmpty(model.ReturnUrl))
                    //if (_InteractionService.IsValidReturnUrl(model.ReturnUrl))
                    {
                        return Redirect(model.ReturnUrl);
                    }
                    else
                    {
                        return Redirect("~/");
                    }
                }
                return View();
            }
    
            /// <summary>
            /// 退出登录
            /// </summary>
            /// <returns></returns>
            public async Task<IActionResult> Logout()
            {
                await _signinManager.SignOutAsync();
                return Redirect("/Login");
            }
        }

     4、新增一个data文件夹用于存放初始化 数据库的相关类 

    public class ApplicationDbContext :IdentityDbContext<ApplicationUser,ApplicationUserRoles,string>
        {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
            {
    
            }
        }

     种子文件:数据库没有数据时,运行的时候给添加一个默认账户

     public class ApplicationDbContextSeed
        {
            private UserManager<ApplicationUser> _userManager;
            private RoleManager<ApplicationUserRoles> _roleManager;
    
            public async Task SeedAsync(ApplicationDbContext context, IServiceProvider services)
            {
                if (!context.Roles.Any())
                {
                    var role = new ApplicationUserRoles()
                    {
                        Id="111",
                        Name = "Administrators",
                        NormalizedName = "Administrators"
                    };
                    _roleManager = services.GetRequiredService<RoleManager<ApplicationUserRoles>>();
                    var result = await _roleManager.CreateAsync(role);
                    if (!result.Succeeded)
                    {
                        throw new Exception("初始默认角色失败:"+result.Errors.SelectMany(e=>e.Description));
                    }
                }
    
                if (!context.Users.Any())
                {
                    _userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
    
                    var defaultUser = new ApplicationUser
                    {
                        Id="111111",
                        UserName = "Administrator",
                        Email = "11111111@qq.com",
                        NormalizedUserName = "admin",
                        SecurityStamp = "admin",
                     };
    
    
                    var result = await _userManager.CreateAsync(defaultUser, "123456");
                    await _userManager.AddToRoleAsync(defaultUser, "Administrators");
                    if (!result.Succeeded)
                    {
                        throw new Exception("初始默认用户失败:" + result.Errors.SelectMany(e => e.Description));
                    }
                }
            }
        }

     在程序开始运行前执行种子文件

     public static class WebHostMigrationExtensions
        {
            public static IHost MigrateDbContext<TContext>(this IHost host, Action<TContext, IServiceProvider> sedder) where TContext : DbContext
            {
                using (var scope = host.Services.CreateScope())
                {//只在本区间内有效
                    var services = scope.ServiceProvider;
                    var logger = services.GetRequiredService<ILogger<TContext>>();
                    var context = services.GetService<TContext>();
    
                    try
                    {
                        context.Database.Migrate();
                        sedder(context, services);
    
                        logger.LogInformation($"执行DBContext {typeof(TContext).Name} seed执行成功");
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, $"执行DBContext {typeof(TContext).Name} seed方法失败");
                    }
                }
    
                return host;
            }
        }

     在program中加入启动时运行种子文件

     public static void Main(string[] args)
            {
                 CreateHostBuilder(args).Build()
                 .MigrateDbContext<ApplicationDbContext>((context, services) =>
                {
                    new ApplicationDbContextSeed().SeedAsync(context, services).Wait();
                })
                .Run();
            }

    5、数据库迁移

    1、 Add-Migration
    2、 Update-Database 

    运行完成后生成的数据库表

     至此全部配置完毕,运行程序,数据库会初始化一条数据。

     用该用户名和密码登录成功。

  • 相关阅读:
    arcgis10安装及破解
    11G在用EXP导出时,空表不能导出
    cmd 中键入netstat,net等出现不是内部或外部命令,也不是可运行的程序或批处理文件
    Could not load file or assembly or one of its dependencies. 试图加载格式不正确的程序。
    Spark读写Hbase的二种方式对比
    Handler系列之原理分析
    虚拟目录webconfig的配置
    Smarty的基本使用与总结
    浅谈WEB前后端分离
    学习笔记之MVC级联及Ajax操作
  • 原文地址:https://www.cnblogs.com/choii/p/13915892.html
Copyright © 2020-2023  润新知