ASP.NET Identity 学习

  1. 创建一个Asp.net core mvc项目

    添加Nuget包:

    • Microsoft.EntityFrameworkCore.SqlServer 3.1.3
    • Microsoft.EntityFrameworkCore.Tools 3.1.3
    • Microsoft.AspNetCore.Identity.EntityFrameworkCore 3.1.3
  2. 更改HomeController类的内容

  1. public IActionResult Index()
  2. {
  3. return View(new Dictionary<string, object> { ["Placeholder"]="Placeholder"});
  4. }

更改HomeController的Index视图内容:

  1. @{
  2. ViewData["Title"] = "首页";
  3. }
  4. @model Dictionary<string, object>
  5. <div class="bg-primary m-1 p-1 text-white"><h4>用户详情</h4></div>
  6. <table class="table table-sm table-bordered m-1 p-1">
  7. @foreach (var kvp in Model)
  8. {
  9. <tr><th>@kvp.Key</th><td>@kvp.Value</td></tr>
  10. }
  11. </table>
  1. 在Models文件夹下创建AppUser类,继承自IdentityUser
  1. using Microsoft.AspNetCore.Identity;
  2. namespace IdentityDemo.Models
  3. {
  4. public class AppUser:IdentityUser
  5. {
  6. }
  7. }
  1. 在Model文件夹下创建DbContext:AppIdentityDbContext
  1. using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
  2. using Microsoft.EntityFrameworkCore;
  3. namespace IdentityDemo.Models
  4. {
  5. public class AppIdentityDbContext:IdentityDbContext<AppUser>
  6. {
  7. public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options):base(options)
  8. {
  9. }
  10. }
  11. }
  1. 配置数据库连接

    在appsettings.json中配置数据库连接
  1. {
  2. "Data": {
  3. "IdentityDemo": {
  4. "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=IdentityDemo;Trusted_Connection=True;MultipleActiveResultSets=true"
  5. },
  6. "Logging": {
  7. "LogLevel": {
  8. "Default": "Information",
  9. "Microsoft": "Warning",
  10. "Microsoft.Hosting.Lifetime": "Information"
  11. }
  12. },
  13. "AllowedHosts": "*"
  14. }
  1. 在Startup.cs中读取配置文件中的数据库链接地址
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using IdentityDemo.Models;
  6. using Microsoft.AspNetCore.Builder;
  7. using Microsoft.AspNetCore.Hosting;
  8. using Microsoft.AspNetCore.HttpsPolicy;
  9. using Microsoft.AspNetCore.Identity;
  10. using Microsoft.EntityFrameworkCore;
  11. using Microsoft.Extensions.Configuration;
  12. using Microsoft.Extensions.DependencyInjection;
  13. using Microsoft.Extensions.Hosting;
  14. namespace IdentityDemo
  15. {
  16. public class Startup
  17. {
  18. public Startup(IConfiguration configuration)
  19. {
  20. Configuration = configuration;
  21. }
  22. public IConfiguration Configuration { get; }
  23. // This method gets called by the runtime. Use this method to add services to the container.
  24. public void ConfigureServices(IServiceCollection services)
  25. {
  26. //配置数据库连接
  27. services.AddDbContext<AppIdentityDbContext>(
  28. options => options.UseSqlServer(Configuration["Data:IdentityDemo:ConnectionString"])
  29. );
  30. //配置Identity
  31. services.AddIdentity<AppUser, IdentityRole>()
  32. .AddEntityFrameworkStores<AppIdentityDbContext>()
  33. .AddDefaultTokenProviders();
  34. services.AddControllersWithViews();
  35. }
  36. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  37. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  38. {
  39. app.UseStatusCodePages();
  40. if (env.IsDevelopment())
  41. {
  42. app.UseDeveloperExceptionPage();
  43. }
  44. else
  45. {
  46. app.UseExceptionHandler("/Home/Error");
  47. // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
  48. app.UseHsts();
  49. }
  50. app.UseHttpsRedirection();
  51. app.UseStaticFiles();
  52. app.UseRouting();
  53. app.UseAuthorization();
  54. app.UseEndpoints(endpoints =>
  55. {
  56. endpoints.MapControllerRoute(
  57. name: "default",
  58. pattern: "{controller=Home}/{action=Index}/{id?}");
  59. });
  60. }
  61. }
  62. }
  1. 添加数据库迁移
  1. add-migrations InitialCreate
  2. update database
  1. 列举用户账户
  1. using IdentityDemo.Models;
  2. using Microsoft.AspNetCore.Identity;
  3. using Microsoft.AspNetCore.Mvc;
  4. namespace IdentityDemo.Controllers
  5. {
  6. public class AdminController : Controller
  7. {
  8. private UserManager<AppUser> userManager;
  9. //构造函数注入,获取UserManager
  10. public AdminController(UserManager<AppUser> usrMgr)
  11. {
  12. userManager = usrMgr;
  13. }
  14. public IActionResult Index()
  15. {
  16. return View(userManager.Users);
  17. }
  18. }
  19. }

视图修改 Index.cshtml:

  1. @model IEnumerable<AppUser>
  2. @{
  3. ViewData["Title"] = "Index";
  4. }
  5. <div class="bg-primary m-1 p-1 text-white"><h4>用户账号</h4></div>
  6. <table class="table table-sm table-bordered">
  7. <tr><th>ID</th><th>用户名</th><th>邮箱</th></tr>
  8. @if (Model.Count() == 0)
  9. {
  10. <tr><td colspan="3" class="text-center">没有</td></tr>
  11. }
  12. else
  13. {
  14. foreach (AppUser user in Model)
  15. {
  16. <tr>
  17. <td>@user.Id</td>
  18. <td>@user.UserName</td>
  19. <td>@user.Email</td>
  20. </tr>
  21. }
  22. }
  23. </table>
  24. <a class="btn btn-primary" asp-action="Create">创建</a>
  1. 创建用户

    1). 创建用户视图模型 UserViewModels
  1. public class CreateModel
  2. {
  3. [Required]
  4. [Display(Name = "用户名")]
  5. public string Name { get; set; }
  6. [Required]
  7. [DataType(DataType.EmailAddress)]
  8. [Display(Name = "电子邮箱")]
  9. public string Email { get; set; }
  10. [Required]
  11. [DataType(DataType.Password)]
  12. [Display(Name="密码")]
  13. public string Password { get; set; }
  14. }
  1. 添加Action方法

    在AdminController中添加Create方法:
  1. /// <summary>
  2. /// 创建用户
  3. /// </summary>
  4. /// <returns></returns>
  5. public ViewResult Create() => View();
  6. [HttpPost]
  7. public async Task<IActionResult> Create(CreateModel model)
  8. {
  9. if (ModelState.IsValid)
  10. {
  11. AppUser user = new AppUser
  12. {
  13. UserName = model.Name,
  14. Email = model.Email
  15. };
  16. ///创建用户
  17. IdentityResult result = await userManager.CreateAsync(user, model.Password);
  18. if (result.Succeeded) //成功则返回列表页
  19. {
  20. return RedirectToAction("Index");
  21. }
  22. else
  23. {
  24. foreach (IdentityError error in result.Errors)
  25. {
  26. ModelState.AddModelError("", error.Description);
  27. }
  28. }
  29. }
  30. return View(model);
  31. }
  1. 创建用户测试
  1. ctrl+F5运行程序,访问 "https://localhost:44382/Admin/Create" ,填写用户名Joe,邮箱:joe@example.com,密码:Secret123$。点击"创建",创建用户成功。
  2. 再次输入相同的用户名,提示“User name 'Joe' is already taken.”
  3. 更改第一步中的用户名为Alice,密码为secret,创建用户时会提示密码强度不够的信息。因为Asp.net内置密码验证规则。
  1. 更改密码验证规则

    在Startup类的ConfigureServices方法中,配置密码验证规则:
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. //配置数据库连接
  4. services.AddDbContext<AppIdentityDbContext>(
  5. options => options.UseSqlServer(Configuration["Data:IdentityDemo:ConnectionString"])
  6. );
  7. //配置Identity的密码验证规则
  8. //规则为至少六位
  9. services.AddIdentity<AppUser, IdentityRole>(opts =>
  10. {
  11. opts.Password.RequiredLength = 6;
  12. opts.Password.RequireNonAlphanumeric = false;
  13. opts.Password.RequireLowercase = false;
  14. opts.Password.RequireUppercase = false;
  15. opts.Password.RequireDigit = false;
  16. }).AddEntityFrameworkStores<AppIdentityDbContext>()
  17. .AddDefaultTokenProviders();
  18. services.AddControllersWithViews();
  19. }
  1. 自定义密码验证器类

    自定义密码验证规则除了上面一种方法,还可以自定义类,实现IPasswordValidator接口或者继承自UserValidator,接口定义:
  1. using System.Threading.Tasks;
  2. namespace Microsoft.AspNetCore.Identity {
  3. public interface IPasswordValidator<TUser> where TUser : class {
  4. Task<IdentityResult> ValidateAsync(UserManager<TUser> manager,
  5. TUser user, string password);
  6. }
  7. }

