shiro教程(3)-shiro授权

时间:2022-06-12 17:00:50

shiro授权

 

1.1 授权流程

shiro教程(3)-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>

 

本教程序授权测试使用第一种编程方式,实际与web系统集成使用后两种方式。

 

1.3 授权测试

1.3.1 shiro-permission.ini

创建存放权限的配置文件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


 

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

 

 

 

1.3.2 权限字符串规则

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

 

例子:

用户创建权限:user:create,或user:create:*

用户修改实001的权限:user:update:001

用户实例001的所有权限:user*001

 

 

1.3.3 测试代码

 

测试代码同认证代码,注意ini地址改为shiro-permission.ini,主要学习下边授权的方法,注意:在用户认证通过后执行下边的授权代码。

 

@Test

public void testPermission() {



// 从ini文件中创建SecurityManager工厂

Factory<SecurityManager> factory = new IniSecurityManagerFactory(

"classpath:shiro-permission.ini");



// 创建SecurityManager

SecurityManager securityManager = factory.getInstance();



// 将securityManager设置到运行环境

SecurityUtils.setSecurityManager(securityManager);



// 创建主体对象

Subject subject = SecurityUtils.getSubject();



// 对主体对象进行认证

// 用户登陆

// 设置用户认证的身份(principals)和凭证(credentials)

UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");

try {

subject.login(token);

} catch (AuthenticationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}



// 用户认证状态

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("role1");

//subject.checkRoles(Arrays.asList("role1", "role2"));



// 授权检测,失败则抛出异常

// subject.checkRole("role22");



// 基于资源授权

System.out.println("是否拥有某一个权限:" + subject.isPermitted("user:delete"));

System.out.println("是否拥有多个权限:" + subject.isPermittedAll("user:create:1","user:delete"));

//检查权限

subject.checkPermission("sys:user:delete");

subject.checkPermissions("user:create:1","user:delete");



}


 

 

1.3.4 基于角色的授权

// 用户授权检测 基于角色授权

// 是否有某一个角色

System.out.println("用户是否拥有一个角色:" + subject.hasRole("role1"));

// 是否有多个角色

System.out.println("用户是否拥有多个角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2")));


 

对应的check方法:


subject.checkRole("role1");

subject.checkRoles(Arrays.asList("role1","role2"));

 

上边check方法如果授权失败则抛出异常:

org.apache.shiro.authz.UnauthorizedException: Subject does not have role [.....]


 

 

1.3.5 基于资源授权

 

// 基于资源授权

System.out.println("是否拥有某一个权限:" + subject.isPermitted("user:delete"));

System.out.println("是否拥有多个权限:" + subject.isPermittedAll("user:create:1","user:delete"));

对应的check方法:

subject.checkPermission("sys:user:delete");

subject.checkPermissions("user:create:1","user:delete");


 

 

上边check方法如果授权失败则抛出异常:

org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [....]


 

 

1.4 自定义realm

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

1.4.1 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");

//将权限信息封闭为AuthorizationInfo

SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

for(String permission:permissions){

simpleAuthorizationInfo.addStringPermission(permission);

}

return simpleAuthorizationInfo;

}


 

 

1.4.2 shiro-realm.ini

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


 

1.4.3 测试代码

同上边的授权测试代码,注意修改ini地址为shiro-realm.ini

 

 

1.4.4 授权执行流程

1、 执行subject.isPermitted("user:create")

2、 securityManager通过ModularRealmAuthorizer进行授权

3、 ModularRealmAuthorizer调用realm获取权限信息

4、ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配