Shiro內置過濾器
認證相關過濾器:
anon(不需要任何認證直接可以訪問),authBasic(也就是httpBasic),authc(需要認證之后才可以訪問),user(需要當前存在用戶才可以訪問),logout(退出)
授權相關的過濾器:
perms(后面跟[ ] 里面加參數,表示具備一些權限才可以訪問),roles(與前者相似),ssl(要求是安全的協議才可以訪問,比如https),port(后面跟[ ] 里面放端口,必須是指定端口的才可以訪問)
(ps:ssl與port用的比較少)
測試一下以上部分過濾器:
@RequestMapping(value = "/testRole",method = RequestMethod.GET) @ResponseBody public String testRole(){ return "test Role success"; }
@RequestMapping(value = "/testRole1",method = RequestMethod.GET) @ResponseBody public String testRole1(){ return "test Role success"; }
@RequestMapping(value = "/testPerms",method = RequestMethod.GET) @ResponseBody public String testPerms(){ return "testPerms success"; } @RequestMapping(value = "/testPerms1",method = RequestMethod.GET) @ResponseBody public String testPerms1(){ return "testPerms1 success"; }
在spring.xml中配置一下:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!--登錄頁的url--> <property name="loginUrl" value="login.html"/> <!--未認證的跳轉頁面--> <property name="unauthorizedUrl" value="403.html" /> <!--過濾器鏈//從上往下匹配攔截認證,--> <property name="filterChainDefinitions"> <value> <!--登錄頁面不需要攔截--> /login.html = anon <!--提交登錄請求的url也不許要攔截--> /subLogin = anon /testRole = roles["admin"] /testRole1 = roles["admind","admin1"] /testPerms = perms["user:delete"] /testPerms1 = perms["user:delete","user:update"] <!--登錄頁面以外的需要攔截認證--> /* = authc </value> </property> </bean>
我的權限表如下:
1.先是訪問testRole:
說明登錄賬戶具備角色admin
2.訪問testRole1
跳轉
3.訪問testPerms 與一個相同
4.testPerms1也一樣
都ok。
這里配置的攔截
/testRole1 = roles["admind","admin1"]
必須同時擁有兩種角色才有權限訪問,那么如何讓登錄用戶擁有其中一個角色就可以訪問呢,這就需要自定義Filter了,
這之前需要先導入Servlet相關的依賴,不然方法會報紅:
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency>
自定義Filter:
public class RolesOrFilter extends AuthorizationFilter { @Override protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception { //先或得到主體 Subject subject = getSubject(servletRequest, servletResponse); //強轉String類型數組 String[] roles = (String[])o; if (roles == null || roles.length == 0){ return true; } //若不為空,遍歷一下數組 for (String role : roles) { //如果一經發現數組里有指定角色時,立即返回true if (subject.hasRole(role)){ return true; } } return false; } }
接着要去spring.xml配置注入自定義Filter:
<!--創建注入自定義Filter--> <bean class="com.yunyun.filter.RolesOrFilter" id="rolesOrFilter"/>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!--登錄頁的url--> <property name="loginUrl" value="login.html"/> <!--未認證的跳轉頁面--> <property name="unauthorizedUrl" value="403.html" /> <!--過濾器鏈//從上往下匹配攔截認證,--> <property name="filterChainDefinitions"> <value> <!--登錄頁面不需要攔截--> /login.html = anon <!--提交登錄請求的url也不許要攔截--> /subLogin = anon <!--/testRole = roles["admin"]--> /testRole2 = rolesOr["admin","admin1"] <!--/testPerms = perms["user:delete"]--> <!--/testPerms1 = perms["user:delete","user:update"]--> <!--登錄頁面以外的需要攔截認證--> /* = authc </value> </property> <property name="filters"> <util:map> <entry key="rolesOr" value-ref="rolesOrFilter"/> </util:map> </property> </bean> <!--創建注入自定義Filter--> <bean class="com.yunyun.filter.RolesOrFilter" id="rolesOrFilter"/>
在controller中添加:
@RequestMapping(value = "/testRole2",method = RequestMethod.GET) @ResponseBody public String testRole2(){ return "test Role2 success"; }
這里Controller層要注意,我發現加了@RequiresRoles("admin1")注解的方法,優先級要高於你自定義的攔截器,也就是說,只能用一個,不能都用= =。不知道這么理解有沒有問題,但是之前就沒注意,倆個一起用在同一個方法上,一直報錯
Subject does not have role [admin1]
,后來重寫了一個方法,不加注解,只用自定義的filter,就完全沒有問題了。
運行效果如下: