1.6 基于资源的授权

  前面二篇中,熟悉了五种授权方式(对于上篇讲的策略授权,还有IAuthorizationPolicyProvider的自定义授权策略提供程序没有讲,后面再补充)。本篇讲的授权方式不是一种全新的授权方式,而是授权应用场景的灵活控制。

  基于资源的授权是控制在 razor pages处理程序或mvc的action之中。资源:比如作者发表的文章,只有该作者才能更新文章,文章在进行授权评估之前,必须从数据存储中检索文章。

  (1) 引用 IAuthorizationService 授权服务

    授权作为实现IAuthorizationService服务并注册到服务集合的Startup类。 下面在mvc action中引用该接口,准备进行授权控制。

    public class DocumentController : Controller
{ private readonly IAuthorizationService _authorizationService;
private readonly IDocumentRepository _documentRepository; public DocumentController(IAuthorizationService authorizationService,
IDocumentRepository documentRepository)
{
_authorizationService = authorizationService;
_documentRepository = documentRepository;
}
}

    IAuthorizationService接口有二个AuthorizeAsync方法重载:

        //重载1:指定资源resource和策略需求列表
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements);
//重载2:指定资源resource和策略名称
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName);

  (2) 授权需求定义

    基于 CRUD (创建、 读取、 更新、 删除) 的授权操作,使用OperationAuthorizationRequirement帮助器类,来提供一些授权名称。

    /// <summary>
///授权四种需求Crud
/// </summary>
public static class Operations
{
public static OperationAuthorizationRequirement Create =
new OperationAuthorizationRequirement { Name = nameof(Create) };
public static OperationAuthorizationRequirement Read =
new OperationAuthorizationRequirement { Name = nameof(Read) };
public static OperationAuthorizationRequirement Update =
new OperationAuthorizationRequirement { Name = nameof(Update) };
public static OperationAuthorizationRequirement Delete =
new OperationAuthorizationRequirement { Name = nameof(Delete) };
}

  (3) 定义处理程序

    /// <summary>
/// 接口AuthorizationHandler<TRequirement, TResource>
/// 使用OperationAuthorizationRequirement需求和Document资源
/// </summary>
public class DocumentAuthorizationCrudHandler: AuthorizationHandler<OperationAuthorizationRequirement, Document>
{ protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
OperationAuthorizationRequirement requirement,
Document resource)
{
//登录的当前用户是该文章作者,并且有读取权限。实际开发中从数据库读取TResource资源和requirement需求(需求这里是CRUD权限)
//动态获取时,可以基于用户声明表UserClaim,也可以基于角色声明表RoleClaim,使用context.User.HasClaim 来判断
if (context.User.Identity?.Name == resource.Author &&
requirement.Name == Operations.Read.Name)
{
context.Succeed(requirement);
} return Task.CompletedTask;
}
}

  (4) Action中使用AuthorizeAsync验证授权

    当用户登录后,要访问该文章页面时(/Document/index/1),使用AuthorizeAsync方法进行调用,确定当前用户是否允许查看提供的文章.

        /// <summary>
