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. 一份从入门到精通NLP的完整指南 | NLPer

    该小博主介绍 本人:笔名zenRRan,方向自然语言处理,方法主要是深度学习. 未来的目标:人工智能之自然语言处理博士. 写公众号目的:将知识变成开源,让每个渴求知识而难以入门人工智能的小白以及想进阶 ...

  2. Vue history路由模式 apache配置上线

    1. 首先在vue项下的router.js 文件配置 mode为history模式,并且设置好对应的base选项 说明:base配置为你当前项目实际上线时所在的目录文件夹, 我这就是放在站点的根目录下 ...

  3. poj——1182食物链 并查集(提升版)

    因为是中文题,题意就不说了,直接说思路: 我们不知道给的说法中的动物属于A B C哪一类,所以我们可以用不同区间的数字表示这几类动物,这并不影响结果,我们可以用并查集把属于一类的动物放在一块,举个例子 ...

  4. 044.集群存储-StorageClass

    一 StoragClass 1.1 StorageClass概述 StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,一方面减少了用户对于存储资源细节的关注,另 ...

  5. docker下centos7编译安装ffmpeg

    1.安装基础命令 docker下精简版centos没有make等命令,先安装: yum -y install gcc automake autoconf libtool make yum instal ...

  6. js拖拽效果的实现及原理

    元素拖拽分成3个步骤:按下鼠标,移动鼠标,松开鼠标. 拖拽原理:按下拖拽元素后开始监听文档中鼠标移动事件,然后再监听鼠标松开事件:鼠标移动时,元素div要随着鼠标一起移动,需要计算元素div位移的距离 ...

  7. ES6规范及语法基础

    var的特点 函数作用域 let的特点 没有变量提升,必须先声明.再调用 同一个作用域下不可以重复定义同一个名称 块级作用域 function fun(){ let a = 10 if(true){ ...

  8. codeblocks 的安装与初体验

    下载 链接 安装  点击默认安装即可! 配置 自带编译器还报错!! 大多数自带编译器的codeblocks安装后无法找到编译器的解决方案 点击Settings->Compiler,找到Toolc ...

  9. JavaScript form表单提交与验证

    原网址:https://blog.csdn.net/vipwxs/article/details/79119701 一.form对象的属性: name:获取表单的名称,该name一般给JS使用 met ...

  10. 使用 python 进行身份证号校验

    使用 python 代码进行身份证号校验 先说,还有很多可以优化的地方. 1.比如加入15位身份证号的校验,嗯哼,15位的好像没有校验,那就只能提取个出生年月日啥的了. 2.比如判断加入地址数据库,增 ...