//首先这里是java代码,就是根据shiro-role.ini配置文件中的信息来得到role与用户信息的对应关系//从而来管理rolepublic class TestShiroRoleTest extends Test2{ @Test public void testHasRole(){ login("classpath:shiro-role.ini","zhang","123"); //判断拥有角色role1 Assert.assertTrue(SecurityUtils.getSubject().hasRole("role1")); //判断拥有角色role1 and role2 对这里是否含有所有role进行判断 Assert.assertTrue(SecurityUtils.getSubject().hasAllRoles(Arrays.asList("role1","role2"))); //判断拥有角色role1 and role2 and role3 分别对是否含有这里的每一个role进行判断 boolean[] result = SecurityUtils.getSubject().hasRoles(Arrays.asList("role1","role2","role3")); Assert.assertTrue(result[0]); Assert.assertTrue(result[1]); Assert.assertTrue(result[2]); } }
shiro-role.ini配置文件中的内容如下所示
然后是Test2的文件中,封装了用户登录和注销时的一些释放工作
public abstract class Test2 { @After public void tearDown() throws Exception{ ThreadContext.unbindSubject();//退出时请解除绑定Subject从当前线程中解绑Subject } protected void login(String configFile,String username,String password){ //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager Factory<org.apache.shiro.mgt.SecurityManager> factory= new IniSecurityManagerFactory(configFile); //2、得到SecurityManager实例,并绑定给SecurityUtils org.apache.shiro.mgt.SecurityManager securityManager=factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //3、得到Subject Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); subject.login(token); } }
2、Shiro提供了hasRole/hasRole用于判断用户是否拥有某个角色/某些权限;但是没有提供如hashAnyRole用于判断是否有某些权限中的某一个。
在断言其有异常抛出的时候,验证是成功的
Shiro提供了hasRole/hasRole用于判断用户是否拥有某个角色/某些权限;但是没有提供如hashAnyRole用于判断是否有某些权限中的某一个。
@Test(expected = UnauthorizedException.class) public void testCheckRole(){ login("classpath:shiro-role.ini","zhang","123"); //断言拥有角色:role1 SecurityUtils.getSubject().checkRole("role1"); //断言拥有角色:role1 and role3 失败抛出 异常 SecurityUtils.getSubject().checkRoles("role1","role3"); }
Shiro提供的checkRole/checkRoles和hasRole/hasAllRoles不同的地方是它在判断为假的情况下会抛出UnauthorizedException异常。
到此基于角色的访问控制(即隐式角色)就完成了,这种方式的缺点就是如果很多地方进行了角色判断,但是有一天不需要了那么就需要修改相应代码把所有相关的地方进行删除;这就是粗粒度造成的问题。
3、基于资源的访问控制(显示角色)
@Test public void testIsPermitted(){ login("classpath:shiro-permission.ini","zhang","123"); //判断拥有权限:user:create Assert.assertTrue(SecurityUtils.getSubject().isPermitted("user:create")); //判断拥有权限:usesr:update and user:delete同时拥有两个权限才返回true Assert.assertTrue(SecurityUtils.getSubject().isPermittedAll("user:create","user:update")); //判断没有权限:user:view Assert.assertFalse(SecurityUtils.getSubject().isPermitted("user:view")); }
Shiro提供了isPermitted和isPermittedAll用于判断用户是否拥有某个权限或所有权限,也没有提供如isPermittedAny用于判断拥有某一个权限的接口。
上边这个方法据测试居然不好用,第一个就报错,真是很奇怪
@Test public void testCheckPermission(){ login("classpath:shiro-permission.ini","zhang","123"); //断言拥有权限:user:create SecurityUtils.getSubject().checkPermission("user:create"); //断言拥有权限:user:delete and user:update SecurityUtils.getSubject().checkPermissions("user:delete","user:update"); //断言拥有权限:user:view失败抛出异常 SecurityUtils.getSubject().checkPermission("user:view"); }
但是失败的情况下会抛出UnauthorizedException异常。
到此基于资源的访问控制(显示角色)就完成了,也可以叫基于权限的访问控制,这种方式的一般规则是“资源标识符:操作”,即是资源级别的粒度;这种方式的好处就是如果要修改基本都是一个资源级别的修改,不会对其他模块代码产生影响,粒度小。但是实现起来可能稍微复杂点,需要维护“用户——角色,角色——权限(资源:操作)”之间的关系。