/// /Document/index/1
/// </summary>
/// <param name="documentId"></param>
/// <returns></returns>
public async Task<IActionResult> Index(int documentId)
{
Document Document = _documentRepository.Find(documentId); if (Document == null)
{
return new NotFoundResult();
} //使用AuthorizeAsync重载方法(1), 来验证用户访问资源权限,条件是当前用户必需是924964690@qq.com,因为是该用户的文章
var authorizationResult = await _authorizationService.AuthorizeAsync(User, Document, Operations.Read); //如果授权成功,则返回查看文档的页面
if (authorizationResult.Succeeded)
{
return View();
}
//用户已通过身份验证,但授权失败
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
//Challenge:怀疑,返回重新执行身份认证,重定向到登录页
return new ChallengeResult();
}
}

  (5) Document实体的定义和该实体仓储

    public class Document
{
public string Author { get; set; } public byte[] Content { get; set; } public int ID { get; set; } public string Title { get; set; }
}
public class DocumentRepository : IDocumentRepository
{
public Document Find(int documentId)
{
return new Document
{
Author = "924964690@qq.com",
Content = null,
ID = documentId,
Title = "Test Document"
};
}
} public interface IDocumentRepository
{
Document Find(int documentId);
}

  (6) 添加路由规则,和注入IAuthorizationService服务

    services.AddSingleton<IAuthorizationHandler, DocumentAuthorizationCrudHandler>();
   routes.MapRoute(
  name: "document",
  template: "{controller=Document}/{action=Index}/{documentId?}");

    最后当924964690@qq.com用户登录成功后,访问Document/index/1,查看该文章成功。

  总结:基于资源的授权,是应用在mvc的action 中或razor pages处理程序中,是区别之前的几种授权方式, 因为之前讲的授权是:启动程序时授权文件或文件夹,在控制器 action 和PageModel之上应用[Authorize]特性。

       对于AuthorizeAsync重载方法(2)的使用案例查看官网文档,这里不在介绍。

  思考:在实际开发项目中,处理资源如(增、删、改、查)权限,可以考虑本篇的基于资源的授权,但上面的示例需要改进,因为示例中定义的处理程序只针对Document资源,以及需求(指权限)是写死在处理程序中。如果要实现通用的资源授权,资源和需求权限需要从数据库中获取。例如考虑如下修改:

         //定义通用的TResource
public class AuthorizationResource
{
public string UrlResource{get;set;}
}
       //在index的action中修改
.AuthorizeAsync(User, new AuthorizationResource (){UrlResource="/Document/index/1" }, Operations.Read);
      //处理程序修改,省略了授权逻辑处理(数据库获取需求和资源)
public class DocumentAuthorizationCrudHandler: AuthorizationHandler<OperationAuthorizationRequirement, AuthorizationResource >

    

1.7 基于视图的授权    

  在项目开发中,授权权限还需要控制页面,对页面的html进行显示或隐藏。需要在页面上使用授权服务依赖关系注入,若要将授权服务注入到 Razor 视图中,使用@inject指令。如果希望每个视图都能使用授权服务,需要将@inject指令插入 _ViewImports.cshtml的文件视图中。下面的视图授权控制是基于资源的授权

    @using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
    <!--  指定策略名称  !-->
  @if ((await AuthorizationService.AuthorizeAsync(User, "PolicyName")).Succeeded)
  {
   <p>This paragraph is displayed because you fulfilled PolicyName.</p>
  }
    <!--  Model是指TResource !-->
   @if ((await AuthorizationService.AuthorizeAsync(User, Model, Operations.Edit)).Succeeded)
  {
  <p><a class="btn btn-default" role="button"
   href="@Url.Action("Edit", "Document", new { id = Model.Id })">Edit</a></p>
  }

  总结:视图中授权控制不能保证权限安全,还需要在action中实现授权服务。开源Github

  参考文献

    基于资源的授权

    基于视图的授权

