前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core分布式项目实战(集成ASP.NETCore Identity)--学习笔记

ASP.NET Core分布式项目实战(集成ASP.NETCore Identity)--学习笔记

作者头像
郑子铭
发布2021-01-13 15:39:42
8010
发布2021-01-13 15:39:42
举报

任务24:集成ASP.NETCore Identity

之前在 Index 页面写了一个 strong 标签,需要加个判断再显示,不然为空没有错误的时候也会显示

代码语言:javascript
复制
@if (!ViewContext.ModelState.IsValid)
{
    <strong>Error""</strong>
    <div asp-validation-summary="All" class="danger"></div>
}

因为 asp-validation-summary 是 asp.net view 视图会自动控制,而 strong 不会,所以要显示标题需要添加一个判断,那么这里我们直接移除掉,当有错误信息的时候直接显示即可,这里作为上一节的补充

代码语言:javascript
复制
<div asp-validation-summary="All" class="danger"></div>

这一节主要把 Identity 加入进来

一开始我们把 startup 中的 Identity 注释掉了,只需要开启即可

添加包 IdentityServer4,IdentityServer4.AspNetIdentity,添加之后就可以把 AddTestUsers 移除掉,它就不会再用测试里面的 user,

Startup.cs
代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
    });

    services.AddIdentity<ApplicationUser, ApplicationUserRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryClients(Config.GetClients())
            .AddInMemoryApiResources(Config.GetApiResource())
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddAspNetIdentity<ApplicationUser>();

    //services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    //    .AddCookie(options => {
    //        options.LoginPath = "/Account/Login";
    //    });

    //services.Configure<IdentityOptions>(options =>
    //{
    //    options.Password.RequireLowercase = true;
    //    options.Password.RequireNonAlphanumeric = true;
    //    options.Password.RequireUppercase = true;
    //    options.Password.RequiredLength = 12;
    //});

    services.AddScoped<ConsentService>();

    services.AddMvc();
}

接下来要到 AccountController 中切换回原先的登录逻辑

AccountController
代码语言:javascript
复制
private UserManager<ApplicationUser> _userManager;
private SignInManager<ApplicationUser> _signInManager;
private IIdentityServerInteractionService _interaction;

//private readonly TestUserStore _users;

//public AccountController(TestUserStore users)
//{
//    _users = users;
//}

public AccountController(UserManager<ApplicationUser> userManager,
    SignInManager<ApplicationUser> signInManager,
    IIdentityServerInteractionService interaction)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _interaction = interaction;
}

接下来改造 AccountController 的 Register 方法,首先把 RegisterViewModel 的 UserName 改回为 Email

RegisterViewModel
代码语言:javascript
复制
public string Email { get; set; }
//public string UserName { get; set; }
AccountController
代码语言:javascript
复制
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel registerViewModel, string returnUrl  = null)
{
    if (ModelState.IsValid)
    {
        ViewData["ReturnUrl"] = returnUrl;
        var identityUser = new ApplicationUser
        {
            Email = registerViewModel.Email,
            UserName = registerViewModel.Email,
            NormalizedUserName = registerViewModel.Email,
        };

        var identityResult = await _userManager.CreateAsync(identityUser, registerViewModel.Password);
        if (identityResult.Succeeded)
        {
            await _signInManager.SignInAsync(identityUser, new AuthenticationProperties { IsPersistent = true });
            return RedirectToLoacl(returnUrl);
        }
        else
        {
            AddErrors(identityResult);
        }
    }

    return View();
}

接着改造 AccountController 的 Login 方法,首先把 LoginViewModel 的 UserName 也改回为 Email,并加上一个 RememberMe 字段

LoginViewModel
代码语言:javascript
复制
public string Email { get; set; }
//public string UserName { get; set; }
public bool RememberMe { get; set; }

调用 UserManager 的查找和登录的逻辑

AccountController
代码语言:javascript
复制
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel loginViewModel,string returnUrl)
{
    if (ModelState.IsValid)
    {
        ViewData["ReturnUrl"] = returnUrl;
        var user = await _userManager.FindByEmailAsync(loginViewModel.Email);
        if (user == null)
        {
            ModelState.AddModelError(nameof(loginViewModel.Email), "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);
}

还原 Logout 方法

Logout
代码语言:javascript
复制
public async Task<IActionResult> Logout()
{
    await _signInManager.SignOutAsync();
    //await HttpContext.SignOutAsync();
    return RedirectToAction("Index", "Home");
}

检查一下 view,将 Login.cshtml 里面的 UserName 修改为 Email,model 改为 LoginViewModel

Login.cshtml
代码语言:javascript
复制
@model LoginViewModel;

恢复 Program 中 EF 的初始化

Program
代码语言:javascript
复制
public static void Main(string[] args)
{
    BuildWebHost(args)
        .MigrateDbContext<ApplicationDbContext>((context, services) =>
        {
            new ApplicationDbContextSeed().SeedAsync(context, services)
            .Wait();
        })
        .Run();
}

启动程序之后会根据 appsettings.json 中的配置创建数据库

appsettings.json
代码语言:javascript
复制
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-IdentitySample-CE9DD12E-9C3B-4072-8E38-6F33420849CB;Trusted_Connection=True;MultipleActiveResultSets=true"
}

编译启动程序,可以看到用户表有一条数据

这条数据来自 ApplicationDbContextSeed

代码语言:javascript
复制
public class ApplicationDbContextSeed
{
    private UserManager<ApplicationUser> _userManager;

    public async Task SeedAsync(ApplicationDbContext context, IServiceProvider services)
    {
        if (!context.Users.Any())
        {
            _userManager = services.GetRequiredService<UserManager<ApplicationUser>>();

            var defaultUser = new ApplicationUser {
                UserName="Administrator",
                Email ="jessetalk@163.com",
                NormalizedUserName ="admin"
            };

            var result = await _userManager.CreateAsync(defaultUser, "Password$123");
            if (!result.Succeeded)
            {
                throw new Exception("初始默认用户失败");
            }
        }
    }
}

浏览器访问

代码语言:javascript
复制
http://localhost:5000/

使用邮箱登录

退出登录之后启动客户端,浏览器访问 5001 之后会跳转到 5000

代码语言:javascript
复制
http://localhost:5001/

输入邮箱和密码之后会来到 consent 页面

点击同意之后跳转到 MvcClient

点击 About 看到用户名是 Administrator,就是数据库里面的用户

这就是我们把程序里面的 TestUserStore 替换为 Identity

课程链接

http://video.jessetalk.cn/course/explore

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 任务24:集成ASP.NETCore Identity
    • Startup.cs
      • AccountController
        • RegisterViewModel
          • AccountController
            • LoginViewModel
              • AccountController
                • Logout
                  • Login.cshtml
                    • Program
                      • appsettings.json
                      • 课程链接
                      相关产品与服务
                      数据库
                      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档