shiro2.3_权限

Permissions 权限

Shiro定义了一个许可声明, 定义了一个明确的行为或行动. 这是一个原始功能的声明在一个应用程序而已. 权限是最低级别的构造安全策略, 他们只明确定义应用程序可以做什么.

他们不描述谁能够执行的操作.

一些权限的例子:

  • 打开一个文件
  • 浏览 '/user/list' 网页
  • 打印文件
  • 删除用户 'jsmith'

规定谁(用户)允许做什么(权限)在某种程度上是分配权限的一种习惯做法. 这始终是通过应用程序数据模型来完成的, 并且在不同应用程序之间差异很大.

例如, 权限可以组合到一个角色中, 且该角色能够关联一个或多个用户对象. 或者某些应用程序能够拥有一组用户, 且这个组可以被分配一个角色, 通过传递的关联, 意味着所有在该组的用户隐式地获得了该角色的权限.

如何授予用户权限可以有很多变化 —— 基于应用需求来决定如何使其模型化.

通配符的权限

上述权限的例子, "打开文件"、"浏览'/user/list' 网页", 等都是有效的权限. 然而, 计算并解释这些自然语言字符串和确定用户是否允许执行这一行为将是非常困难的过程.

为了使此过程更容易处理且仍可读权限语句, Shiro 提供了强大的和直观的语法我们称之为 WildcardPermission

Simple Usage 简单示例

你想保护访问公司的打印机, 这样有些人就可以打印到特定的打印机, 而其他人可以查询什么工作目前在队列中.

一个非常简单的方法是授予用户 "queryPrinter" 权限. 然后你可以通过调用检查用户是否有 "queryPrinter" 权限:

subject.isPermitted("queryPrinter")

这是(大部分)相当于:

subject.isPermitted( new WildcardPermission("queryPrinter") )

但远不只这些.

简单的权限字符串可能在简单的应用程序中工作的很好, 但它需要你拥有像"printPrinter", "queryPrinter", "managePrinter"等权限. 你还可以通过使用通配符 "*" 授予用户任意权限(权限名任意), 这意味着他们在整个应用程序中拥有了所有的权限.

但使用这种方法没有办法说明用户具有 "所有打印机权限". 出于这个原因, Wildcard Permissions(通配符权限) 支持多层次的权限管理.

多个部分

通配符权限支持多层次或部件(parts)的概念. 例如, 你可以通过授予用户权限来调整之前那个简单的例子

printer:query

在这个例子中的冒号是一个特殊字符, 它用来分隔权限字符串的下一部件.

在该例中, 第一部分是权限被操作的领域(printer), 第二部分是被执行的操作(query). 上面的例子将被改为:

printer:print
printer:manage

对于能够使用的部件是没有数量限制的, 因此它取决于你的想象, 依据你可能在你的应用程序中使用的方法

多值

每个部件能够保护多个值. 因此, 除了授予用户 "printer:print" 和 "printer:query" 权限外, 你可以简单地授予他们一个:

printer:print,query

它能够赋予用户 print 和 query 打印机的能力. 由于他们被授予了这两个操作, 你可以通过调用下面的语句来判断用户是否有能力查询打印机:

subject.isPermitted("printer:query")

该语句将会返回true

所有值

如果你想在一个特定的部件给某一用户授予所有的值呢? 这将是比手动列出每个值更为方便的事情. 同样, 基于通配符的话, 我也可以做到这一点. 若打印机域有3 个可能的操作(query, print 和manage), 可以像下面这样:

printer:query,print,manage

简单点变成这样:

printer:*

然后, 任何对 "printer:XXX" 的权限检查都将返回 true , 以这种方式使用的通配符比明确地列出操作具有更好的尺度, 如果你不久为应用程序增加了一个新的操作, 你不需要更新使用通配符那部分的权限.

最后, 还可以在通配符权限字符串的任何部分中使用通配符标记. 例如, 如果要在所有域(不只是打印机)中授予用户"查看"操作, 可以授予:

*:view

这样任何对 "foo:view" 的权限检查都将返回true

实例级的访问控制

另一种常见的通配符权限用法是塑造实例级的访问控制列表. 在这种情况下, 你可以使用三个部件 —— 第一个是域, 第二个是操作, 第三个是被付诸实施的实例.

简单例子

printer:query:lp7200
printer:print:epsoncolor

第一个定义了查询拥有ID: lp7200 的打印机的行为. 第二条权限定义了打印到拥有 ID: epsoncolor 的打印机的行为.

如果你授予这些权限给用户, 那么他们能够在特定的实例上执行特定的行为. 然后你可以在代码中做一个检查:

