shiro入门(二)授权

6 篇文章 0 订阅

授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、角色(Role)。

主体
主体,即访问应用的用户,在 Shiro 中使用 Subject 代表该用户。

资源
用户只要授权后才能访问。

权限
权限表示在应用中用户能不能访问某个资源。

Shiro 支持粗粒度权限(如用户模块的所有权限)和细粒度权限(操作某个用户的权限,即实例级别的)。

角色
角色代表了操作集合,即这样用户可以拥有一组权限,不同的角色拥有一组不同的权限。

隐式角色:(粗粒度权限)
即直接通过角色来验证用户有没有操作权限。

显式角色:(细粒度权限)
在程序中通过权限控制谁能访问某个资源,角色聚合一组权限集合。

代码示例:

shiro2.ini

[users]
zhang=123,role1,role2
wang=123,role3
[roles]
role1=user:create
role2=user:update
role3=user:detele

规则:“用户名=密码,角色 1,角色 2”“角色=权限 1,权限 2”,即首先根据用户名找到角色,然后根据角色再找到权限;

Permission字符串通配符权限

规则:“资源标识符:操作:对象实例 ID” 即对哪个资源的哪个实例可以进行什么操作。其默认支持通配符权限字符串,“:”表示资源/操作/实例的分割;“,”表示操作的分割;“*”表示任意资源/操作/实例。

基于角色的访问控制(隐式角色)Role.java

public class Role {
	 private void login(String configFile,String name,String password) {
	        //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
	        Factory<SecurityManager> factory =
	                new IniSecurityManagerFactory(configFile);
	        //2、得到SecurityManager实例 并绑定给SecurityUtils
	        SecurityManager securityManager = factory.getInstance();
	        SecurityUtils.setSecurityManager(securityManager);
	        //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
	        Subject subject = SecurityUtils.getSubject();
	        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
	        subject.login(token);
	    }
	   @Test(expected = UnauthorizedException.class)
	    public void testHasRole() {
		   login("classpath:shiro2.ini", "zhang", "123");
		   Subject subject = SecurityUtils.getSubject();
		   System.out.println("role1:"+subject.hasRole("role1")); 
		   System.out.println("role2:"+subject.hasRole("role2")); 
		   System.out.println("role3:"+subject.hasRole("role3")); 
		   boolean[] result = subject.hasRoles(Arrays.asList("role1", "role2", "role3"));
		   System.out.println("result[0]:"+result[0]);
		   System.out.println("result[1]:"+result[1]);
		   System.out.println("result[2]:"+result[2]);
		 
	    }
}

Shiro 提供了 hasRole/hasRoles 用于判断用户是否拥有某个角色/某些权限。

结果为:

role1:true
role2:true
role3:false
result[0]:true
result[1]:true
result[2]:false

基于资源的访问控制(显式角色)

@Test(expected = UnauthorizedException.class)
	    public void testCheckPermission () {
		   login("classpath:shiro2.ini", "zhang", "123");
		   Subject subject = SecurityUtils.getSubject();
		   System.out.println("isPermitted1:"+subject.isPermitted("user:create")); 
		   System.out.println("isPermitted2:"+subject.isPermittedAll("user:create","user:update")); 
		   System.out.println("isPermitted3:"+subject.isPermitted("user:view")); 
		
		 
	    }

Shiro 提供了 isPermitted 和 isPermittedAll 用于判断用户是否拥有某个权限或所有权限。

结果为:

isPermitted1:true
isPermitted2:true
isPermitted3:false

授权流程如下:

  1. 首先调用 Subject.isPermitted*/hasRole*接口,其会委托给 SecurityManager,而 SecurityManager 接着会委托给 Authorizer;
  2. Authorizer 是真正的授权者(Authorizer 的职责是进行授权(访问控制),是 Shiro API 中授权核心的入口点,其提供了相应的角色/权限判断接口,具体请参考其 Javadoc),如果我们调用如 isPermitted(“user:view”),其首先会通过 PermissionResolver 把字符串转换成相应的 Permission 实例;
  3. 在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的角色/权限;
  4. Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个 Realm,会委托给 ModularRealmAuthorizer 进行循环判断,如果匹配如 isPermitted*/hasRole* 会返回 true,否则返回 false 表示授权失败。

ModularRealmAuthorizer 进行多 Realm 匹配流程:

  • 首先检查相应的 Realm 是否实现了实现了 Authorizer;
  • 如果实现了 Authorizer,那么接着调用其相应的 isPermitted*/hasRole* 接口进行匹配;
  • 如果有一个 Realm 匹配那么将返回 true,否则返回 false。

如果 Realm 进行授权的话,应该继承 AuthorizingRealm,其流程是:

  • 如果调用 hasRole*,则直接获取 AuthorizationInfo.getRoles() 与传入的角色比较即可;首先如果调用如 isPermitted(“user:view”),首先通过 PermissionResolver 将权限字符串转换成相应的 Permission 实例,默认使用 WildcardPermissionResolver,即转换为通配符的 WildcardPermission;
  • 通过 AuthorizationInfo.getObjectPermissions() 得到 Permission 实例集合;通过 AuthorizationInfo.getStringPermissions() 得到字符串集合并通过 PermissionResolver 解析为 Permission 实例;然后获取用户的角色,并通过 RolePermissionResolver 解析角色对应的权限集合(默认没有实现,可以自己提供);
  • 接着调用 Permission.implies(Permission p) 逐个与传入的权限比较,如果有匹配的则返回 true,否则 false。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值