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类的内容

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

更改HomeController的Index视图内容:

@{
ViewData["Title"] = "首页";
}
@model Dictionary<string, object>
<div class="bg-primary m-1 p-1 text-white"><h4>用户详情</h4></div>
<table class="table table-sm table-bordered m-1 p-1">
@foreach (var kvp in Model)
{
<tr><th>@kvp.Key</th><td>@kvp.Value</td></tr>
}
</table>
  1. 在Models文件夹下创建AppUser类,继承自IdentityUser
using Microsoft.AspNetCore.Identity;

namespace IdentityDemo.Models
{
public class AppUser:IdentityUser
{
}
}
  1. 在Model文件夹下创建DbContext:AppIdentityDbContext
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; namespace IdentityDemo.Models
{
public class AppIdentityDbContext:IdentityDbContext<AppUser>
{
public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options):base(options)
{ }
}
}
  1. 配置数据库连接

    在appsettings.json中配置数据库连接
{
"Data": {
"IdentityDemo": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=IdentityDemo;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
  1. 在Startup.cs中读取配置文件中的数据库链接地址
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityDemo.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; namespace IdentityDemo
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//配置数据库连接
services.AddDbContext<AppIdentityDbContext>(
options => options.UseSqlServer(Configuration["Data:IdentityDemo:ConnectionString"])
); //配置Identity
services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders(); services.AddControllersWithViews();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStatusCodePages();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
  1. 添加数据库迁移
add-migrations InitialCreate
update database
  1. 列举用户账户
using IdentityDemo.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; namespace IdentityDemo.Controllers
{
public class AdminController : Controller
{
private UserManager<AppUser> userManager;
//构造函数注入,获取UserManager
public AdminController(UserManager<AppUser> usrMgr)
{
userManager = usrMgr;
}
public IActionResult Index()
{
return View(userManager.Users);
}
}
}

视图修改 Index.cshtml:

@model IEnumerable<AppUser>

@{
ViewData["Title"] = "Index";
}
<div class="bg-primary m-1 p-1 text-white"><h4>用户账号</h4></div>
<table class="table table-sm table-bordered">
<tr><th>ID</th><th>用户名</th><th>邮箱</th></tr>
@if (Model.Count() == 0)
{
<tr><td colspan="3" class="text-center">没有</td></tr>
}
else
{
foreach (AppUser user in Model)
{
<tr>
<td>@user.Id</td>
<td>@user.UserName</td>
<td>@user.Email</td>
</tr>
}
}
</table>
<a class="btn btn-primary" asp-action="Create">创建</a>
  1. 创建用户

    1). 创建用户视图模型 UserViewModels
public class CreateModel
{
[Required]
[Display(Name = "用户名")]
public string Name { get; set; } [Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "电子邮箱")]
public string Email { get; set; } [Required]
[DataType(DataType.Password)]
[Display(Name="密码")]
public string Password { get; set; }
}
  1. 添加Action方法

    在AdminController中添加Create方法:
/// <summary>
/// 创建用户
/// </summary>
/// <returns></returns>
public ViewResult Create() => View(); [HttpPost]
public async Task<IActionResult> Create(CreateModel model)
{
if (ModelState.IsValid)
{
AppUser user = new AppUser
{
UserName = model.Name,
Email = model.Email
};
///创建用户
IdentityResult result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded) //成功则返回列表页
{
return RedirectToAction("Index");
}
else
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
}
return View(model);
}
  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方法中,配置密码验证规则:
public void ConfigureServices(IServiceCollection services)
{
//配置数据库连接
services.AddDbContext<AppIdentityDbContext>(
options => options.UseSqlServer(Configuration["Data:IdentityDemo:ConnectionString"])
); //配置Identity的密码验证规则
//规则为至少六位
services.AddIdentity<AppUser, IdentityRole>(opts =>
{
opts.Password.RequiredLength = 6;
opts.Password.RequireNonAlphanumeric = false;
opts.Password.RequireLowercase = false;
opts.Password.RequireUppercase = false;
opts.Password.RequireDigit = false;
}).AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders(); services.AddControllersWithViews();
}
  1. 自定义密码验证器类

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

CustomPasswordValidator类:

