asp.net core 身份认证/权限管理系统简介

如今的网站大多数都离不开账号注册及用户管理,而这些功能就是通常说的身份验证。这些常见功能微软都为我们做了封装,我们只要利用.net core提供的一些工具就可以很方便的搭建适用于大部分应用的权限管理系统。

先贴官方文档地址:https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity 善用谷歌翻译可以减少语言障碍。

这里我们用一个相对简单的权限管理案例来作为讲解。环境:vs2017,asp.net core 2.1,sqlserver 2017 dev,datagrip

新建asp.net core项目,选择更改身份验证->个人用户账号->存储应用内的用户账户

为了之后更直观的查看成果,项目创建间完成后将appsettings.json中的默认连接字符串修改以连接自己的数据库。

这个时候启动项目,点击右上角的注册,填写邮箱和密码(密码要求包含大小写字母及符号)

完成后提交,发现报错了。查看错误日志,提示数据库没有迁移。回到资源管理器下的项目根目录,重新生成解决方案,运行:

dotnet ef migrations add first

dotnet ef database update

这两条命令的详细介绍见微软官方文档:https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/

完成后用数据库连接工具查看数据库下的默认架构(dbo),发现多出来了8张表。

为了给大家一个初步的印象以理解之后的内容,这里需要稍微讲解几个名词:

User:用户。包含了用户名、邮箱、昵称、加密后的登录密码等数据

Role:角色。用来承载权限。

Claims:具体的权限。比如能够发表文章是一条权限,能够删除文章也是一条权限。

权限可以赋予给具体的用户和角色。角色/用户和权限是多对多的关系。

生成的8张表就是为了存放这些数据。其中__EFMigrationsHistory用来记录数据库的迁移历史,如果需要重新迁移则需要清空或删除这张表。

这时候我们再打开调试,跟之前一样注册用户,这次我们没有看到任何错误,完成后跳转到了首页,右上角也显示出了我们刚刚注册的用户名。

现在我们尝试添加一个需要一定权限才能访问的接口。新建Auth控制器(AuthController),创建AddEmp方法。

    public class AuthController : Controller

    {

        [Authorize(Policy = "ManagerOnly")] //Policy的意思是“策略”,可以理解为对一组权限需求的描述。ManagerOnly是Policy的名字

        public IActionResult AddEmp()

        {

            return Content("true");

        }

}

转到Startup.cs的ConfigureServices,添加

services.AddAuthorization(opt => { opt.AddPolicy("ManagerOnly", p => p.RequireRole("manager")); });

这一行可以理解为添加名为ManagerOnly的权限策略,这个策略要求访问者具备名为manager的角色。

现在我们 启动网站,访问/auth/AddEmp,发现跳转到了权限不足页面。获得权限,让结果变成true呢

由于默认的代码没有提供角色管理,这时候我们需要对startup.cs进行修改。

修改ConfigureServices方法,将

 services.AddDefaultIdentity<IdentityUser>()

                .AddEntityFrameworkStores<ApplicationDbContext>();

改为

//            services.AddDefaultIdentity<IdentityUser>()

            services.AddIdentity<IdentityUser, IdentityRole>()

                .AddEntityFrameworkStores<ApplicationDbContext>();

IdentityUser, IdentityRole是系统默认的用户和角色,如果我们需要添加自定义属性,就需要自定义类来继承这两个自带的类。这个我们之后讲。

添加完毕后,我们回到AuthController,使用依赖注入来注入Manager类:

        private UserManager<IdentityUser> _userManager;

        private RoleManager<IdentityRole> _roleManager;

        public AuthController(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)

        {

            _userManager = userManager;

            _roleManager = roleManager;

        }

完成后添加AddManagerRole方法:

 public IActionResult AddManagerRole()

        {

            var role = _roleManager.Roles.SingleOrDefault(o=>o.Name=="manager");

            if (role==null)

            {

                var identityResult = _roleManager.CreateAsync(new IdentityRole("manager")).Result;

                if (!identityResult.Succeeded)

                {

                    return Content("create role error");

                }

            }

            var user = _userManager.GetUserAsync(User).Result; //User指的是当前登陆的用户。HttpContext中自带

            var result = _userManager.AddToRoleAsync(user, "manager").Result;

            if (result.Succeeded)

            {

                return Content("true");

            }

            return Content("false");

        }

完成后访问/Auth/AddManagerRole,返回true的话就成功的为当前登录用户添加“manager”角色了。

然后我们访问之前的/Auth/AddEmp接口,发现这次成功的返回了true。这就是基于角色的权限管理。

接下来谈谈之前提到的Claim,这次我们尝试使用claim进行权限管理。

auth控制器添加方法Raise

        [Authorize(Policy = "RequireRaise")]

        public IActionResult Raise()

        {

            return Content("true");

        }

