shiro授权的实现原理
这篇文章主要介绍了Shiro授权的实现原理,对于理解网络安全中的访问控制机制有着重要意义。随着互联网的普及,网络安全问题愈发重要,而授权作为其中的关键环节,更是不可忽视。接下来,我将为您详细解读这篇文章。
授权,也称访问控制,是指在应用中控制谁能访问哪些资源。在这个过程中,我们需要了解几个关键对象:主体、资源、权限和角色。
一、主体
主体即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有经过授权后,才能访问相应的资源。这种机制确保了只有具备相应权限的用户才能对特定资源进行访问和操作。
二、资源
资源是指用户在应用中可以访问的东西,如访问页面、查看或编辑数据等。只有经过授权的用户才能访问这些资源,这保证了数据的安全性和系统的稳定运行。
三、权限
权限是安全策略中的原子授权单位,表示用户在应用中能否访问某个资源。例如,访问用户列表页面、查看或修改数据等。权限反映了用户是否有权操作某个资源,但不反映由谁执行这个操作。Shiro主要提供授权框架,具体的权限分配需要由开发人员来实现。
四、角色
角色是操作的集合,可以理解为权限的集合。通常我们会赋予用户角色而非直接赋予权限,这样用户可以拥有一组权限,方便管理。不同的角色通常拥有不同的权限集合,如项目经理、技术总监等。
五、授权方式
Shiro支持三种授权方式:编程式、注解式和JSP/GSP标签式。
1. 编程式:通过编写if/else授权代码块来完成,根据用户的角色或权限来判断其是否有权访问某个资源。
2. 注解式:通过在执行的Java方法上放置相应的注解来完成。如果用户没有相应的角色或权限,将抛出异常。
3. JSP/GSP标签:在JSP/GSP页面通过相应的标签来完成。这适用于网页端的授权控制。
基于角色的访问控制(隐式角色)与基于资源的访问控制(显示角色)
一、基于角色的访问控制(隐式角色)
在信息安全领域,角色访问控制是一种常见且重要的安全策略。在 Shiro 安全框架中,我们可以通过 ini 配置文件来配置用户所拥有的角色。
例如,我们的配置文件(shiro-rolei)可能如下所示:
| 用户名 | 密码 | 角色 |
| | | |
| zhang | 123 | role1,role2 |
| wang | 123 | role1 |
这意味着用户 zhang 拥有 role1 和 role2 两个角色,而用户 wang 仅拥有 role1。在应用中,如果需要判断用户是否具有某个角色,就需要通过 Realm 返回角色信息。Shiro 只提供接口进行验证,不负责维护用户和角间的关系。如何动态获取用户角色,后续我们会详细介绍。
在测试案例中(RoleTest),我们可以使用 `hasRole` 和 `hasAllRoles` 方法来判断用户是否拥有某个或某些角色。例如:
```java
@Test
public void testHasRole() {
login("classpath:shiro-rolei", "zhang", "123");
Assert.assertTrue(subject().hasRole("role1")); // 判断用户是否拥有 role1 角色
Assert.assertTrue(subject().hasAllRoles(Arrays.asList("role1", "role2"))); // 判断用户是否拥有多个角色
// 其他角色判断...
}
```
Shiro 也提供了 `checkRole` 和 `checkRoles` 方法,它们在判断为假的情况下会抛出 UnauthorizedException 异常。这种方式虽然方便,但如果需要进行大量角色判断的地方进行修改,一旦策略改变,就需要修改相应代码。这就是所谓的粗粒度问题。
二、基于资源的访问控制(显示角色)
为了更精细地控制权限,我们可以采用基于资源的访问控制,也被称为显示角色。在这种模式下,我们不仅配置用户拥有的角色,还配置角色与权限的对应关系。
在 ini 配置文件(shiro-permissioni)中,我们可以这样配置:
| 用户名 | 密码 | 角色 | 权限 |
| | | | |
| zhang | 123 | role1,role2 | user:create,user:update |
| wang | 123 | role1 | user:create,user:delete |
3、单个资源的全面权限掌控
想象一下你在掌控一项资源的所有权限,如同执掌一方领土的君主。在ini配置文件中,你可以通过如下方式赋予用户“system:user”这一资源的所有权限:
role51="system:user:create,update,delete,view"
这样的配置意味着用户拥有创建、更新、删除和查看该资源的权限。为了验证这些权限,你可以使用以下代码:
subject().checkPermissions("system:user:create,delete,update:view");
简洁的写法可以这样:
role52=system:user:
或者
role53=system:user
通过代码验证:
subject().checkPermissions("system:user:");
subject().checkPermissions("system:user");
值得注意的是,“system:user:”这样的格式仅验证前缀,后缀的部分可以省略,但反过来则不成立。这样的设计为用户带来了极大的便利性和灵活性。
4、掌握所有资源的查看权限
想要拥有对所有资源的查看权限吗?只需进行如下的ini配置:
role61=:view
然后,通过代码验证用户的权限:
subject().checkPermissions("user:view");
这意味着用户拥有对所有资源的查看权限。如果想要验证特定资源的查看权限,如“system:user:view”,则需要使用不同的配置方式。这样的设计确保了权限管理的精细化和灵活性。
5、实例级别的权限掌控
除了资源级别的权限,还有实例级别的权限设置。让我们一一:
5.1 单个实例的单一权限:如资源user的实例1的查看权限,配置为role71=user:view:1。验证代码为:subject().checkPermissions("user:view:1");。
5.2 单个实例的多个权限:如资源user的实例1的更新和删除权限,配置为role72="user:update,delete:1"。验证代码为:subject().checkPermissions("user:delete,update:1"); 或 subject().checkPermissions("user:update:1", "user:delete:1");。
5.3 对单个实例的所有权限:配置为role73=user::1。验证代码为:subject().checkPermissions("user:update:1", "user:delete:1", "user:view:1");。这意味着用户拥有对该实例的所有操作权限。
5.4 所有实例的单一权限:如所有实例的认证权限,配置为role74=user:auth:。验证代码为:subject().checkPermissions("user:auth:1", "user:auth:2");。这种方式实现了对所有实例的同一权限的管理。需要注意的是,这种配置方式涵盖所有实例,不论其编号如何。当然还有其他类似的操作方式可以实现对特定实例的操作。总体来说,这些实例级别的权限管理方式提供了更为精细的控制和操作手段。同时允许用户在更广泛的场景下使用不同的配置来满足实际需求。此外还确保了安全性,确保用户不会滥用他们的权限来访问未经授权的资源或执行不当操作。用户权限与授权流程
在日常的系统权限管理中,我们经常面临复杂的权限匹配和授权流程。针对这些问题,有一套基于字符串匹配和通配符匹配的系统权限管理机制。下面,我将详细这一机制的工作原理和授权流程。
一、权限匹配规则
在权限匹配过程中,"user:"前缀用于标识用户相关的权限。其后可以跟多个冒号分隔的子字符串,如"view"、"delete"等,表示具体的操作权限。例如,"user:view:1"表示用户对于编号为1的资源的查看权限。这种前缀匹配方式允许灵活匹配不同的权限组合。系统还支持通配符匹配,如使用WildcardPermission进行权限匹配。在这种情况下,"menu:view:"可以匹配所有与菜单查看相关的权限。但需要注意的是,通配符匹配相对于字符串匹配更为复杂,需要花费更长的时间。
二、授权流程详解
授权流程主要涉及以下几个步骤:
1. 调用接口: 当系统接收到请求时,首先会调用Subject的isPermitted/hasRole接口进行权限检查。这些接口会委托给SecurityManager,进而委托给Authorizer进行实际授权判断。
2. 真正的授权者——Authorizer: Authorizer根据传入的权限字符串(如"user:view")通过PermissionResolver将其转换为相应的Permission实例。
3. 获取角色/权限: 在进行授权之前,Authorizer会从Realm获取Subject相应的角色和权限。如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断。
4. 匹配过程: Authorizer会判断从Realm获取的角色/权限是否与传入的角色/权限匹配。如果匹配成功,则返回true,表示授权成功;否则返回false。
如果使用的是ModularRealmAuthorizer进行多Realm匹配,流程稍有不同:
首先检查相应的Realm是否实现了Authorizer。
如果实现了,则调用其isPermitted/hasRole接口进行匹配。
只要有一个Realm匹配成功,即返回true;否则返回false。
对于基于Realm的授权,如果Realm需要自行处理授权逻辑,应继承AuthorizingRealm。在授权过程中,首先会通过PermissionResolver将权限字符串转换为Permission实例。接着,通过AuthorizationInfo获取对象的权限和字符串权限,并通过Permission与传入的权限进行比较。如果有匹配的权限,则返回true;否则返回false。通过这种方式,系统能够高效、灵活地处理各种复杂的权限匹配和授权需求。理解 Shiro 中的 Authorizer、PermissionResolver 及 RolePermissionResolver
在 Shiro 安全框架中,授权是保障数据安全的重要环节。在这一环节中,Authorizer 扮演着核心角色,负责进行访问控制,是授权决策的入口点。
Authorizer 的角色与功能
Authorizer 主要职责在于判断用户是否拥有某个角色或权限。当我们在应用中进行权限校验时,都会通过 Authorizer 来完成。SecurityManager 接口继承了 Authorizer,提供了丰富的授权功能。其中,ModularRealmAuthorizer 是为多个 Realm 提供的授权匹配实现,能够在多 Realm 环境下进行灵活的权限判断。
PermissionResolver 与 RolePermissionResolver 的作用
在授权过程中,除了角色和权限的判断,还需要将权限字符串为具体的 Permission 实例,这就需要用到 PermissionResolver。而 RolePermissionResolver 则负责根据角色出相应的权限集合,为授权提供数据支持。
如何配置 Authorizer
通过 INI 配置,我们可以轻松地更改 Authorizer 的实现。例如,我们可以使用以下配置来设置 ModularRealmAuthorizer:
```ini
authorizer=.apache.shiro.authz.ModularRealmAuthorizer
securityManager.authorizer=$authorizer
```
当 AuthorizingSecurityManager 初始化完成后,ModularRealmAuthorizer 会自动将对应的 realm 设置进去。我们也可以通过调用其 setRealms() 方法进行手动设置。
自定义 Authorizer
Shiro 提供了完善的授权机制,通过 Authorizer、PermissionResolver 及 RolePermissionResolver 等组件,确保了数据的安全性。开发者只需深入了解这些组件的作用,并合理进行配置和使用,就能为应用提供坚实的安全保障。在设置ModularRealmAuthorizer的权限器(permissionResolver)和角色权限器(rolePermissionResolver)时,它们会自动应用到相应的Realm上,这些Realm需要实现了PermissionResolverAware和RolePermissionResolverAware接口。这是Apache Shiro安全框架的一个重要特性。
以ini配置文件(shiro-authorizeri)为例,我们可以自定义authorizer,permissionResolver和rolePermissionResolver。这些自定义的器可以帮助我们更好地管理和理解权限和角色。比如,我们可以设置permissionResolver为.github.zhangkaitao.shiro.chapter3.permission.BitAndWildPermissionResolver,这样,我们的ModularRealmAuthorizer就会使用这个器来处理权限问题。同样的,我们也可以设置rolePermissionResolver为我们的自定义器。
在设置securityManager的realms时,必须放在设置authorizer之后。因为在调用SecurityManager.setRealms时,会将realms设置给authorizer,并为各个Realm设置permissionResolver和rolePermissionResolver。这里需要注意的是,不能使用IniSecurityManagerFactory创建的IniRealm,因为其初始化顺序可能会导致后续的初始化Permission受到影响。
我们还定义了BitAndWildPermissionResolver和BitPermission。BitPermission是用来实现位移方式的权限管理,比如权限字符串格式可以是“+资源字符串+权限位+实例ID”,以+开头并通过+进行分割。在这里,权限位是通过二进制表示的,例如0表示所有权限,1表示新增(二进制0001),2表示修改(二进制0010),4表示删除(二进制0100),8表示查看(二进制1000)。例如,“+user+10”就表示对资源user拥有修改和查看的权限。
这种设置方式可以让我们更灵活地管理权限和角色,从而更好地控制用户对不同资源的访问权限。通过自定义器,我们可以更好地适应不同的业务需求和场景。Apache Shiro提供了一个强大而灵活的安全管理解决方案。在编程世界中,权限管理是一项至关重要的任务,它确保了资源的安全性和系统的稳定运行。这里,我们有两个核心类:BitPermission和BitAndWildPermissionResolver,它们分别实现了Permission接口和PermissionResolver接口。接下来,让我们深入了解这两个类以及即将定义的MyRolePermissionResolver。
BitAndWildPermissionResolver类实现了PermissionResolver接口。它的主要任务是根据权限字符串的格式,出对应的BitPermission或WildcardPermission对象。如果权限字符串以“+”开头,那么就为BitPermission;否则,为WildcardPermission。这种方式确保了权限管理的灵活性和可扩展性。
接下来,我们将定义MyRolePermissionResolver,这是一个根据角色字符串权限集合的器。在这个器中,我们将实现一种机制,能够将从角色字符串中获取的信息转化为对应的权限集合。这将极大简化权限管理的工作,使得根据角色分配权限变得更为直观和方便。MyRolePermissionResolver将允许我们根据用户的角色,快速获取其对应的权限集合,从而进行访问控制等权限管理操作。
这些类的设计和实现都是为了更好地管理权限,确保系统的安全性和稳定性。它们通过不同格式的权限字符串,将复杂的权限管理逻辑简化,使得系统的权限管理更为灵活、直观和高效。随着MyRolePermissionResolver的加入,我们将能够更进一步地简化角色与权限之间的映射,提高权限管理的效率和准确性。我们将看到一个关于角色权限器(RolePermissionResolver)和自定义Realm的实现。这些实现是安全框架Shiro中的重要组成部分,用于处理用户的身份验证和授权。让我们深入理解一下这两个实现的细节。
我们来看RolePermissionResolver的实现。在这个例子中,我们有一个名为MyRolePermissionResolver的类,它实现了RolePermissionResolver接口。它的主要任务是角色中的权限。当用户的角色为role1时,它将返回一个WildcardPermission权限,这个权限允许用户访问菜单(menu:)。这个逻辑非常简单明了,但它为基于角色的权限管理提供了基础。
接下来,我们讨论自定义Realm的实现。Realm在Shiro中是一个核心组件,它负责与数据源(如数据库或文件)交互以获取用户信息和权限信息。在这个例子中,我们有一个名为MyRealm的类,它扩展了AuthorizingRealm。这意味着它可以提供授权信息,即根据用户的身份决定他们有权访问哪些资源。
这篇文章深入解释了Shiro中的RolePermissionResolver和自定义Realm的实现。通过理解这些实现的工作原理,你可以更好地在应用中实现基于角色的访问控制和用户身份验证。在测试环境中,我们经常需要进行权限验证,确保每一项操作都符合既定的安全策略。下面是一个关于自定义权限验证的测试案例,通过代码展示了一个名为AuthorizerTest的测试类。该类继承了BaseTest,并定义了一个名为testIsPermitted的测试方法。在这个测试方法中,详细展示了如何使用权限验证功能。
通过login方法登录系统并加载配置文件“shiro-authorizeri”,使用用户zhang和密码123进行身份验证。接下来,通过subject().isPermitted方法判断用户是否拥有特定的权限。这里进行了几个权限的判断测试,如user1和user2的更新权限、二进制位表示的新增、查看、删除等权限。通过断言Assert.assertTrue和Assert.assertFalse来验证权限的赋予与否。还展示了通过MyRolePermissionResolver得到的权限验证。这个测试案例展示了如何使用自定义的权限验证系统,确保系统中的操作符合设定的安全策略。
在实际应用中,权限验证是保障系统安全的重要一环。通过合理的权限设置和验证,可以确保只有具备相应权限的用户才能执行特定的操作,从而避免潜在的安全风险。这个测试案例为我们提供了一个很好的参考,帮助我们理解如何自定义权限验证,并根据实际需求进行配置和使用。
在进行权限验证时,我们可以根据具体的业务需求和系统特点进行定制化的配置。比如,可以根据角色的不同设置不同的权限范围,或者根据用户的身份和职责分配不同的操作权限。这样,我们可以更好地控制系统中的操作,确保系统的安全性和稳定性。
通过本文对测试用例的解读,相信大家对自定义权限验证有了更深入的了解。希望大家在学习过程中能够充分利用这些知识和技巧,为自己的系统搭建更加完善的安全体系。也希望大家能够关注和支持狼蚁SEO,共同学习进步。
通过自定义权限验证,我们可以更好地控制系统中的操作,确保只有具备相应权限的用户才能执行特定的任务。这对于保障系统安全、提高系统的稳定性和可靠性非常重要。希望通过本文的介绍和,能够帮助大家更好地理解和应用自定义权限验证的功能。
网络推广网站
- shiro授权的实现原理
- 苹果4s怎么连接电脑
- 如何改善极品飞车OL游戏体验 优化修改技巧有哪
- JavaScript日期对象(Date)基本用法示例
- Angular实现的日程表功能【可添加及隐藏显示内容
- vue 实现 ios 原生picker 效果及实现思路解析
- asp下IP地址分段计算函数
- SQLSERVER 创建索引实现代码
- Node.js+ES6+dropload.js实现移动端下拉加载实例
- 发如雪 歌词
- jQuery超精致图片轮播幻灯片特效代码分享
- 阿里斯顿售后服务
- 东航是哪里的航空公司
- 在AngularJS框架中处理数据建模的方式解析
- 基于Angularjs+mybatis实现二级评论系统(仿简书)
- 说了再见以后 歌词