CustomPasswordValidator类:

  1. using Microsoft.AspNetCore.Identity;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using IdentityDemo.Models;
  6. namespace IdentityDemo.Infrastructure
  7. {
  8. /// <summary>
  9. /// 自定义用户密码验证规则
  10. /// </summary>
  11. public class CustomPasswordValidator : UserValidator<AppUser>
  12. {
  13. public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
  14. {
  15. IdentityResult result = await base.ValidateAsync(manager, user);
  16. List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
  17. if (!user.Email.ToLower().EndsWith("@example.com"))
  18. {
  19. errors.Add(new IdentityError
  20. {
  21. Code = "EmailIdentityError",
  22. Description = "只允许example.com的邮箱地址注册账号"
  23. });
  24. }
  25. return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
  26. }
  27. }
  28. }

在Startup类的ConfigureServices中注入服务:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. //自定义密码验证服务
  4. services.AddTransient<IPasswordValidator<AppUser>, CustomPasswordValidator>();
  5. //配置数据库连接
  6. services.AddDbContext<AppIdentityDbContext>(
  7. options => options.UseSqlServer(Configuration["Data:IdentityDemo:ConnectionString"])
  8. );
  9. //配置Identity
  10. services.AddIdentity<AppUser, IdentityRole>(opts =>
  11. {
  12. opts.Password.RequiredLength = 6;
  13. opts.Password.RequireNonAlphanumeric = false;
  14. opts.Password.RequireLowercase = false;
  15. opts.Password.RequireUppercase = false;
  16. opts.Password.RequireDigit = false;
  17. }).AddEntityFrameworkStores<AppIdentityDbContext>()
  18. .AddDefaultTokenProviders();
  19. services.AddControllersWithViews();
  20. }
  1. 用户名验证码规则

    用户名验证规则有两种:通过配置和自定义验证类。

