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
.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串有权限,否则 没有权限,抛出异常。