using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityDemo.Models; namespace IdentityDemo.Infrastructure
{
/// <summary>
/// 自定义用户密码验证规则
/// </summary>
public class CustomPasswordValidator : UserValidator<AppUser>
{
public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
{
IdentityResult result = await base.ValidateAsync(manager, user);
List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
if (!user.Email.ToLower().EndsWith("@example.com"))
{
errors.Add(new IdentityError
{
Code = "EmailIdentityError",
Description = "只允许example.com的邮箱地址注册账号"
});
}
return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
}
}
}

在Startup类的ConfigureServices中注入服务:

public void ConfigureServices(IServiceCollection services)
{
//自定义密码验证服务
services.AddTransient<IPasswordValidator<AppUser>, CustomPasswordValidator>(); //配置数据库连接
services.AddDbContext<AppIdentityDbContext>(
options => options.UseSqlServer(Configuration["Data:IdentityDemo:ConnectionString"])
); //配置Identity
services.AddIdentity<AppUser, IdentityRole>(opts =>
{
opts.Password.RequiredLength = 6;
opts.Password.RequireNonAlphanumeric = false;
opts.Password.RequireLowercase = false;
opts.Password.RequireUppercase = false;
opts.Password.RequireDigit = false;
}).AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders(); services.AddControllersWithViews();
}
  1. 用户名验证码规则

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

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

//配置Identity
services.AddIdentity<AppUser, IdentityRole>(opts =>
{
opts.User.RequireUniqueEmail = true;
opts.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyz";
opts.Password.RequiredLength = 6;
opts.Password.RequireNonAlphanumeric = false;
opts.Password.RequireLowercase = false;
opts.Password.RequireUppercase = false;
opts.Password.RequireDigit = false;
}).AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();

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

using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityDemo.Models; namespace IdentityDemo.Infrastructure
{
/// <summary>
/// 自定义用户名或者邮箱验证规则
/// </summary>
public class CustomUserValidator : UserValidator<AppUser>
{
public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user)
{
IdentityResult result = await base.ValidateAsync(manager, user);
List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
if (!user.Email.ToLower().EndsWith("@example.com"))
{
errors.Add(new IdentityError
{
Code = "EmailIdentityError",
Description = "只允许example.com的邮箱地址注册账号"
});
}
return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
}
}
}

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

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

    1). 在用户列表页,添加编辑、删除按钮:Index.cshtml:
@model IEnumerable<AppUser>

@{
ViewData["Title"] = "Index";
}
<div class="bg-primary m-1 p-1 text-white"><h4>用户账号</h4></div>
<table class="table table-sm table-bordered">
<tr><th>ID</th><th>用户名</th><th>邮箱</th><th>操作</th></tr>
@if (Model.Count() == 0)
{
<tr><td colspan="3" class="text-center">没有</td></tr>
}
else
{
foreach (AppUser user in Model)
{
<tr>
<td>@user.Id</td>
<td>@user.UserName</td>
<td>@user.Email</td>
<td>
<form asp-action="Delete" asp-route-id="@user.Id" method="post">
<a class="btn btn-sm btn-primary" asp-action="Edit"
asp-route-id="@user.Id">编辑</a>
<button type="submit"
class="btn btn-sm btn-danger">
删除
</button>
</form>
</td>
</tr>
}
}
</table>
<a class="btn btn-primary" asp-action="Create">创建</a>

2). 删除用户

//删除用户
[HttpPost]
public async Task<IActionResult> Delete(string id)
{
AppUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
IdentityResult result = await userManager.DeleteAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrorsFromResult(result);
}
}
else
{
ModelState.AddModelError("", "User Not Found");
}
return View("Index", userManager.Users);
} private void AddErrorsFromResult(IdentityResult result)
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}

3). 编辑用户

