asp.net core系列 51 Identity 授权(下)
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 授权(下)的更多相关文章
- asp.net core系列 49 Identity 授权(上)
一.概述 授权是指用户能够访问资源的权限,如页面数据的查看.编辑.新增.删除.导出.下载等权限.ASP.NET Core 授权提供了多种且灵活的方式,包括:Razor pages授权约定.简单授权.R ...
- asp.net core系列 50 Identity 授权(中)
1.5 基于策略的授权 在上篇中,已经讲到了授权访问(authorization)的四种方式.其中Razor Pages授权约定和简单授权二种方式更像是身份认证(authentication) ,因为 ...
- asp.net core系列 46 Identity介绍
一. Identity 介绍 ASP.NET Core Identity是一个会员系统,可为ASP.NET Core应用程序添加登录功能.可以使用SQL Server数据库配置身份以存储用户名,密码和 ...
- asp.net core系列 52 Identity 其它关注点
一.登录分析 在使用identity身份验证登录时,在login中调用的方法是: var result = await _signInManager.PasswordSignInAsync(Input ...
- asp.net core系列 62 CQRS架构下Equinox开源项目分析
一.DDD分层架构介绍 本篇分析CQRS架构下的Equinox开源项目.该项目在github上star占有2.4k.便决定分析Equinox项目来学习下CQRS架构.再讲CQRS架构时,先简述下DDD ...
- asp.net core系列 48 Identity 身份模型自定义
一.概述 ASP.NET Core Identity提供了一个框架,用于管理和存储在 ASP.NET Core 应用中的用户帐户. Identity添加到项目时单个用户帐户选择作为身份验证机制. 默认 ...
- asp.net core系列 47 Identity 自定义用户数据
一.概述 接着上篇的WebAppIdentityDemo项目,将自定义用户数据添加到Identity DB,自定义扩展的用户数据类应继承IdentityUser类, 文件名为Areas / Ident ...
- asp.net core 系列 11 配置configuration (下)
四. 文件配置提供程序AddIniFile. AddXmlFile.AddJsonFile FileConfigurationProvider 是从文件系统加载配置的基类. 以下配置提供程序专用于特定 ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
随机推荐
- Centos6离线安装MySQL5.5.55-1(附带安装包及Perl依赖包)
资源包下载https://pan.baidu.com/s/1U3myYp4GSmDUfZocMWI9FA 密码:xdac 资源包所带有的资源截图 1.上传MySQL-client-5.5.55-1.l ...
- jenkins中集成commander应用
jenkins中集成commander应用 jenkins 集成测试 promotion 最近参加公司的集成测试平台的开发,在开发中遇到了不少问题,两个星期的迭代也即将完成,在这也用这篇博客记录下开发 ...
- PAT1070:Mooncake
1070. Mooncake (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Mooncake is ...
- Socket 聊天工具
package cn.davy.mychat; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FontD ...
- AWS的区域和可用区概念解释
AWS的每个区域一般由多个可用区(AZ)组成,而一个可用区一般是由多个数据中心组成.AWS引入可用区设计主要是为了提升用户应用程序的高可用性.因为可用区与可用区之间在设计上是相互独立的,也就是说它们会 ...
- 常见js特效的思路
1.焦点轮播路 1.布局:父容器用overflow:hidden隐藏多余的图片 2:通过ID获取到重要的元素(父容器.图片列表.左右切换按钮等) 给左右按钮加上点击事件,通过JS更新图片的位置,判断边 ...
- 监听Web容器启动与关闭
在Servlet API 中有一个 ServletContextListener 接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期. 要监听web ...
- linux释放内存的命令
释放cache: sync echo 3>/proc/sys/vm/drop_caches 释放swap: sync swapoff -a swapon -a 版权声明:本文为博主原创文章,未经 ...
- leetcode 26 80 删除已排序数组中重复的数据
80. Remove Duplicates from Sorted Array II Follow up for "Remove Duplicates":What if dupli ...
- ECMAScript简介以及es6新增语法
ECMAScript简介 ECMAScript与JavaScript的关系 ECMAScript是JavaScript语言的国际化标准,JavaScript是ECMAScript的实现.(前者是后者的 ...