//首先這里是java代碼,就是根據shiro-role.ini配置文件中的信息來得到role與用戶信息的對應關系
//從而來管理role
public 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異常。
到此基於資源的訪問控制(顯示角色)就完成了,也可以叫基於權限的訪問控制,這種方式的一般規則是“資源標識符:操作”,即是資源級別的粒度;這種方式的好處就是如果要修改基本都是一個資源級別的修改,不會對其他模塊代碼產生影響,粒度小。但是實現起來可能稍微復雜點,需要維護“用戶——角色,角色——權限(資源:操作)”之間的關系。