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. K折-交叉验证

    k-折交叉验证(k-fold crossValidation):在机器学习中,将数据集A分为训练集(training set)B和测试集(test set)C,在样本量不充足的情况下,为了充分利用数据 ...

  2. 《深入理解 Java 虚拟机》读书笔记:Java 内存模型与线程

    正文 由于计算机的处理器运算速度与它的存储和通信子系统速度的差距太大了,大量的时间都花费在磁盘 I/O.网络通信或者数据库访问上,导致处理器在大部分时间里都处于等待其他资源的状态.因此,为了充分利用计 ...

  3. iOS 图片加载和处理

    一.图片显示 图片的显示分为三步:加载.解码.渲染.解码和渲染是由 UIKit 进行,通常我们操作的只有加载. 以 UIImageView 为例.当其显示在屏幕上时,需要 UIImage 作为数据源. ...

  4. Mysql数据库主键,外键,索引概述

    主键: 主键是数据表的唯一索引,比如学生表里有学号和姓名,姓名可能有重名的,但学号确是唯一的,你要从学生表中搜索一条纪录如查找一个人,就只能根据学号去查找,这才能找出唯一的一个,这就是主键;如:id ...

  5. Matlab——m_map指南(3)——实例

    m_map 实例 1. clear all m_proj('ortho','lat', 48,'long',-123');%投影方式,范围 m_coast('patch','r');%红色填充 m_g ...

  6. POI2014 FAR-FarmCraft 树形DP+贪心

    题目链接 https://www.luogu.org/problem/P3574 题意 翻译其实已经很明确了 分析 这题一眼就是贪心啊,但贪心的方法要思索一下,首先是考虑先走时间多的子树,但不太现实, ...

  7. # H - H HDU - 2066 (多起点、多终点问题)

    H - H HDU - 2066 (多源点.多汇点问题) 一个图上,有M条边,Z个出发点,Y个终止点.求一条最短路,其中起点是Z中的任意一点,终点是Y中任意一点. Input 输入数据有多组,输入直到 ...

  8. Codeforces Round #629 (Div. 3)

    A. Divisibility Problem time limit per test 1 second memory limit per test 256 megabytes input stand ...

  9. C语言:static关键字用法

    参考博客:https://blog.csdn.net/guotianqing/article/details/79828100 看个例子: #include <stdio.h> void ...

  10. 201771010108-韩腊梅《面向对象程序设计(java)》第二周学习总结

    201771010108<面向对象程序设计(java)>第二周学习总结 第一部分:理论知识学习部分 第三章:Java的基本程序设计结构 1.标识符:① 标识符由字母.下划线.美元符号和数字 ...