1)Shiro授权过程
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)授权执行流程
- 执行subject.isPermitted(“user:create”)
- securityManager通过ModularRealmAuthorizer进行授权
- ModularRealmAuthorizer调用realm获取权限信息
- ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配
下一章我们详细Spring整合shiro的使用