1). 通过配置,在Startup类的ConfigureServices方法中配置

  1. //配置Identity
  2. services.AddIdentity<AppUser, IdentityRole>(opts =>
  3. {
  4. opts.User.RequireUniqueEmail = true;
  5. opts.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyz";
  6. opts.Password.RequiredLength = 6;
  7. opts.Password.RequireNonAlphanumeric = false;
  8. opts.Password.RequireLowercase = false;
  9. opts.Password.RequireUppercase = false;
  10. opts.Password.RequireDigit = false;
  11. }).AddEntityFrameworkStores<AppIdentityDbContext>()
  12. .AddDefaultTokenProviders();

2). 自定义验证规则类,实现IUserValidator接口

  1. using Microsoft.AspNetCore.Identity;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using IdentityDemo.Models;
  6. namespace IdentityDemo.Infrastructure
  7. {
  8. /// <summary>
  9. /// 自定义用户名或者邮箱验证规则
  10. /// </summary>
  11. public class CustomUserValidator : UserValidator<AppUser>
  12. {
  13. public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
  14. {
  15. IdentityResult result = await base.ValidateAsync(manager, user);
  16. List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
  17. if (!user.Email.ToLower().EndsWith("@example.com"))
  18. {
  19. errors.Add(new IdentityError
  20. {
  21. Code = "EmailIdentityError",
  22. Description = "只允许example.com的邮箱地址注册账号"
  23. });
  24. }
  25. return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
  26. }
  27. }
  28. }

在Startup类中,配置依赖注入:

  1. services.AddTransient<IUserValidator<AppUser>,CustomUserValidator>();
  1. 编辑、删除用户功能

    1). 在用户列表页,添加编辑、删除按钮:Index.cshtml:
  1. @model IEnumerable<AppUser>
  2. @{
  3. ViewData["Title"] = "Index";
  4. }
  5. <div class="bg-primary m-1 p-1 text-white"><h4>用户账号</h4></div>
  6. <table class="table table-sm table-bordered">
  7. <tr><th>ID</th><th>用户名</th><th>邮箱</th><th>操作</th></tr>
  8. @if (Model.Count() == 0)
  9. {
  10. <tr><td colspan="3" class="text-center">没有</td></tr>
  11. }
  12. else
  13. {
  14. foreach (AppUser user in Model)
  15. {
  16. <tr>
  17. <td>@user.Id</td>
  18. <td>@user.UserName</td>
  19. <td>@user.Email</td>
  20. <td>
  21. <form asp-action="Delete" asp-route-id="@user.Id" method="post">
  22. <a class="btn btn-sm btn-primary" asp-action="Edit"
  23. asp-route-id="@user.Id">编辑</a>
  24. <button type="submit"
  25. class="btn btn-sm btn-danger">
  26. 删除
  27. </button>
  28. </form>
  29. </td>
  30. </tr>
  31. }
  32. }
  33. </table>
  34. <a class="btn btn-primary" asp-action="Create">创建</a>