asp.net core系列 51 Identity 授权(下)的更多相关文章

  1. asp.net core系列 49 Identity 授权(上)

    一.概述 授权是指用户能够访问资源的权限,如页面数据的查看.编辑.新增.删除.导出.下载等权限.ASP.NET Core 授权提供了多种且灵活的方式,包括:Razor pages授权约定.简单授权.R ...

  2. asp.net core系列 50 Identity 授权(中)

    1.5 基于策略的授权 在上篇中,已经讲到了授权访问(authorization)的四种方式.其中Razor Pages授权约定和简单授权二种方式更像是身份认证(authentication) ,因为 ...

  3. asp.net core系列 46 Identity介绍

    一. Identity 介绍 ASP.NET Core Identity是一个会员系统,可为ASP.NET Core应用程序添加登录功能.可以使用SQL Server数据库配置身份以存储用户名,密码和 ...

  4. asp.net core系列 52 Identity 其它关注点

    一.登录分析 在使用identity身份验证登录时,在login中调用的方法是: var result = await _signInManager.PasswordSignInAsync(Input ...

  5. asp.net core系列 62 CQRS架构下Equinox开源项目分析

    一.DDD分层架构介绍 本篇分析CQRS架构下的Equinox开源项目.该项目在github上star占有2.4k.便决定分析Equinox项目来学习下CQRS架构.再讲CQRS架构时,先简述下DDD ...

  6. asp.net core系列 48 Identity 身份模型自定义

    一.概述 ASP.NET Core Identity提供了一个框架,用于管理和存储在 ASP.NET Core 应用中的用户帐户. Identity添加到项目时单个用户帐户选择作为身份验证机制. 默认 ...

  7. asp.net core系列 47 Identity 自定义用户数据

    一.概述 接着上篇的WebAppIdentityDemo项目,将自定义用户数据添加到Identity DB,自定义扩展的用户数据类应继承IdentityUser类, 文件名为Areas / Ident ...

  8. asp.net core 系列 11 配置configuration (下)

    四. 文件配置提供程序AddIniFile. AddXmlFile.AddJsonFile FileConfigurationProvider 是从文件系统加载配置的基类. 以下配置提供程序专用于特定 ...

  9. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

随机推荐

  1. .net core使用Ku.Core.Extensions.Layui实现layui表单渲染

    演示网站地址:http://layui.kulend.com/项目地址:https://github.com/kulend/Ku.Core.Extensions/tree/master/Ku.Core ...

  2. JavaScript对json操作小记

    JSON是一种轻量级的数据交换格式,同时,JSON是 JavaScript 原生格式,因此我们可以直接处理它不需要依赖任何工具包或者插件.因此,好多后台都会选择返回给前端这种非常友好的数据格式. 引子 ...

  3. CSS命名规则常用的css命名规则

    CSS命名规则常用的css命名规则 头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wr ...

  4. CSS中的变形、过渡、动画效果

    一.变形 .过渡效果 1:元素平移 x方向 y方向 transform:translate(100px 100px); 2:过渡动画效果 a:什么属性参与过渡效果 b:过渡时间 c:过渡的效果 值包含 ...

  5. 基于Microsoft Graph打造自己的Timeline应用

    原文链接:https://github.com/chenxizhang/office365dev/blob/e9b5a59cb827841d36692cc4ec52c11d43062e04/docs/ ...

  6. sql中关于存在就不做操作的代码块

    前言: 在开发中,经常会对数据库表进行新增修改操作,那么如果表中的属性信息已然存在啦!就没必要去做重复的操作了... 代码块 BEGIN SELECT "COUNT"(*) int ...

  7. Asp.Net Core 2.0 项目实战(6)Redis配置、封装帮助类RedisHelper及使用实例

    本文目录 1. 摘要 2. Redis配置 3. RedisHelper 4.使用实例 5. 总结 1.  摘要 由于內存存取速度远高于磁盘读取的特性,为了程序效率提高性能,通常会把常用的不常变动的数 ...

  8. 关于ArrayList的5道面试题

    我以面试官的身份参加过很多Java的面试,以下是五个比较有技巧的问题,我发现有些初级到中级的Java研发人员在这些问题上没有完全弄明白,似懂非懂.所以我写了一篇相关的文章,帮助初级Java研发人员弄清 ...

  9. win7 telnet命令无法开启的解决方案(不是内部命令或外部命令)

    如果你想在win 7上直接使用 telnet命令,却不能开启那怎么办呢?记得在Wingdows XP上telnet都是已经安装好的,直接就可用,但是Win7是没有这个功能的,都需要后来自己安装的,下面 ...

  10. 使用STM32Cube在STM32F7开发板上实现SD+Freertos+Fatfs

    简介 最近项目中可能需要使用到SD卡,所以需要对SD卡的配置和使用调研,在配置过程中遇到了一些问题,在此记录一下. STM32Cube配置 Pinout 只需要注意绿色部分的设定 Clock配置 这里 ...