Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[认证授权] 6.Permission Based Access Control

[认证授权] 6.Permission Based Access Control

作者头像
blackheart
发布于 2018-01-19 11:03:31
发布于 2018-01-19 11:03:31
1K00
代码可运行
举报
文章被收录于专栏:blackheart的专栏blackheart的专栏
运行总次数:0
代码可运行

那么当我们得到OAuth2的Access Token或者OIDC的Id Token之后,我们的资源服务如何来验证这些token是否有权限来执行对资源的某一项操作呢?比如我有一个API,/books,它具有如下5个操作:

POST /books

添加一本书

GET /books/{id}

获取一本书

PUT /books/{id}

更新一本书

DELETE /books/{id}

删除一本书

GET /books

获取书的列表

其伪代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Route("books")]
public class BooksController : Controller
{
    [HttpGet("")]
    public Book[] Get() { return null; }

    [HttpGet("{bookId}")]
    public Book Get(int bookId) { return null; }

    [HttpPost("")]
    public Book Post(Book book) { return null; }

    [HttpPut("{bookId}")]
    public Book Put(int bookId, Book book) { return null; }

    [HttpDelete("{bookId}")]
    public Book Delete(int bookId) { return null; }
}

那么我们先看看基于OAuth2的Access Token,OIDC的Id Token和传统的基于角色的权限控制是如何处理控制这些资源的操作。

1 OAuth2的Access Token之Scope

我们都知道OAuth2的最终产物是提供给我们一个Access Token,而这个Access Token中包含了一个Scope的字段,这个字段代表的是授权服务器或者资源拥有者授予第三方客户端允许操作资源服务器的哪些资源的范围。这里有一点需要注意的是,这个授权过程可以有资源拥有着的参与(Authorization Code,Implicit,Resource Owner Password Credentials Grant),也可以没有他的参与(Client Credentials Grant)。那么基于上述的books的资源,我们可以定义一个 user_manager 的Scope,来控制对books的五个操作的权限控制。那么Books的基于Scope的权限控制看起来就像是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Route("books")]
public class BooksController : Controller
{
    [HttpGet("")]
    [Scope("book_manager")]
    public Book[] Get() { return null; }

    [HttpGet("{bookId}")]
    [Scope("book_manager")]
    public Book Get(int bookId) { return null; }

    [HttpPost("")]
    [Scope("book_manager")]
    public Book Post(Book book) { return null; }

    [HttpPut("{bookId}")]
    [Scope("book_manager")]
    public Book Put(int bookId, Book book) { return null; }

    [HttpDelete("{bookId}")]
    [Scope("book_manager")]
    public Book Delete(int bookId) { return null; }
}

注意看红色的部分,为每一个操作都添加了一个Scope的描述。如果Access Token拥有user_manager这个Scope(不管他是OAuth2的哪一个授权方式颁发的,我们的最终代码部分只认Scope),那么对这些API的调用就是被允许的,否则视为无权操作。

2 OIDC的Id Token之sub

关于Id Token的用途以及其包含哪些信息请参考Id Token。Id Token和Access Token的不同之处在于它一定是包含某一个用户的标识 sub ,但是没有Scope,这是因为Id Token的用途是认证当前用户是谁,所以用户是必须存在的;由于仅仅是认证,则不会包含被认证用户可以做哪些操作之类的授权相关的事情。那么针对Id Token,我们的API应该如何进行权限管控呢?通常的做法是使用传统的基于校色的权限控制(Role Based Access Control)。其实现细节就不解释了,它的模型大致是:一个实体(用户或者组织)拥有一组角色,每一个角色代表着一组权限集合。感觉是不是和Scope很像呢,其实差不多。我们定义一个这样的角色 图书管理员 吧。这里是故意和Scope的命名区分开的,因为其来源不同,那么我们最终实现的时候也会是独立开来的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 [Route("books")]
 2 public class BooksController : Controller
 3 {
 4     [HttpGet("")]
 5     [Scope("book_manager")]
 6     [Role("图书管理员")]
 7     public Book[] Get() { return null; }
 8 
 9     [HttpGet("{bookId}")]
10     [Scope("book_manager")]
11     [Role("图书管理员")]
12     public Book Get(int bookId) { return null; }
13 
14     [HttpPost("")]
15     [Scope("book_manager")]
16     [Role("图书管理员")]
17     public Book Post(Book book) { return null; }
18 
19     [HttpPut("{bookId}")]
20     [Scope("book_manager")]
21     [Role("图书管理员")]
22     public Book Put(int bookId, Book book) { return null; }
23 
24     [HttpDelete("{bookId}")]
25     [Scope("book_manager")]
26     [Role("图书管理员")]
27     public Book Delete(int bookId) { return null; }
28 }