2). 删除用户

  1. //删除用户
  2. [HttpPost]
  3. public async Task<IActionResult> Delete(string id)
  4. {
  5. AppUser user = await userManager.FindByIdAsync(id);
  6. if (user != null)
  7. {
  8. IdentityResult result = await userManager.DeleteAsync(user);
  9. if (result.Succeeded)
  10. {
  11. return RedirectToAction("Index");
  12. }
  13. else
  14. {
  15. AddErrorsFromResult(result);
  16. }
  17. }
  18. else
  19. {
  20. ModelState.AddModelError("", "User Not Found");
  21. }
  22. return View("Index", userManager.Users);
  23. }
  24. private void AddErrorsFromResult(IdentityResult result)
  25. {
  26. foreach (IdentityError error in result.Errors)
  27. {
  28. ModelState.AddModelError("", error.Description);
  29. }
  30. }

3). 编辑用户

  1. /// <summary>
  2. /// 编辑用户
  3. /// </summary>
  4. /// <param name="id"></param>
  5. /// <returns></returns>
  6. public async Task<IActionResult> Edit(string id)
  7. {
  8. AppUser user = await userManager.FindByIdAsync(id);
  9. if (user != null)
  10. {
  11. return View(user);
  12. }
  13. else
  14. {
  15. return RedirectToAction("Index");
  16. }
  17. }
  18. /// <summary>
  19. /// 编辑用户
  20. /// </summary>
  21. /// <param name="id"></param>
  22. /// <param name="email"></param>
  23. /// <param name="password"></param>
  24. /// <returns></returns>
  25. [HttpPost]
  26. public async Task<IActionResult> Edit(string id, string email,
  27. string password)
  28. {
  29. AppUser user = await userManager.FindByIdAsync(id);
  30. if (user != null)
  31. {
  32. user.Email = email;
  33. //用户邮箱校验
  34. IdentityResult validEmail = await userValidator.ValidateAsync(userManager, user);
  35. if (!validEmail.Succeeded)
  36. {
  37. AddErrorsFromResult(validEmail);
  38. }
  39. IdentityResult validPass = null;
  40. if (!string.IsNullOrEmpty(password))
  41. {
  42. //用户密码校验
  43. validPass = await passwordValidator.ValidateAsync(userManager, user, password);
  44. if (validPass.Succeeded)
  45. {
  46. //用户密码加密
  47. user.PasswordHash = passwordHasher.HashPassword(user, password);
  48. }
  49. else
  50. {
  51. AddErrorsFromResult(validPass);
  52. }
  53. }
  54. //1. 只修改了邮箱,2. 修改了邮箱和密码
  55. if ((validEmail.Succeeded && validPass == null) || (validEmail.Succeeded && password != string.Empty && validPass.Succeeded))
  56. {
  57. IdentityResult result = await userManager.UpdateAsync(user); //更新用户信息s
  58. if (result.Succeeded)
  59. {
  60. return RedirectToAction("Index");
  61. }
  62. else
  63. {
  64. AddErrorsFromResult(result);
  65. }
  66. }
  67. }
  68. else
  69. {
  70. ModelState.AddModelError("", "User Not Found");
  71. }
  72. return View(user);
  73. }

编辑用户的视图:

Edit.cshtml:

  1. @model AppUser
  2. @{
  3. ViewData["Title"] = "修改用户信息";
  4. }
  5. <div class="bg-primary m-1 p-1"><h4>修改用户信息</h4></div>
  6. <div asp-validation-summary="All" class="text-danger"></div>
  7. <form asp-action="Edit" method="post">
  8. <div class="form-group">
  9. <label asp-for="Id"></label>
  10. <input asp-for="Id" class="form-control" disabled />
  11. </div>
  12. <div class="form-group">
  13. <label asp-for="Email"></label>
  14. <input asp-for="Email" class="form-control" />
  15. </div>
  16. <div class="form-group">
  17. <label for="password">Password</label>
  18. <input name="password" class="form-control" />
  19. </div>
  20. <button type="submit" class="btn btn-primary">保存</button>
  21. <a asp-action="Index" class="btn btn-secondary">取消</a>
  22. </form>

