ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?

news2024/11/26 23:43:07

image

前言

ASP.NET Core 内置的标识(identity)框架,采用的是 RBAC(role-based access control,基于角色的访问控制)策略,是一个用于管理用户身份验证、授权和安全性的框架。

它提供了一套工具和库,用于管理用户、角色、登录、密码重置、电子邮件确认等功能。

通过它,你可以:

  1. 用户管理:创建、管理和验证用户,这样你可以轻松操作注册用户、登录、注销、密码重置等功能。

  2. 角色管理:定义不同的用户角色,并将用户分配到这些角色中,这样你可以更好地控制用户的权限和访问级别。

  3. 密码策略:框架提供了密码策略功能,允许你定义密码的复杂度要求,例如密码长度、大小写字母、数字等要求。

  4. 外部登录:框架还支持你使用外部身份验证提供者(如 QQ、微信、微博等)进行身份验证。

  5. 电子邮件确认:通过电子邮件确认用户注册和密码重置操作,这样注册和修改密码操作更加安全可靠。

今天,我们主要聊聊如何使用 ASP.NET Core 标识(Identity)框架来管理用户和角色,也有涉及到密码策略、电子邮件确认等方面。

Step By Step 步骤

  1. 创建一个 ASP.NET Core webapi 项目,命名为 IdentitySample

  2. 引用以下 Nuget 包:

    Microsoft.AspNetCore.Identity.EntityFrameworkCore
    Microsoft.EntityFrameworkCore.Relational
    Microsoft.EntityFrameworkCore.SqlServer
    Microsoft.EntityFrameworkCore.Tools

  3. 修改 appsettings.json,添加数据库连接字符串

    {
      "Logging": {
    	"LogLevel": {
    	  "Default": "Information",
    	  "Microsoft.AspNetCore": "Warning"
    	}
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
    	"Default": "Server=(localdb)\\mssqllocaldb;Database=IdentityTestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
      }
    }	
    
  4. 创建用户实体类 User(重点看注释

    using Microsoft.AspNetCore.Identity;
    
    // IdentityUser<long> 表示 long 类型主键的用户实体类
    // IdentityUser 中定义了 UserName(用户名)、Email(邮箱)、PhoneNumber(手机号)、PasswordHash(密码的哈希值)等属性,
    // 这里又添加了 CreationTime(创建时间)、NickName(昵称)两个属性。
    public class User: IdentityUser<long>
    {
    	public DateTime CreationTime { get; set; }
    	public string? NickName { get; set; }
    }
    
  5. 创建角色实体类 Role

    using Microsoft.AspNetCore.Identity;
    
    public class Role: IdentityRole<long>
    {
    
    }
    
  6. 创建继承自 IdentityDbContext 的上下文类(重点看注释

    using Microsoft.EntityFrameworkCore;
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    
    // 使用 Identity 框架要继承 IdentityDbContext
    // IdentityDbContext 是一个泛型类,有3个泛型参数,分别代表用户类型、角色类型和主键类型
    public class IdDbContext: IdentityDbContext<User, Role, long>
    {
    	public IdDbContext(DbContextOptions<IdDbContext> options) : base(options)
    	{
    
    	}
    
    	protected override void OnModelCreating(ModelBuilder modelBuilder)
    	{
    		base.OnModelCreating(modelBuilder);
    		modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
    	}
    }	
    
  7. 打开 Program.cs 文件,向依赖注入容器中注册与标识框架相关的服务,并且对相关的选项进行配置(重点看注释

    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    // 向依赖注入容器中注册与标识框架相关的服务,并对相关的选项进行配置
    // ----1. 数据库注入
    IServiceCollection services = builder.Services;
    services.AddDbContext<IdDbContext>(opt =>
    {
    	string connStr = builder.Configuration.GetConnectionString("Default")!;
    	opt.UseSqlServer(connStr);
    });
    // ----2. 数据保护服务注入
    // ----数据保护提供了一个简单、基于非对称加密改进的加密API用于确保Web应用敏感数据的安全存储
    // ----不需要开发人员自行生成密钥,它会根据当前应用的运行环境,生成该应用独有的一个私钥
    services.AddDataProtection();
    // ----3. 添加标识框架的一些重要的基础服务
    services.AddIdentityCore<User>(options => { 
    	options.Password.RequireDigit = false;
    	options.Password.RequireLowercase = false;
    	options.Password.RequireNonAlphanumeric = false;
    	options.Password.RequireUppercase = false;
    	options.Password.RequiredLength = 6;
    	options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
    	options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
    });
    // ----4. 注入 UserManager、RoleManager等服务
    var idBuilder = new IdentityBuilder(typeof(User), typeof(Role), services);
    idBuilder.AddEntityFrameworkStores<IdDbContext>()
    	.AddDefaultTokenProviders()
    	.AddRoleManager<RoleManager<Role>>()
    	.AddUserManager<UserManager<User>>();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
    	app.UseSwagger();
    	app.UseSwaggerUI();
    }
    
    app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();
    
  8. 执行以下命令进行数据迁移,执行后将在数据库中生成多张与 Identity 相关的表

    Add-Migration InitIdentity
    Update-database
    
  9. 创建相应的实体类

    public record LoginRequest(string UserName, string Password);
    
    public record SendResetPasswordTokenRequest(string Email);
    
    public record ResetPasswordResponse(string Email, string Token, string NewPassword);
    
  10. 在控制器中编写代码,操作角色、用户数据(重点看注释

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Identity;
    
    namespace IdentitySample.Controllers
    {
    	[ApiController]
    	[Route("[controller]/[action]")]
    	public class Test1Controller : ControllerBase
    	{
    		private readonly ILogger<Test1Controller> logger;
    		private readonly RoleManager<Role> roleManager;
    		private readonly UserManager<User> userManager;
    
    		// 注入 RoleManager,UserManager,ILogger
    		public Test1Controller(
    			ILogger<Test1Controller> logger,
    			RoleManager<Role> roleManager,
    			UserManager<User> userManager)
    		{
    			this.logger = logger;
    			this.roleManager = roleManager;
    			this.userManager = userManager;
    		}
    
    		// 创建角色和用户
    		[HttpPost]
    		public async Task<ActionResult> CreateUserRole()
    		{
    			// 1. 判断管理员角色是否存在,不存在则创建
    			bool roleExists = await roleManager.RoleExistsAsync("admin");
    			if (!roleExists)
    			{
    				Role role = new Role() { Name = "Admin" };
    				var r = await roleManager.CreateAsync(role);
    				if (!r.Succeeded)
    				{
    					return BadRequest(r.Errors);
    				}
    			}
    
    			// 2. 创建账户
    			User user = await userManager.FindByNameAsync("yzk");
    			if (user == null)
    			{
    				user = new User
    				{
    					UserName = "yzk",
    					Email = "51398898@qq.com",
    					EmailConfirmed = true,
    				};
    
    				var r = await userManager.CreateAsync(user, "123456");
    				if (!r.Succeeded)
    				{
    					return BadRequest(r.Errors);
    				}
    				r = await userManager.AddToRoleAsync(user, "Admin");
    				if (!r.Succeeded)
    				{
    					return BadRequest(r.Errors);
    				}
    			}
    			return Ok();
    		}
    
    		// 登录
    		[HttpPost]
    		public async Task<ActionResult> Login(LoginRequest req)
    		{
    			string userName = req.UserName;
    			string password = req.Password;
    			var user = await userManager.FindByNameAsync(userName);
    			if (user == null)
    			{
    				return NotFound($"用户名不存在{userName}");
    			}
    			if (await userManager.IsLockedOutAsync(user))
    			{
    				return BadRequest("LockedOut");
    			}
    			var success = await userManager.CheckPasswordAsync(user, password);
    			if (success)
    			{
    				return Ok("Success");
    			}
    			else
    			{
    				// 调用userManager的AccessFailedAsync方法来记录一次“登录失败”,
    				// 当连续多次登录失败之后,账户就会被锁定一段时间,以避免账户被暴力破解
    				var r = await userManager.AccessFailedAsync(user);
    				if (!r.Succeeded)
    				{
    					return BadRequest("AccessFailed failed");
    				}
    				return BadRequest("Failed");
    			}
    		}
    
    		// 发送重置密码 Token
    		[HttpPost]
    		public async Task<IActionResult> SendResetPasswordToken(
    			SendResetPasswordTokenRequest req)
    		{
    			string email = req.Email;
    			var user = await userManager.FindByEmailAsync(email);
    			if (user == null)
    			{
    				return NotFound($"邮箱不存在:[{email}]");
    			}
    			// 调用GeneratePasswordResetTokenAsync方法来生成一个密码重置令牌,这个令牌会被保存到数据库中
    			// 然后把这个令牌发送到用户邮箱
    			string token = await userManager.GenerateEmailConfirmationTokenAsync(user);
    			logger.LogInformation($"向邮箱{user.Email}发送Token={token}");
    			return Ok(token); 
    		}
    
    		// 重置密码
    		[HttpPost]
    		public async Task<IActionResult> VerifyResetPasswordToken(
    			ResetPasswordRequest req)
    		{
    			string email = req.Email;
    			var user = await userManager.FindByEmailAsync(email);
    			string token = req.Token;
    			string password = req.NewPassword;
    			var r = await userManager.ResetPasswordAsync(user, token, password);
    			return Ok();
    		}
    	}
    }	
    
  11. 启动项目,通过 Postman 或 Swagger 运行 API 进行测试

最后

ASP.NET Core 内置的标识(identity)框架使用 EF Core 对数据库进行操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1582390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

爬虫+RPC+js逆向---直接获取加密值

免责声明:本文仅做技术交流与学习,请勿用于其它违法行为;如果造成不便,请及时联系... 目录 爬虫RPCjs逆向---直接获取加密值 target网址: 抓包 下断点 找到加密函数 分析参数 RPC流程 一坨: 二坨: 运行py,拿到加密值 爬虫RPCjs逆向---直接获取加密值 target网址: 优志…

prometheus expected a valid start token, got “\““ (“INVALID“) while parsing:

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

C++中的数组下标可以出现越界并且不报错

C中数组越界 最近用C写算法题目的时候&#xff0c;突然在某个题目中发现其数组下标会出现越界的情况&#xff0c;但是程序似乎不会报错&#xff0c;百思不得其解&#xff0c;然后自己写了个代码测试了一下&#xff0c;如下图所示&#xff1a; 当我们访问越界地址的时候&#…

rhce复习3

DNS DNS&#xff08;Domain Name System&#xff09;是互联网上的一项服务&#xff0c;它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网。 DNS系统使用的是网络的查询&#xff0c;那么自然需要有监听的port。DNS使用的是53端口&#x…

[react] useState的一些小细节

1.无限循环 因为setState修改是异步的,加上会触发函数重新渲染, 如果代码长这样 一秒再修改,然后重新触发setTImeout, 然后再触发,重复触发循环 如果这样呢 还是会,因为你执行又会重新渲染 2.异步修改数据 为什么修改多次还是跟不上呢? 函数传参解决 因为是异步修改 ,所以…

接口日志处理类

类&#xff1a;ZCL_IFLOG_UTILITIES 属性&#xff1a;AUTH_RESULTS_LIST 类型&#xff1a; TY_AUTH_RESULT Private 受保护部分&#xff1a; PRIVATE SECTION.TYPES: BEGIN OF ty_auth_result,funcname TYPE ztall_logcfg-funcname,pass TYPE abap_bool,END OF ty_aut…

CentOS 7 升级 5.4 内核

MatrixOne 推荐部署使用的操作系统为 Debian 11、Ubuntu 20.04、CentOS 9 等 Kernel 内核版本高于 5.0 的操作系统。随着 CentOS 7 的支持周期接近尾声&#xff0c;社区不少小伙伴都在讨论用以替换的 Linux 操作系统&#xff0c;经过问卷调查&#xff0c;我们发现小伙伴们的操作…

测试开发-快速定位问题

写在前面 这两天工作实在是有点小忙&#xff0c;感觉好久没更新了&#xff0c;但是平时也是有感而发的比较多&#xff0c;今天遇到一个问题&#xff0c;感觉挺有意思&#xff0c;处理过程也非常有意义&#xff0c;希望能给大家一个借鉴吧。 测试平台又又又出问题了 今天一位…

【文件IO】JavaIO详解

一.文件的相关概念 什么是文件? 文件是计算机中存储信息的基本单位。文件通常指的是存储在计算机或其他数字存储设备上的一段信息的集合&#xff0c;这些信息可以是文本、图片、音频、视频等不同格式的数据。 文件路径: 文件的路径可以分为两类 相对路径:先指定一个"当前…

c++的STL(8) -- queue

queue容器概述 queue容器实现了实现了和队列相同结构的容器。 如图&#xff0c;队列这种结构有两端: 队首和队尾。 对于队列&#xff0c;我们添加数据只能从队尾添加&#xff0c;删除数据和获取数据只能从队首删除。是一种先进先出的结构。 -- 当然读取数据也只能从队首或者…

方案分享 | 嵌入式指纹方案

随着智能设备的持续发展&#xff0c;指纹识别技术成为了现在智能终端市场和移动支付市场中占有率最高的生物识别技术。凭借高识别率、短耗时等优势&#xff0c;被广泛地运用在智能门锁、智能手机、智能家居等设备上。 我们推荐的品牌早已在2015年进入指纹识别应用领域&#xff…

MUNK电源维修GmbH高频电源E230 G60/45 WRG-TFMYCT24

德国MUNK电源维修主要系列&#xff1a;ΡKA2&#xff0c;DCAC100&#xff0c;AS100&#xff0c;HS100&#xff0c;ESA2000&#xff0c; HSG2000&#xff0c;E230 G60/45&#xff1b;E230 G100&#xff0c;D400 G100全系列型号。 常见维修型号包括&#xff1a;D400 G100/75WRG-…

【四十一】【算法分析与设计】floodfill(2),130. 被围绕的区域,417. 太平洋大西洋水流问题

目录 130. 被围绕的区域 417. 太平洋大西洋水流问题 结尾 130. 被围绕的区域 给你一个 m x n 的矩阵 board &#xff0c;由若干字符 X 和 O &#xff0c;找到所有被 X 围绕的区域&#xff0c;并将这些区域里所有的 O 用 X 填充。 示例 1&#xff1a; 输入&#xff1a;board …

长基线大高差RTK定位效果分析

为了评估基于GNSS参考站网的实时高精度滑坡监测算法效果&#xff0c;如图2所示&#xff0c;本文共收集了中国西北2019年年积日第271&#xff5e;277共7天的4个CORS站数据&#xff0c;分别为LZLC、BYBY、LXDX、LXJS&#xff0c; 2个黑方台滑坡监测站数据HF01和HF06&#xff0c;其…

算法:多重背包问题dp

文章目录 一、多重背包问题特点1.1、多重背包问题的特征1.2、解决多重背包问题的基本方法典型例题&#xff1a;AcWing——多重背包问题I 1.3、二进制优化1.3.1、二进制优化的思想1.3.2、多重背包问题的二进制优化 一、多重背包问题特点 多重背包问题是背包问题的又一变种&…

大厂设计师倾心推荐的在线作图免费网站

在当今数字时代&#xff0c;绘画已经成为各行各业的必备技能。无论你是设计师、学生、创作者还是业余爱好者&#xff0c;免费的在线绘图软件都是发挥创造力和表达想法的理想选择。本文将介绍七款强大免费的在线绘图软件&#xff0c;让你轻松实现自己的创作梦想。你可以在不安装…

功能测试_验证qq账号的合法性

案例&#xff1a;验证qq账号的合法性&#xff08;要求&#xff1a;6-10位的自然数&#xff09; 使用等价类设计用例案例&#xff1a; 步骤&#xff1a; 1:明确需求&#xff1a;qq账号的合法性 2:划分等价类&#xff1a;有效等价类、有效取值、无效等价类、无效取值 3&…

docker搭建EFK

目录 elasticsearch1.创建网络2.拉取镜像3.创建容器如果出现启动失败&#xff0c;提示目录挂载失败&#xff0c;可以考虑如下措施 开放防火墙端口4.验证安装成功重置es密码关闭https连接创建kibana用户创建新账户给账户授权 kibana1.创建容器2.验证安装成功3.es为kibana创建用户…

LeetCode-冗余连接(并查集)

每日一题&#xff0c;今天又刷到一道使用并查集来解决的问题&#xff0c;再次加深了一遍自己对并查集的印象和使用。 题目要求 树可以看成是一个连通且 无环 的 无向 图。 给定往一棵 n 个节点 (节点值 1&#xff5e;n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1…

Windows11下Docker使用记录(一)

Docker使用记录&#xff08;一&#xff09; 简单介绍Docker安装Docker 常用命令Docker 可视化Docker 使用GPU可视化rviz、gazebo 在进行ROS项目开发时&#xff0c;如果只有一台Windows电脑&#xff0c;我们可以考虑使用WSL或Docker来搭建ROS环境。在尝试了两种方式后&#xff0…