如果 sub 代表的用户自身拥有或者其所属的组织机构拥有(不管其是怎么组织管理的吧,最终我们可以知道这个用户是否具有某一个角色) 图书管理员 这个角色。则允许其访问books的这些操作。

3 以上两种方式的弊端在哪里?

其实不止以上两种,比如在Asp.Net Core中有内置的这些授权控制组件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1 [Authorize(Policy = "AtLeast21")]
2 public class AlcoholPurchaseController : Controller
3 {
4     public IActionResult Login() => View();
5 
6     public IActionResult Logout() => View();
7 }

以上这些本质上和上面的基于Scope和基于Role的属于同一种类型。我们这样做当然可以工作,但是问题来了,它们直观吗,灵活吗?繁琐吗?好用吗?能满足我们变化的需求吗?总有着一种把简单的事情搞复杂的感觉。比如现在我增需要增加一个角色,超级管理员,那么上述的代码是不是需要我们做出改变呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1 [HttpGet("")]
2 [Scope("book_manager")]
3 [Role("图书管理员","超级管理员")]
4 public Book[] Get() { return null; }

再比如,现在需要增加一个Scope book_reader ,它只能执行读取的操作,又要做出改变了吧。况且即使我们把Scope和Role合二为一了,还是混乱不堪。

4 基于权限为最小粒度的解决方案

那么造成这些问题的根本原因是什么?答:不管是Scope还是Role它们体现的都是一个隐式的描述信息,而不是某一个具体的操作行为的描述信息。既然我们知道了其症结所在,那么怎么解决这个问题呢?原理很简单,使用权限作为我们的最小单元,把Scope和Role等等还有其他的一些管理组织权限的概念都作为一个中间层,禁止它们出现在接口权限验证的地方,而是仅作为管理组织Permission的手段存在。然后改造上面的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 [Route("books")]
 2 public class BooksController : Controller
 3 {
 4     [HttpGet("")]
 5     [Permission("books.read")]
 6     public Book[] Get() { return null; }
 7 
 8     [HttpGet("{bookId}")]
 9     [Permission("book.read")]
10     public Book Get(int bookId) { return null; }
11 
12     [HttpPost("")]
13     [Permission("book.add")]
14     public Book Post(Book book) { return null; }
15 
16     [HttpPut("{bookId}")]
17     [Permission("book.edit")]
18     public Book Put(int bookId, Book book) { return null; }
19 
20     [HttpDelete("{bookId}")]
21     [Permission("book.delete")]
22     public Book Delete(int bookId) { return null; }
23 }

我们把每一个操作都定义一个权限Permission,不管你是Access Token的Scope,还是Role,都不会在这里出现。比如在检查超级管理员是不是能操作的时候,我们可以直接放行(把这些检查和我们对接口的操作权限的描述分开)。如果是名为book_reader的Scope的时候,我们让book_reader只关联books.read和book.read这两个Permission,而这种关联关系的管理,我们是可以通过数据存储来维持的,也很方便的提供管理页面来灵活的配置。而最终的代码上关心的只是Permission。这种方式可以称为Resource Based Access Control或者Permission Based Access Control

5 Apache Shiro

以上是我自己的一些理解和思路,然后我发现了Apache Shiro这个项目,感觉就像是找到了组织,Apache Shiro走的更远,而且为Permission定义了一套规则。强烈建议读一读https://shiro.apache.org/permissions.html这篇文档。而.Net这边就没有这么好的福气了,,,Asp.Net Core中的默认授权过滤器还是传统的方式。