if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
    // 返回ID: lp7200 的打印机的当前任务
}

这是体现权限的一个极为有效的方法. 但同样, 为所有的打印机定义多个实例ID 不能很好的扩展, 尤其是当新的打印机添加到系统的时候. 你可以使用通配符来代替:

printer:print:*

这个做到了扩展, 因为它同时涵盖了任何新的打印机. 你甚至可以运行访问所有打印机上的所有操作

printer:*:*

或在一台打印机上的所有操作:

printer:*:lp7200

或甚至特定的操作:

printer:query, print:lp7200

*通配符和,子部件分离器可用于权限的任何部分

缺省的部分

最后要注意的是权限分配: 缺省的部分意味着用户可以访问所有与之匹配的值, 换句话说

printer:print

等价于

printer:print:*

并且

printer

等价于

printer:*:*

然而,你只能从字符串的结尾处省略部件,因此这样的:

printer:lp7200

并不等价于

printer:*:lp7200

检查权限

虽然权限分配使用通配符较为方便且具有扩展性 ("printer:print:*" = 允许在任意打印机上打印), 但在运行时的权限检查应该始终基于大多数具体的权限字符串.定义权限时可以模糊匹配, 但权限检查时必须确定具体权限

例如,如果用户有一个用户界面, 他们想打印一份文档到 lp7200 打印机, 你应该通过执行这段代码来检查用户是否被允许这样做:

if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
    //用 lp7200 打印机来打印文档
}

这种检查非常具体和明确地反映了用户在那一时刻试图做的事情. 然而, 下面这个运行是检查是不理想的:

if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
    // 打印文档
}

为什么? 因为第二个例子表明对于下面的代码块的执行, 你必须能够打印到任何打印机. 请记住 "pinter:print" 是等价 "priner:print:*" 的 !

因此, 这是一个不正确的检查. 如果当前用户不具备打印到任何打印机的能力, 仅仅只有打印到 lp7200 和 epsoncolor 的能力, 该怎么办呢? 那么上面的第二个例子也绝不允许他们打印到 lp7200 打印机, 即使他们已被赋予了相应的能力 !

因此, 经验告诉我们在执行权限检查时, 应尽可能使用详细的权限字符串. 当然, 上面的第二块可能是在应用程序中别处的一个有效检查, 如果你真的想要执行该代码块, 比如用户被允许打印到任何打印机(令人怀疑, 但有可能). 你的应用程序将决定检查哪些有意义, 但一般情况下, 越具体越好.

隐含, 不相等(潜规则)

为什么运行时权限检查应该尽可能的具体, 但权限分配可以较为普通? 这是因为权限检查是通过隐含的逻辑来判断的 —— 而不是通过相等来检查.

也就是说, 如果一个用户被分配了 user: * 权限, 这意味着该用户可以执行 user:view 操作. user:* 字符串明显不等于 user:view , 但前者默认包含了后者. 因此 user:* 描述了 user:view 所定义的功能的一个超集

为了支持隐含规则, 所有权限都转换为实现 org.apache.shiro.authz.Permission 接口的对象实例. 这使得隐含逻辑可以在运行时执行, 并且隐含逻辑通常比简单的字符串相等性检查更复杂. 本文档中描述的所有通配符行为实际上都是由 org.apache.shiro.authz.permission.wildcardpmission 类实现的. 下面是一些更多的通配符权限字符串, 它们通过隐含方式确定如何访问:

user:*

同时隐含着删除一个用户的能力:

user:delete

同样地,

user:*:12345

同时隐含着更新 ID 为12345 的用户帐户的能力:

user:update:12345

而且

printer

隐含着打印到任何打印机的能力

printer:print
___________           .___         _____  _________ .__                   __                
\_   _____/ ____    __| _/   _____/ ____\ \_   ___ \|  |__ _____  _______/  |_  ___________ 
 |    __)_ /    \  / __ |   /  _ \   __\  /    \  \/|  |  \\__  \ \____ \   __\/ __ \_  __ \
 |        \   |  \/ /_/ |  (  <_> )  |    \     \___|   Y  \/ __ \|  |_> >  | \  ___/|  | \/
/_______  /___|  /\____ |   \____/|__|     \______  /___|  (____  /   __/|__|  \___  >__|   
        \/     \/      \/                         \/     \/     \/|__|             \/       

End of Chapter

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,873评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,483评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,525评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,595评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,018评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,958评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,118评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,873评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,643评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,813评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,293评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,615评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,306评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,170评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,968评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,107评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,894评论 2 278