asp.net core identity学习1的更多相关文章

  1. ASP.NET Core Identity Hands On(1)——Identity 初次体验

    ASP.NET Core Identity是用于构建ASP.NET Core Web应用程序的成员资格系统,包括成员资格.登录和用户数据存储 这是来自于 ASP.NET Core Identity 仓 ...

  2. ASP.NET Core Identity Hands On(2)——注册、登录、Claim

    上一篇文章(ASP.NET Core Identity Hands On(1)--Identity 初次体验)中,我们初识了Identity,并且详细分析了AspNetUsers用户存储表,这篇我们将 ...

  3. ASP.NET Core Identity 实战(2)——注册、登录、Claim

    上一篇文章(ASP.NET Core Identity Hands On(1)--Identity 初次体验)中,我们初识了Identity,并且详细分析了AspNetUsers用户存储表,这篇我们将 ...

  4. ASP.NET Core Identity 实战(4)授权过程

    这篇文章我们将一起来学习 Asp.Net Core 中的(注:这样描述不准确,稍后你会明白)授权过程 前情提要 在之前的文章里,我们有提到认证和授权是两个分开的过程,而且认证过程不属于Identity ...

  5. 用一个应用场景理解ASP.NET Core Identity是什么?

    目录 前言 基于声明的认证(Claims-based Authentication) 应用场景一 在ASP.NET Core 中Identity是如何实现的 类ClaimsPrincipal 考察另外 ...

  6. 用例子看ASP.NET Core Identity是什么?

    原文:用例子看ASP.NET Core Identity是什么? 目录 前言 基于声明的认证(Claims-based Authentication) Claim 在ASP.NET Core Iden ...

  7. ASP.NET Core Identity 配置 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Identity 配置 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Identity 配置 上一章节我们简单介绍了下 Id ...

  8. ASP.NET Core Identity 框架 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Identity 框架 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Identity 框架 前面我们使用了 N 多个章节, ...

  9. 使用WebApi和Asp.Net Core Identity 认证 Blazor WebAssembly(Blazor客户端应用)

    原文:https://chrissainty.com/securing-your-blazor-apps-authentication-with-clientside-blazor-using-web ...

随机推荐

  1. CF 997A

    You’ve got a string a1,a2,…,an, consisting of zeros and ones.Let’s call a sequence of consecutive el ...

  2. RabbitMQ 交换机类型

    1,扇形交换机 fanout 2, 直连交换机 direct 3, 通配符交换机 topic

  3. [HDU2546]饭卡<dp 01背包>

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2546 #题目描述: 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前, ...

  4. yum-程序包管理器前端工具

    一.要想使用yum先要指定yum源 /etc/yum.com /etc/yum.repos.d/*repo 一.yum的使用 yum [option] command  包名 option -y: c ...

  5. 人工智能新手入门学习路线和学习资源合集(含AI综述/python/机器学习/深度学习/tensorflow)

    [说在前面]本人博客新手一枚,象牙塔的老白,职业场的小白.以下内容仅为个人见解,欢迎批评指正,不喜勿喷![握手][握手] 1. 分享个人对于人工智能领域的算法综述:如果你想开始学习算法,不妨先了解人工 ...

  6. MVC分层设计

    MVC分层设计 什么是MVC? MVC 是一种软件架构模式,利用分层的思想来设计交互式应用程序,由以下3层组成: Model 业务模型层. View 展示层. Controller 控制层. MVC包 ...

  7. java文件中字母出现的次数和百分比

    主要是文件的读写.先在代码中导入文件.一行一行的进行数据的读入,通过“  ”空格对读入的信息进行分割,存入到数组里之后对于每一个单词的每一个字母进行区分存入相应的字母数组里.最后统计总的字母个数.应用 ...

  8. docker-compose 部分错误

    Get https://hub.17kxkx.com/v2/: dial tcp 39.106.209.67:443: connect: connection refused vim /etc/doc ...

  9. C语言 刷新缓冲区

    fflush int fflush(FILE* stream); 用于清空文件缓冲区,如果文件是以写的方式打开 的,则把缓冲区内容写入文件. eg: 1. #include <stdio.h&g ...

  10. Linux 磁盘管理篇,目录管理(一)

    目录:     当我们在linux的ext2档案建立一个目录时,ext2会分配一个inode与至少一块Block给该目录,其中inode记录该目录在相关属性,并指向分配到在那块Block,而block ...