Startup.cs添加Policy

            services.AddAuthorization(opt =>

            {

                opt.AddPolicy("ManagerOnly", p => p.RequireRole("manager"));

                opt.AddPolicy("RequireRaise",p=>p.RequireClaim("salary","raise"));

            });

完成后访问/Auth/Raise,提示权限不足。

为了获得权限,auth控制器添加方法AddRaiseClaim:

        public IActionResult AddRaiseClaim()

        {

            var user = _userManager.GetUserAsync(User).Result; 

            var result = _userManager.AddClaimAsync(user, new Claim("salary", "raise")).Result;  //一个Claim由Type和Value构成。这句的意思是添加type为salary,value为raise的claim。

            if (result.Succeeded)

            {

                return Content("true");

            }

            return Content("false");

        }

完成后启动网站,访问/Auth/AddRaiseClaim,返回true则表示添加成功。

再次访问/Auth/Raise,返回true则表示鉴权成功。

最后再来讲解一下如何修改asp.net core自带User和Role的主键类型。

新建User类和Role类,分别继承IdentityUser和IdentityRole并添加目标类型泛型。这里以修改为int型为例:

   public class User : IdentityUser<int>    //可添加自定义属性

    public class Role:IdentityRole<int>

回到startup.cs,将

            services.AddIdentity<IdentityUser, IdentityRole>()

                .AddEntityFrameworkStores<ApplicationDbContext>();

改为

            services.AddIdentity<User,Role>()

                .AddEntityFrameworkStores<ApplicationDbContext>();

转到ApplicationDbContext.cs,注册之前添加的用户和角色:

public class ApplicationDbContext : IdentityDbContext<User,Role,int>

完成后删除数据库中之前迁移的8张表,并且删除项目中的Migrations文件夹(很重要,不然报错),重新执行迁移命令:

dotnet ef migrations add sec

dotnet ef database update

完成后查看数据库,发现主键已经成功修改成了int并且自增了。

这里需要注意的一点是,如果以后在ApplicationDbContext里注册新的类,并修改OnModelCreating方法的时候,记得调用base.OnModelCreating(modelBuilder); 不然会报错。

这时候启动网站,发现报错了。提示No service for type ‘Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]‘ has been registered.  意思就是UserManager<IdentityUser>没注册。因为我们之前在startup中将services.Addidentity<IdentityUser, IdentityRole>()改成了services.AddIdentity<User,Role>(),所以UserManager<IdentityUser>自然就没注册了。解决方法是全局搜索UserManager<IdentityUser>和,RoleManager<IdentityRole>,将其改成UserManager<User>和RoleManager<Role>就行了。

这时启动网站,访问登录页面,发现提示404。这也是由于我们修改了services.Addidentity<IdentityUser, IdentityRole>()导致的问题,解决方案是自己实现login和register。

页面这里就不写了,只提供控制器的login和register方法:

public class RegisterDto

{

  public string UserName { get; set; }

  public string Password { get; set; }

}
private readonly UserManager<MyUser> _userManager;
private readonly SignInManager<MyUser> _signInManager; //管理登录登出的Manager类。系统自带。
private readonly RoleManager<MyRole> _roleManager;

public AccountController(UserManager<MyUser> userManager, SignInManager<MyUser> signInManager, RoleManager<MyRole> roleManager)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _roleManager = roleManager;
}
[HttpPost]
public async Task<IActionResult> Login(RegisterDto dto)
{

    var result = await _signInManager.PasswordSignInAsync(dto.UserName, dto.Password, true, false);

    if (result.Succeeded)
    {
        return RedirectToAction("Index", "Home");
    }

    return Content("login fail");

}
   [HttpPost]
        public async Task<IActionResult> Register(RegisterDto dto)
        {
            var user = new MyUser()
            {
                UserName = dto.UserName,
            };
            var result = await _userManager.CreateAsync(user, dto.Password);

            if (result.Succeeded)
            {
                await _signInManager.SignInAsync(user, isPersistent: true);
//                await _userManager.AddToRoleAsync(user, "Member");
                return Content("true");
            }

            return Content("false");
        } 
public async Task<IActionResult> Logout()
{
    await _signInManager.SignOutAsync();
    return RedirectToAction("Index","Home");
}

完成后访问相应方法即可完成登陆等功能。

关于Startup中的配置,一些常用的就在这里说一下:

配置相关文档:https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-configuration

配置密码校验:

services.Configure<IdentityOptions>(options =>
{
    options.Password. ... = ...; //密码相关

    options.User.AllowedUserNameCharacters = null; //允许用户名使用任意字符。不配置则默认只允许英文字母及数字
});

配置重定向地址:

            services.ConfigureApplicationCookie(opt =>

            {

                opt.AccessDeniedPath = "/denied"; //配置鉴权失败后跳转的地址

                opt.LoginPath = "/login";  //配置未登录情况下访问需要授权的接口后跳转的地址

            });

附送一个演示项目:

https://github.com/axel10/auth_demo

原文地址:https://www.cnblogs.com/axel10/p/9689807.html