不过基于Asp.Net Core的Filter:IAuthorizationFilter,我们可以把这一整套授权控制方式给替换掉:使用代码:https://github.com/linianhui/oidc.example/tree/master/src/web.oauth2.resources;Filters代码:https://github.com/linianhui/oidc.example/tree/master/src/aspnetcore.filters.permissions

从此和讨厌的 [Authorize(Roles ="图书管理员",Policy ="XXX")] 说再见。

以上只是个人的一些理解,如有错误,欢迎指正。

参考

https://shiro.apache.org/

强烈推荐:https://shiro.apache.org/permissions.html

https://stormpath.com/blog/new-rbac-resource-based-access-control

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-01-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
sed & awk 第二版学习(四)—— 基本 sed 命令
第一个命令可以和左大括号放置在同一行,但是右大括号必须自己单独处于一行。每个命令都可以有自己的地址并允许有多层分组。而且就像命令在大括号内的缩进方式一样,允许在行的开始处插入空格或制表符。要确保在大括号后没有空格。
用户1148526
2024/09/10
1580
sed & awk 第二版学习(五)—— 高级 sed 命令
高级命令改变执行或控制的流程顺序。sed 脚本中正常的控制流为:一行被读入模式空间并用脚本中的每个命令逐个应用于那一行;当到达脚本底部时,输出这一行并且清空模式空间;然后新行被读入模式空间,并且控制被转移回脚本顶端。
用户1148526
2024/09/20
1820
sed & awk 第二版学习(一)—— sed 与 awk 基本操作
有 3 种方式可以在 sed 命令行上指定多个指令: 1. 用分号分隔指令。
用户1148526
2024/08/21
1670
sed入门详解教程 原
    sed 是一个比较古老的,功能十分强大的用于文本处理的流编辑器,加上正则表达式的支持,可以进行大量的复杂的文本编辑操作。sed 本身是一个非常复杂的工具,有专门的书籍讲解 sed 的具体用法,但是个人觉得没有必要去学习它的每个细节,那样没有特别大的实际意义。网上也有很多关于 sed 的教程,我也是抱着学习的心态来学习 sed 的常见的用法,并进行系统的总结,内容基本覆盖了 sed 的大部分的知识点。文中的内容比较简练,加以实际示例来帮助去理解 sed 的使用。
拓荒者
2019/03/11
1.5K0
sed入门详解教程
                                                                            原
