Shiro(三)——Shiro授权入门案例

1)Shiro授权过程

Shiro(三)——Shiro授权入门案例_第1张图片


2)授权方式

shiro支持三种方式的授权:

  • 编程式:通过写if/else授权代码块完成:
Subject  subject = SecurityUtils.getSubject();
if(subject.hasRole("admin")){
  //有权限
}else{
   //无权限
}
  • 注解方式:通过在执行的java 方法上放置相应的注解完成:
@RequiresRoles("admin")
public void hello(){
  //有权限
}
  • jsp标签: 在jsp页面通过相应的标签完成
<shiro:hasRole name="admin">
<!-- 有权限 -->
</shiro:hasRole>

3)编写shiro-permission.ini

创建存放权限的配置文件shiro-permission.ini,里面的内容相当于在数据库里面:

[users]
#用户admin的密码是123,此用户具有role1和role2两个角色
admin=123,role1,role2
#zs的密码是123,此用户拥有role2角色
zs=123,role2

[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
#角色role2对资源user拥有create权限
role2=user:create

在ini文件中用户、角色、权限的配置规则是:“用户名=密码,角色1,角色2…” “角色=权限1,权限2…”,首先根据用户名找角色,再根据角色找权限,角色是权限集合。

权限字符串规则

权限字符串的规则是:“资源标识符:操作:资源实例标识符”,意思是对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。
例子:

  • 用户创建权限:user:create,或user:create:*
  • 用户修改实例001的权限:user:update:001
  • 用户实例001的所有权限:user:*:001

4)测试代码

@Test
public void testPermission(){
	//创建securityManager工厂,通过ini配置文件创建securityManager工厂
	Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-permission.ini");
	
	//创建SecurityManager
	SecurityManager securityManager=factory.getInstance();
	
	//将securityManager设置到当前运行环境中
	SecurityUtils.setSecurityManager(securityManager);
	
	//从SecurityUtils里边创建一个subject
	Subject subject = SecurityUtils.getSubject();
	//对主体对象进行认证
	//用户登录
	//设置用户认证的身份(prinicipals)和凭证(credentials)
	UsernamePasswordToken token = new UsernamePasswordToken("admin", "123");
	
	subject.login(token);
	
	//用户认证状态
	//是否认证通过
	boolean isAuthenticated =subject.isAuthenticated();
	System.out.println("是否认证通过:"+isAuthenticated);
	
	//用户授权检测 基于角色授权
	//是否有某一个角色
	System.out.println("用户是否拥有一个角色:" + subject.hasRole("role1"));
	// 是否有多个角色
	System.out.println("用户是否拥有多个角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2")));  
	//判断角色 没有则直接报异常
    	//subject.checkRole("role2");
	// 基于资源授权
	System.out.println("是否拥有某一个权限:" + subject.isPermitted("user:delete"));
	//检查权限
	//subject.checkPermission("sys:user:delete");
	//subject.checkPermissions("user:create:1","user:delete");
}

5)自定义realm

与上面认证自定义realm一样,大部分情况是要从数据库获取权限数据,这里直接实现基于资源的授权。

编写自定义realm

在认证章节写的自定义realm类中完善doGetAuthorizationInfo方法,此方法需要完成:根据用户身份信息从数据库查询权限字符串,由shiro进行授权。

@Override
protected AuthorizationInfo doGetAuthorizationInfo(
		PrincipalCollection principals) {
	//获取身份信息
	String username=(String) principals.getPrimaryPrincipal();
	//根据身份信息从数据库中查询权限数据
	//...从这里使用静态数据模拟
	List<String> permissions=new ArrayList<String>();
	permissions.add("user:create");
	permissions.add("user:delete");
	
	//将权限信息封闭为AuthorrizationInfo
	SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
	for(String permission:permissions){
		simpleAuthorizationInfo.addStringPermission(permission);
	}
	return simpleAuthorizationInfo;
}

配置realm

ini配置文件还使用认证阶段使用的,不用改变。

修改test中创建securityManager工厂的配置文件

//创建securityManager工厂,通过ini配置文件创建securityManager工厂
Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-realm.ini");

6)授权执行流程

  1. 执行subject.isPermitted(“user:create”)
  2. securityManager通过ModularRealmAuthorizer进行授权
  3. ModularRealmAuthorizer调用realm获取权限信息
  4. ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配

下一章我们详细Spring整合shiro的使用

你可能感兴趣的:(shiro)