Shiro授权
1.授权流程
2.授权方式
Shiro 支持三种方式的授权:
1.编程式:通过写if/else 授权代码块完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}
2.注解式:通过在执行的Java方法上放置相应的注解完成:
@RequiresRoles("admin")
public void hello() {
//有权限的操作
}
3.JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:####
<shiro:hasRole name="admin">
<!— 有权限—>
</shiro:hasRole>
3.入门测试程序
测试分为基于角色的权限控制和基于资源的权限控制(开发中建议使用)
1. 创建shiro-permission.ini文件模拟数据源
#用户
[users]
#用户zhang的密码是123,此用户具有role1和role2两个角色
zhang=123,role1,role2
wang=123,role2
#权限
[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
#角色role2对资源user拥有create、delete权限
role2=user:create,user:delete
#角色role3对资源user拥有create权限
role3=user:create
权限标识符号规则:资源:操作:实例(中间使用半角:分隔)
user:create:01 表示对用户资源的01实例进行create操作。
user:create 表示对用户资源进行create操作,相当于user:create:*,对所有用户资源实例进行create操作。
user:*:01 表示对用户资源实例01进行所有操作。
2. 测试代码
public void testPermission(){
//根据ini文件创建SecurityManagerFactory
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
SecurityManager securityManager = factory.getInstance();
//将securityManager设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//创建主体对象
Subject subject = SecurityUtils.getSubject();
//有身份和凭证信息生成一个token
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
boolean isAuthenticated = subject.isAuthenticated();
System.out.println("用户认证状态: "+isAuthenticated);
//基于角色的权限控制
boolean isHasRole1 = subject.hasRole("role1");
System.out.println("是否有role1角色: "+isHasRole1);
boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3"));
System.out.println("是否有所有角色: "+hasAllRoles);
//使用check进行授权,如果授权失败则拋异常
subject.checkRole("role1");
subject.checkRoles("role1","role2");
//基于资源的权限控制
boolean isPermitted = subject.isPermitted("user:create");
System.out.println("是否拥有该权限: "+isPermitted);
boolean isPermittedAll = subject.isPermittedAll("user:create:1","user:delete");
System.out.println("是否拥有所有的权限: "+isPermittedAll);
//使用check进行授权,如果授权失败则拋异常
subject.checkPermission("user:create");
subject.checkPermissions("user:create","user:delete");
}
4.自定义realm
这里用到的是基于资源的权限控制
1.在自定义realm完善doGetAuthorizationInfo()方法
// 授权
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//获取身份信息
String principal = (String)principals.getPrimaryPrincipal();
//根据身份信息从数据库中获取权限数据
//使用静态数据进行模拟...
List<String> permissions = new ArrayList<String>();
permissions.add("user:create");
permissions.add("user:delete");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//将权限数据封装到SimpleAuthorizationInfo对象中
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
2.ini配置文件还使用认证阶段使用的,不用改变。
[main]
#自定义realm
customRealm=com.ak.shiro.CustomRealm
#将realm设置到securityManager
securityManager.realms=$customRealm
5.授权流程
1、对subject进行授权,调用方法isPermitted(”permission串”)
2、SecurityManager执行授权,通过ModularRealmAuthorizer执行授权
3、ModularRealmAuthorizer执行realm(自定义的CustomRealm)从数据库查询权限数据
调用realm的授权方法:doGetAuthorizationInfo
4、realm从数据库查询权限数据,并返回给ModularRealmAuthorizer
5、ModularRealmAuthorizer调用PermissionResolver进行权限串比对
6、如果比对后,isPermitted中”permission串”在realm查询到权限数据中,说明用户访问permission串有权限,否则 没有权限,抛出异常。