干货!上古神器 sed 教程详解,小白也能看的懂
熟悉 Linux 的同学一定知道大名鼎鼎的 Linux 三剑客,它们是 grep、awk、sed,我们今天要聊的主角就是 sed。
用户3105362
2021/02/04
2.6K0
干货!上古神器 sed 教程详解,小白也能看的懂
文本处理三剑客之sed
sed 全名为 stream editor,流编辑器,用程序的方式来编辑文本。sed 与vim等编辑器不同,sed 是一种非交互式编辑器(即用户不必参与编辑过程),它使用预先设定好的编辑指令对输入的文本进行编辑,完成之后再输出编辑结构。
用户4877748
2020/07/21
9670
《Linux命令行与shell脚本编程大全》第二十一章 sed进阶
本章介绍一些sed编辑器提供的高级特性。 21.1 多行命令 按照之前的知识,所有的sed编辑器命令都是针对单行数据执行操作的。 在sed编辑器读取数据流时,它会基于换行符的位置将数据分成行,一次处理一行数据。 有时会需要对跨多行的数据执行特定操作。 比如,在数据中查找一个长的短语Linux system Administrators Group.如果这个短语出现在两行当中,之前的知识就不够用了。 解决方案,sed编辑器包含了三个可用来处理多行文本的特殊命令: N:将数据流中的下一行加进来创建一个多行组(m
xcywt
2018/01/11
1.7K0
《Linux命令行与shell脚本编程大全》第二十一章 sed进阶
shell脚本–sed的用法[通俗易懂]
sed在处理文本时是逐行读取文件内容,读到匹配的行就根据指令做操作,不匹配就跳过。
全栈程序员站长
2022/09/19
4K0
shell脚本–sed的用法[通俗易懂]
命令行上的数据科学第二版 五、清理数据
两章前,在 OSEMN 数据科学模型的第一步,我们看到了从各种来源获取数据。这一章讲的都是第二步:清理数据。你看,你很少能立即继续探索甚至建模数据。您的数据首先需要清理或清理的原因有很多。
ApacheCN_飞龙
2023/03/31
2.8K0
sed的用法详解
概述:sed是流式编辑器,非交互式的基于模式匹配过滤及修改文本,可实现对文本的输出删除复制替换剪切等各种操作
xibianyu0202
2019/07/24
4.3K0
sed的用法详解
Sed三剑客入门与进阶
描述:功能强大的流式文本编辑器(流编辑器-Stream editor)进行文本过滤与格式化替换输出,是在进行文本处理中非常实用的工具,能够完美的配合正则表达式使用;
全栈工程师修炼指南
2022/09/28
3.2K0
Sed三剑客入门与进阶
Shell笔记5:sed用法详解
概述:sed是流式编辑器,非交互式的基于模式匹配过滤及修改文本,可实现对文本的输出删除复制替换剪切等各种操作
陪你听风
2021/03/31
1.4K0
shell脚本编写手册(2021重编)
{ #!/bin/sh # 在脚本第一行脚本头 # sh为当前系统默认shell,可指定为bash等shell shopt # 显示和设置shell中的行为选项 sh -x # 执行过程 sh -n # 检查语法 set -
IT运维技术圈
2022/06/26
3.4K0
Linux三剑客命令之Sed
sed是一种流编辑器,也是文本处理中非常好的工具,配合正则使用更强大处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区的内容,完成后输出到屏幕,接着处理下一行
民工哥
2020/09/16
1.5K0
实例详解linux文本三剑客--sed
sed 简介 sed是一种流编辑器,以行为单位进行文本处理,可以将数据行进行替换、删除、新增、选取等操作。 sed [options] 'command' file(s) 基本命令 匹配内容 $ sed 'p' /etc/passwd # 每一行输出两次 $ sed -n 'p' /etc/passwd # 每行只出现一次 $ sed -n '/root/p' /etc/passwd root:x:0:0:root:/root:/bin/zsh # 等同于 $ grep 'root' /etc/pas
章鱼喵
2018/06/27
9580
【Linux篇】--sed的用法
Sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
LhWorld哥陪你聊算法
2018/09/13
1.6K0
精简运维流程:grep、awk、sed三剑客的实用脚本
以下这些操作不用刻意去背或记,只要多加练习,自然而然就会用。我这里只挑常用的参数,更详细的参数,大家可以自行搜索查阅。
希里安
2024/01/22
3360
精简运维流程:grep、awk、sed三剑客的实用脚本
Linux:sed命令详解
1. 简介 sed 是非交互式的编辑器。它不会修改文件,除非使用 shell 重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。 sed 编辑器逐行处理文件(或输入),并将结果发送到屏幕。具
张戈
2018/03/23
7.3K0
Linux:sed命令详解
Linux三剑客(grep、sed、awk)
下面所说的是Linux中最重要的三个命令在业界被称为“三剑客”,它们是awk,sed,grep。
全栈程序员站长
2022/07/21
2.8K0
Linux三剑客(grep、sed、awk)
Shell三大利器之sed
sed (stream editor)流编辑器也是linux中的一条命令,在shell中经常需要用到的非交互式修改文件内容的命令。sed处理文本是按行处理,也就是读一行处理一行。 sed的常用参数 -n 屏蔽默认输出;如果不加-n选项会全部输出文本满足条件的行再重复输出 -r 如果使用扩展正则,则需要添加-r选项,默认不支持扩展正则,只支持标准正则 -i 直接修改源文件;不加-i只会在屏幕临时输出不会修改源文件,一般测试过命令无误才会在脚本中使用-i选项 sed常用命令 a 在当前行后添加一行或多行。多行时
入门笔记
2021/01/18
2.2K0
相关推荐
sed & awk 第二版学习(四)—— 基本 sed 命令
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验