• 【从0开始.NET CORE认证】-3 声明和策略授权


    系列

    【从0开始.NET CORE认证】-1 认识认证和授权

    回顾

    Hi,朋友们,我稍微整理了一下,把整个系列放到每篇文章的最前面和最后面,方便大家阅读。

    我们简单回顾以下上周讲的内容

    1. 引入了.Net Core自带的Identity框架和EF Core
    2. 在SqlServer数据库中做了数据持久化
    3. 设计了登录/注册等功能

    上次我们讲的比较简单。所以说本文就开始写如何对这些用户操作,为这些用户添加某些权限,或者使用策略限制用户访问不同的接口,达到不同的目的(这边文章选读性的)

    具体要做的功能是我是下图我箭头指出的框选区域

    从本篇开始,会开始精简一些机械化操作,部分操作会用图片来代替GIF图.会在调试、解决错误、运行示例的时候还是使用GIF图 同样,本文还是包含大量GIF图,请耐心等待加载


    为用户添加声明

    还记得我们第一章创建的Demo吗?我们当时引入Claim、Identitty等概念,仔细看一下,我们登录接口(生成Cookie接口)和我们使用.net core Identity接口有什么不同

    通过比对,我们很快发现,第一章写的Claims、ClaimsIdentity、ClaimsPrincipal在.Net Core Identity的项目登录中,没有使用到。

    如果我们要对一个接口进行限制,例如只有老板才能访问接口。我们在.Net Core Identity写的是完全没有办法实现这个功能的。所以我们需要改造一下。

    在Identity中对用户信息操作要使用的是UserManager这个接口,顺便说一句:UserManager是SignInManager的属性,即你可以只引入SignInManager,然后使用SignInManager.UserManager的方式来访问UserManager下面的方法和属性

    把代码改成下面

      代码如下

     1 [HttpPost]
     2         public async Task<IActionResult> Login(string username, string password)
     3         {
     4             var user = await _userManager.FindByNameAsync(username);
     5             if (user != null)
     6             {
     7                 var signResult = await _signInManager.PasswordSignInAsync(user, password, false, false);
     8                 if (signResult.Succeeded)
     9                 {
    10                     var claims = new List<Claim>()
    11                     {
    12                         new Claim(ClaimTypes.Name,user.UserName),
    13                         new Claim("Age","15"),
    14                     };
    15                     var r = await _signInManager.UserManager.AddClaimsAsync(user, claims);
    16                     if (r.Succeeded)
    17                     {
    18                         return RedirectToAction("Secert");
    19                     }
    20                 }
    21             }
    22             return RedirectToAction("Register");
    23         }

     从图中可以看到,我们跟第一章一样,给用户添加了Claim,然后调用了UserManager下面的AddClaimsAsync的方法,传递的参数是我们从数据库中获取出来的的User类型是IdentityUser和我们定义的Claims的集合。题外话:多个Claim组合然后找个签发机构,就会变成什么?

    然后我们为接口套上一层验证机制,只需要在Authorize的标签上赋值即可。为Secect接口加上验证。并且在Secert.cshtml将该用户的Claim显示出来

    代码如下

    1 <h1>这需要授权访问的页面</h1>
    2 
    3 
    4 @foreach (var item in User.Claims)
    5 {
    6     <p>@item.Type.Split('/')[item.Type.Split('/').Length - 1]:@item.Value</p>
    7 }

    运行结果如下

    修改或删除用户的Claim

    我们添加一个可以修改用户的页面,将上次的Update.cshtml页面搬出来修改一下

    1 <form formaction="/Home/ModifyUserClaim" method="post">
    2     <input name="username" value="@User.Claims.Where(i=>i.Type==ClaimTypes.Name).Select(p=>p.Value).FirstOrDefault()" />
    3     <button>确认修改</button>
    4 </form>

    修改接口:

    1 [HttpPost]
    2 public async Task<IActionResult> ModifyUserClaim(string username)
    3 {
    4    var newclaim =  new Claim(ClaimTypes.Name, "qqq");
    5    var user = await _userManager.FindByNameAsync(username);
    6    await _signInManager.UserManager.ReplaceClaimAsync(user, User.Claims.Where(u=>u.Type==ClaimTypes.Name).First(), newclaim);
    7    return View("Update");
    8 }

      删除接口

    1 [HttpPost]
    2 public async Task<IActionResult> RemoveUserClaim(string username)
    3 {
    4    var user = await _userManager.FindByNameAsync(username);
    5    await _signInManager.UserManager.RemoveClaimAsync(user, User.Claims.Where(u => u.Type == ClaimTypes.Name).First());
    6    return View("Update");
    7 }

     他们分别调用了ReplaceClaimAsync和RemoveClaimAsync。其余操作没什么差异

    基于策略的授权

    这个应用场景非常多,日常生活中肯定会碰到多多少少需要权限访问接口的业务。例如:公司员工信息表中,有些员工填写了出生日期,有些没有,填写的人可以访问生日福利接口,没填写的人拒绝访问。又或者说:没填写的人,但是他的职位是总经理以上级别,就可以不需要填写出生日期就可以访问这个接口。等等诸如此类的权限控制。所以我们这么做

    添加一个接口,和一个页面,加上Authorize(Policy ="HasBirthDay") 就是指定一个授权策略,这个授权策略名为HasBirthDay

     然后添加页面

     运行:很显然,会出错,提示没有找到一个名为HasBirthDay的授权策略。

    我们在Startp.cs中加入这个授权策略

    代码如下

    1  services.AddAuthorization(config => {
    2      var defaultPolicyBuilder = new AuthorizationPolicyBuilder();
    3      defaultPolicyBuilder.RequireClaim(ClaimTypes.DateOfBirth);
    4      config.AddPolicy("HasBirthDay", defaultPolicyBuilder.Build());
    5 });

    再次运行试试看:因为我们当面登录的用户中没有给与DateOfBirth的Claims所以会被强制跳转到拒绝授权的页面。

    我们给当前的用户加上DateOfBirth,试试看能不能访问,在Login出增加一行Claims

    运行:可以看到,成功运行小提示:请先清空浏览器的Cookies,否则还是会被拒绝的。

     

    基于角色的授权

    在.net中,有一个非常方便的授权模式就是基于角色的授权,例如,普通用户不能访问,管理员能访问,老板能访问,员工不能访问。基于角色的授权其实就是基于策略的授权的演化,本身属于策略的一部分。稍微改动一下代码,把Policy换成了Role 值从HasBirthDay改成了Boss

    运行试试看,很显然,我们又被拒绝了。

    我们在登录的时候增加以下代码:

    运行:可以看到,成功运行小提示:请先清空浏览器的Cookies,否则还是会被拒绝的。

     

    基于权限的认证显然比基于策略的使用方便很多,这也是.net 认证系统中非常闻名的一个方式,对付单个接口非常有用

    好了,本期文章就写到这里我们下次再见

    【从0开始.NET CORE认证】-1 认识认证和授权

    【从0开始.NET CORE认证】-2 使用.Net Core Identity和EF Core

  • 相关阅读:
    一文让你彻底了解卷积神经网络
    处理 3d 视频的简单理论基础
    ffmpeg 学习:000-概述和库的组成
    Linux 补丁 的简单使用: 制作补丁,打补丁,撤销补丁
    “反向传播算法”过程及公式推导
    机器学习:梯度下降算法原理讲解
    神经网络浅讲:从神经元到深度学习
    Git详解之安装
    Git详解之Git起步
    Git详解之协议/速度/安全
  • 原文地址:https://www.cnblogs.com/lihuadeblog/p/12199297.html
Copyright © 2020-2023  润新知