/// <summary>
/// 编辑用户
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<IActionResult> Edit(string id)
{
AppUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
return View(user);
}
else
{
return RedirectToAction("Index");
}
} /// <summary>
/// 编辑用户
/// </summary>
/// <param name="id"></param>
/// <param name="email"></param>
/// <param name="password"></param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> Edit(string id, string email,
string password)
{
AppUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
user.Email = email;
//用户邮箱校验
IdentityResult validEmail = await userValidator.ValidateAsync(userManager, user);
if (!validEmail.Succeeded)
{
AddErrorsFromResult(validEmail);
}
IdentityResult validPass = null;
if (!string.IsNullOrEmpty(password))
{
//用户密码校验
validPass = await passwordValidator.ValidateAsync(userManager, user, password);
if (validPass.Succeeded)
{
//用户密码加密
user.PasswordHash = passwordHasher.HashPassword(user, password);
}
else
{
AddErrorsFromResult(validPass);
}
}
//1. 只修改了邮箱,2. 修改了邮箱和密码
if ((validEmail.Succeeded && validPass == null) || (validEmail.Succeeded && password != string.Empty && validPass.Succeeded))
{
IdentityResult result = await userManager.UpdateAsync(user); //更新用户信息s
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrorsFromResult(result);
}
}
}
else
{
ModelState.AddModelError("", "User Not Found");
}
return View(user);
}

编辑用户的视图:

Edit.cshtml:

@model AppUser

@{
ViewData["Title"] = "修改用户信息";
} <div class="bg-primary m-1 p-1"><h4>修改用户信息</h4></div>
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="Edit" method="post">
<div class="form-group">
<label asp-for="Id"></label>
<input asp-for="Id" class="form-control" disabled />
</div>
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input name="password" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">保存</button>
<a asp-action="Index" class="btn btn-secondary">取消</a>
</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. OpenCV-Python 改变颜色空间 | 十三

    目标 在本教程中,你将学习如何将图像从一个色彩空间转换到另一个,像BGR↔灰色,BGR↔HSV等 除此之外,我们还将创建一个应用程序,以提取视频中的彩色对象 你将学习以下功能:cv.cvtColor, ...

  2. 多线程设计模式——Read-Write Lock模式和Future模式分析

    目录 多线程程序评价标准 任何模式都有一个相同的"中心思想" Read-Write Lock 模式 RW-Lock模式特点 冲突总结 手搓RW Lock模式代码 类图 Data类 ...

  3. POJ - 3255 SPFA+邻接表求次短路径

    题意:给出m条边 , n个顶点,u [ i ]到v [ i ] 的距离w [ i ],求除了最短路的那条最短的边的长度. 思路:之前有做过相似的题,使用迪杰斯特拉算法求单源最短路径,并且记录路径,枚举 ...

  4. redis++:Redis的两种持久化 RDB 和 AOF

    Redis持久化备份数据的方式有两种:RDB(Redis DataBase) . AOF(Append Only  File). RDB 什么是RDB: 在指定时间间隔内,将内存中的数据集快照写入磁盘 ...

  5. 纯css实现图片或者页面变灰色

    前言 今天是个沉痛的日子,全国哀悼英雄,各大平台平日鲜丽的界面置纷纷换成了灰色,以表对逝者的安息与尊敬!!对付疫病,我没多大的本事,只能记录一点点知识来提升自己擅长的技术,待到将来能为国家尽一份绵薄之 ...

  6. Cygwin工具编译Ardupilot方法

    注意:该编译方法生成的固件基于Chibios系统,如果想要Nuttx系统固件,需采用make编译,步骤见make编译说明部分. 软件安装准备 安装Cygwin 打开链接www.cygwin.com/i ...

  7. CentOS7通过wget下载文件到指定目录

    查看自己的CentOS7系统有没有安装wget: [duanyongchun@192 3DUnetCNN]$ rpm -qa|grep wget 已安装提示: #已安装提示:wget-1.14-18. ...

  8. 总结:自动将函数对象添加到字典的bug

    介绍 本文以ATM项目为背景,介绍一个比较实用的编程技巧,使用装饰器将项目中的指定函数添加到字典中. 利用字典通过key访问value的特点,实现用户输入编号,通过字典直接获取并调用编号对应的功能函数 ...

  9. Gang Of Four的23中设计模式

    Gang Of Four的23中设计模式 标签(空格分隔): 设计模式 1. 根据目的来进行划分 根据目的进行划分可以分为创建型模式, 结构型模式和行为模式三种. 1.1 创建型模式 怎样创建对象, ...

  10. apache-atlas 深度剖析

    atlas  是apache下的大数据的元数据管理平台,支持对hive.storm.kafka.hbase.sqoop等进行元数据管理以及以图库的形式展示数据的血缘关系. 一.架构 整体架构实现如下图 ...