时间: 2024-10-29 01:00:54

asp.net core 身份认证/权限管理系统简介的相关文章

【转】权限管理学习 一、ASP.NET FORMS身份认证

[转]权限管理学习 一.ASP.NET Forms身份认证 说明:本文示例使用的VS2017和MVC5.系统无论大小.牛逼或屌丝,一般都离不开注册.登录.那么接下来我们就来分析下用户身份认证. 简单实现登录.注销 以前在学习.net的时候不知道什么Forms身份认证,直接用session实现登录,效果也蛮好嘛.而且用户信息存在服务端,安全.前端代码: @if (string.IsNullOrWhiteSpace(ViewBag.UserName)) { <form action="/hom

细说ASP.NET Windows身份认证

上篇博客我谈到了一些关于ASP.NET Forms身份认证方面的话题,这次的博客将主要介绍ASP.NET Windows身份认证. Forms身份认证虽然使用广泛,不过,如果是在 Windows Active Directory 的环境中使用ASP.NET, 那么使用Windows身份认证也会比较方便. 方便性表现为:我们不用再设计登录页面,不用编写登录验证逻辑.而且使用Windows身份认证会有更好的安全保障. 回到顶部 认识ASP.NET Windows身份认证 要使用Windows身份认证

ASP.NET Core Token认证

翻译:Token Authentication in ASP.NET Core 令牌认证(Token Authentication)已经成为单页应用(SPA)和移动应用事实上的标准.即使是传统的B/S应用也能利用其优点.优点很明白:极少的服务端数据管理.可扩展性.可以使用单独的认证服务器和应用服务器分离. 如果你对令牌(token)不是太了解,可以看这篇文章( overview of token authentication and JWTs) 令牌认证在asp.net core中集成.其中包括

简单的ASP.NET Forms身份认证

读了几篇牛人的此方面的文章,自己也动手做了一下,就想有必要总结一下.当然我的文章质量自然不能与人家相比,只是写给从没有接触过这个知识点的朋友. 网站的身份认证我以前只知道session,偶然发现一些牛人提倡用Forms方式,微软官方也推荐这种方法.详见使用Session作为身份识别的问题 ASP.NET的身份认证方式是在web.config文件中configuration->system.web->authentication指定,如 [html] view plain copy print?

细说ASP.NET Forms身份认证

用户登录是个很常见的业务需求,在ASP.NET中,这个过程被称为身份认证. 由于很常见,因此,我认为把这块内容整理出来,与大家分享应该是件有意义的事. 在开发ASP.NET项目中,我们最常用的是Forms认证,也叫[表单认证]. 这种认证方式既可以用于局域网环境,也可用于互联网环境,因此,它有着非常广泛的使用. 这篇博客主要讨论的话题是:ASP.NET Forms 身份认证. 有一点我要申明一下:在这篇博客中,不会涉及ASP.NET的登录系列控件以及membership的相关话题, 我只想用比较

IE11下ASP.NET Forms身份认证无法保存Cookie的问题

IE11下ASP.NET Forms身份认证无法保存Cookie的问题 折腾了三四天,今天才找到资料,解决了. 以下会转贴,还没来得及深究,先放着,有空再学习下. ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加authentication节点 <authentication mode="Forms"> <forms name="MyAuth" loginUrl="manager/Log

细说ASP.NET Forms身份认证 别人写的不过很透彻就转来了以后用时再看

阅读目录 开始 ASP.NET身份认证基础 ASP.NET身份认证过程 如何实现登录与注销 保护受限制的页面 登录页不能正常显示的问题 认识Forms身份认证 理解Forms身份认证 实现自定义的身份认证标识 在多台服务器之间使用Forms身份认证 在客户端程序中访问受限页面 用户登录是个很常见的业务需求,在ASP.NET中,这个过程被称为身份认证. 由于很常见,因此,我认为把这块内容整理出来,与大家分享应该是件有意义的事. 在开发ASP.NET项目中,我们最常用的是Forms认证,也叫[表单认

asp.net core 自定义认证方式--请求头认证

原文:asp.net core 自定义认证方式--请求头认证 asp.net core 自定义认证方式--请求头认证 Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思路 网关可以做一部分的认证和授权,服务内部有时候也会需要用户的信息,这时该怎么办呢,我们使用的是 JWT 认证,有一个 identity server去颁发,验证 token,一种简单方式可以把 token 直接往后传,传递给后面的具体某

权限管理学习 一、ASP.NET Forms身份认证

说明:本文示例使用的VS2017和MVC5.系统无论大小.牛逼或屌丝,一般都离不开注册.登录.那么接下来我们就来分析下用户身份认证. 简单实现登录.注销 以前在学习.net的时候不知道什么Forms身份认证,直接用session实现登录,效果也蛮好嘛.而且用户信息存在服务端,安全.前端代码: @if (string.IsNullOrWhiteSpace(ViewBag.UserName)) { <form action="/home/login1"> <input t