IdentityServer4(六):集成ASP.NET Core Identity


此前我们已经使用 EFCoreIdentityServer4相关配置写入 SqlServer,但是用户数据还是写死的TestUser,本篇将集成 ASP.NET Core Identity,将用户数据保存到 SqlServer中,当然,您也可以使用自建的用户数据库。

开始前先安装必要的nuget包

Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore -Version 3.1.1
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 3.1.1

添加上下文

public class AspNetAccountDbContext : IdentityDbContext<ApplicationUser>
{
    public AspNetAccountDbContext(DbContextOptions<AspNetAccountDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
}

向容器中添加服务

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AspNetAccountDbContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("DefaultAspNetAccountConnection"));
    });
    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<AspNetAccountDbContext>()
        .AddDefaultTokenProviders();
    services.Configure<IdentityOptions>(options =>
    {
    	// 密码复杂度配置
        options.Password.RequireDigit = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;
        options.Password.RequireLowercase = false;
        options.Password.RequireNonAlphanumeric = false;
        options.Password.RequireUppercase = false;
    });
    // 为了代码简单一点,后面的配置省略,可参考前文
}

登录控制器的修改

删除原先的TestUserStore,使用ASP.NET Core Identity进行操作

public class AccountController : Controller
{
    private UserManager<ApplicationUser> _userManager;
    private SignInManager<ApplicationUser> _signInManager;
    private IIdentityServerInteractionService _interaction;

    public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IIdentityServerInteractionService interaction)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _interaction = interaction;
    }
    public IActionResult Login(string returnUrl)
    {
        ViewData["ReturnUrl"] = returnUrl;
        return View();
    }
            [HttpPost]
    public async Task<IActionResult> Login(LoginViewModel loginViewModel, string returnUrl)
    {
        if (!ModelState.IsValid)
        {
            return View();
        }

        var user = await _userManager.FindByEmailAsync(loginViewModel.Email);
        if (user == null)
        {
            ModelState.AddModelError(nameof(loginViewModel.Email), $"Email {loginViewModel.Email} not exists");
        }
        else
        {
            if (await _userManager.CheckPasswordAsync(user, loginViewModel.Password))
            {
                AuthenticationProperties props = null;
                if (loginViewModel.RememberMe)
                {
                    props = new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(30))
                    };
                }

                await _signInManager.SignInAsync(user, props);

                if (_interaction.IsValidReturnUrl(returnUrl))
                {
                    return Redirect(returnUrl);
                }
                return Redirect("~/");
            }
            ModelState.AddModelError(nameof(loginViewModel.Password), "Wrong password");
        }
        return View(loginViewModel);
    }
}

数据迁移

执行命令

add-migration InitialAspNetAccountDbMigration -c AspNetAccountDbContext -o Data/Migrations/Application/AspNetAccountDb

可以看到成功添加了迁移代码
在这里插入图片描述
执行命令生成数据库

update-database -c AspNetAccountDbContext

成功生成
在这里插入图片描述

播种默认用户数据

public class SeedData
{
    public static void EnsureSeedAspNetAccountData(string connectionString)
    {
        var services = new ServiceCollection();
        services.AddLogging();
        services.AddDbContext<AspNetAccountDbContext>(options =>
        {
            options.UseSqlServer(connectionString);
        });

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<AspNetAccountDbContext>()
            .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>(options =>
        {
            options.Password.RequireDigit = true;
            options.Password.RequiredLength = 6;
            options.Password.RequiredUniqueChars = 1;
            options.Password.RequireLowercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = false;
        });

        using (var serviceProvider = services.BuildServiceProvider())
        {
            using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                var context = scope.ServiceProvider.GetService<AspNetAccountDbContext>();
                context.Database.Migrate();

                var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();

                var zhangsan = userManager.FindByNameAsync("zhangsan").Result;
                if (zhangsan == null)
                {
                    zhangsan = new ApplicationUser
                    {
                        UserName = "zhangsan",
                        Email = "[email protected]"
                    };
                    var result = userManager.CreateAsync(zhangsan, "123456").Result;
                    if (!result.Succeeded)
                    {
                        throw new Exception(result.Errors.First().Description);
                    }
                    result = userManager.AddClaimsAsync(zhangsan, new Claim[] {
                        new Claim(JwtClaimTypes.Name, "张三"),
                        new Claim(JwtClaimTypes.GivenName, "三"),
                        new Claim(JwtClaimTypes.FamilyName, "张"),
                        new Claim(JwtClaimTypes.Email, "[email protected]"),
                        new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                        new Claim(JwtClaimTypes.WebSite, "http://zhangsan.com"),
                        new Claim(JwtClaimTypes.Address, @"{ '城市': '杭州', '邮政编码': '310000' }",
                            IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json)
                    }).Result;

                    if (!result.Succeeded)
                    {
                        throw new Exception(result.Errors.First().Description);
                    }
                }
                // 为了代码简单一点,删除其他用户数据
            }
        }
    }
}

当我们成功运行程序后,查看数据库,可以看到种子数据已经插入
在这里插入图片描述

更多

可访问GitHub查看源码

发布了125 篇原创文章 · 获赞 37 · 访问量 35万+

猜你喜欢

转载自blog.csdn.net/zhaobw831/article/details/104001309