.Net中的标识框架Identity

中间件:

1、Authentication对访问者的用户身份进行验证,“用户是否登录成功”。

2、Authorization验证访问者的用户身份是否有对资源访问的访问权限,“用户是否有权限访问这个地址”。

简单描述

1、标识(Identity)框架:采用基于角色的访问控制(Role-Based Access Control,简称RBAC)策略,内置了对用户、角色等表的管理以及相关的接口,支持外部登录、2FA等。它允许我们创建、读取、更新和删除账户。支持账号验证、身份验证、授权、恢复密码和SMS双因子身份验证。它还支持微软、Facebook和Google等第三方登录提供商。它提供了一个丰富的API,并且这些API还可以进行大量的扩展。我们将在本书的后面实现这些功能。

2、标识框架使用EF Core对数据库进行操作,因此标识框架支持几乎所有数据库。

使用场景

涉及注册、登录和修改密码等功能,登录系统后,有些功能会提示没有权限,甚至有些位置我们无法访问,这些都是系统权限和认证的体现。

配置Identity

安装Nuget

Microsoft.AspNetCore.Identity.EntityFrameworkCore

创建Identity上下文对象

public class MyContext:IdentityDbContext<User,Role,long>

{

    public MyContext(DbContextOptions options)

    : base(options)

    {

    }

 

    protected override void OnModelCreating(ModelBuilder builder)

    {

        base.OnModelCreating(builder);

        builder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);

    }

}

如果需要对User(用户)和Role(角色)进行扩展可进行继承

public class Role:IdentityRole<long> //泛型类型longId类型

{

}

 

public class User:IdentityUser<long>

{

    public DateTime CreationTime { get; set; } //创建时间

    public string? NickName { get; set; }   //昵称

}

向依赖注入容器中注册标识框架相关的服务

builder.Services.AddDataProtection();

//注意不是AddIdentity

builder.Services.AddIdentityCore<User>(options => {   

    options.Password.RequireDigit = false;//设置密码是否必须是数字

    options.Password.RequireLowercase = false;//是否必须小写

    options.Password.RequireNonAlphanumeric = false;//是否必须非数字

    options.Password.RequireUppercase = false;//是否必须大写

    options.Password.RequiredLength = 6;//长度为6

    options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultProvider;//设置密码令牌

    options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;//设置邮箱令牌

});

var idBuilder = new IdentityBuilder(typeof(User), typeof(Role), builder.Services);

idBuilder.AddEntityFrameworkStores()

    .AddDefaultTokenProviders().AddRoleManagerRole>>()

    .AddUserManagerUser>>();

执行Add-Migration、Update-Database等命令执行EF Core的数据库迁移。

Add-Migration Init

Update-Database

.Net中的标识框架Identity_第1张图片

创建角色与用户信息

[Route("api/[controller]/[action]")]

[ApiController]

public class IdentityController : ControllerBase

{

//通过RoleManager、UserManager等来进行数据操作。比如创建角色、创建用户。

    private readonly RoleManager roleManager;

    private readonly UserManager userManager;

    public IdentityController(RoleManager roleManager, UserManager userManager)

    {

        this.roleManager = roleManager;

        this.userManager = userManager;

    }

 

    [HttpPost]

    public async Task CreateUserRole()

    {

        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);

            }

        }

 

        User user = await this.userManager.FindByNameAsync("rodio");//获取某用户信息

        if (user == null)

        {

            user = new User {

           UserName = "rodio",

           Email = "abc123888@gmail.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();

    }

}

 

用户登录

//用户登录类

public record LoginRequest(string UserName,string Password);

//控制器添加一个Action

[HttpPost]

public async Task 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

    {

        //将用户的登录失败进行计数。如果超过配置次数将会被锁(封号)

        var r = await userManager.AccessFailedAsync(user);

        if (!r.Succeeded)

        {

            return BadRequest("AccessFailed failed");

        }

        return BadRequest("Failed");

    }

}

 

你可能感兴趣的:(ASP.Net,MVC,.net,c#,.netcore)