专注Java教育14年 全国咨询/投诉热线:444-1124-454
赢咖4LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 了解Apache Shiro权限管理

了解Apache Shiro权限管理

更新时间:2022-02-08 10:51:04 来源:赢咖4 浏览579次

Shiro 将 Permission 定义为定义显式行为或动作的语句。它是应用程序中原始功能的声明,仅此而已。权限是安全策略中最低级别的结构,它们仅明确定义应用程序可以做什么。

他们根本没有描述“谁”能够执行这些操作。

一些权限示例:

打开一个文件

查看“/用户/列表”网页

打印文件

删除“jsmith”用户

定义“谁”(用户)被允许做“什么”(权限)是以某种方式为用户分配权限的练习。这始终由应用程序的数据模型完成,并且在应用程序之间可能会有很大差异。

例如,权限可以分组在一个角色中,并且该角色可以与一个或多个用户对象相关联。或者某些应用程序可以有一个用户组,并且可以为一个组分配一个角色,通过传递关联意味着该组中的所有用户都被隐式授予角色中的权限。

授予用户权限的方式有很多变化 - 应用程序根据应用程序要求确定如何对其进行建模。

通配符权限

上面的权限示例,“打开文件”,“查看‘用户/列表’网页”等都是有效的权限声明。但是,在计算上解释这些自然语言字符串并确定用户是否是非常困难的是否允许执行该行为。

因此,为了启用易于处理但仍然可读的权限语句,Shiro 提供了强大而直观的权限语法,我们称之为 WildcardPermission。

简单用法

假设您想保护对公司打印机的访问,以便某些人可以打印到特定的打印机,而其他人可以查询当前队列中的作业。

一个非常简单的方法是授予用户“queryPrinter”权限。然后您可以通过调用来检查用户是否具有 queryPrinter 权限:

subject.isPermitted("queryPrinter")

这(大部分)相当于

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

但稍后会详细介绍。

简单权限字符串可能适用于简单的应用程序,但它要求您具有“printPrinter”、“queryPrinter”、“managePrinter”等权限。您还可以使用通配符授予用户“*”权限(授予此权限构造它的名字),这意味着他们拥有整个应用程序的所有权限。

但是使用这种方法没有办法只说用户拥有“所有打印机权限”。因此,通配符权限支持多级权限。

多个零件

通配符权限支持多个级别或部分的概念。例如,您可以通过授予用户权限来重构前面的简单示例

printer:query

此示例中的冒号是一个特殊字符,用于分隔权限字符串中的下一部分。

在此示例中,第一部分是正在操作的域 ( printer),第二部分是query正在执行的操作 ( )。上面的其他示例将更改为:

printer:print
printer:manage

可以使用的部件数量没有限制,因此在您的应用程序中使用它的方式取决于您的想象力。

多个值

每个部分可以包含多个值。因此,您可以简单地授予用户一个“printer:print”和“printer:query”权限,而不是授予用户“printer:print”和“printer:query”权限:

printer:print,query

这使他们能够print和query打印机。由于他们被授予这两个操作,您可以通过调用来检查用户是否有能力查询打印机:

subject.isPermitted("printer:query")

这将返回true

所有价值观

如果您想授予用户特定部分中的所有值怎么办?这样做比手动列出每个值更方便。同样,基于通配符,我们可以做到这一点。如果printer域有 3 个可能的操作(query、print和manage),则:

printer:query,print,manage

简单地变成这样:

printer:*

然后,任何对“printer:XXX”的权限检查都会返回true。以这种方式使用通配符比明确列出操作具有更好的扩展性,因为如果您稍后向应用程序添加新操作,则无需更新在该部分中使用通配符的权限。

最后,还可以在通配符权限字符串的任何部分使用通配符标记。例如,如果您想授予用户跨所有域(不仅仅是打印机)的“查看”操作,您可以授予此权限:

*:view

然后对“foo:view”的任何权限检查都会返回true

检查权限

虽然权限分配使用通配符构造相当多(“打印机:打印:*”=打印到任何打印机)以方便和可扩展性,但运行时的权限检查应始终基于可能的最具体的权限字符串。

例如,如果用户有一个 UI 并且他们想将文档打印到lp7200打印机,您应该通过执行以下代码来检查用户是否被允许这样做:

if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
    //print the document to the lp7200 printer }
}

该检查非常具体,并明确反映了用户当时试图做什么。

但是,对于运行时检查,以下内容不太理想:

if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
    //print the document }
}

为什么?因为第二个示例说“您必须能够打印到任何打印机才能执行以下代码块”。但请记住,“printer:print”等价于“printer:print:*”!

因此,这是不正确的检查。如果当前用户没有能力打印到任何打印机,但他们确实有能力打印lp7200到打印机,该怎么办epsoncolor。那么上面的第二个示例将永远不允许他们打印到lp7200打印机,即使他们已被授予该能力!

因此,经验法则是在执行权限检查时尽可能使用最具体的权限字符串。当然,如果您真的只想在允许用户打印到任何打印机(怀疑,但可能)时执行代码块,那么上面的第二个块可能是应用程序中其他地方的有效检查。您的应用程序将确定哪些检查有意义,但一般来说,越具体越好。如果大家想了解更相关知识,不妨来关注一下赢咖4的Java视频,里面的课程细致全面,从入门到精通,适合没有基础的小白学习,希望对大家能够有所帮助。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>