分享

我的shiro之旅: 四 自定义filter

 WindySky 2017-12-27

上一篇文章对shiro的filter作了一些简单的介绍,接一下写写息自定义shiro的filter。使用shiro的时候,比较常用的filter有anon,authc,roles和perms。当我们想定义某个链接是拥有某些权限的用户才可以访问的时候,我们可以这样定义。/xx = roles[A,B]。在shiro中,表示当前用户同时拥有A,B两种角色才可以访问/xx这个链接,是一种&&(与)的关系,我们可以看看源码。在shiro-web-xx.jar的org.apache.shiro.web.filter.authz包下有RolesAuthorizationFilter这样一个类,这个类就是定义roles的filter。

  1. public class RolesAuthorizationFilter extends AuthorizationFilter {  
  2.   
  3.     //TODO - complete JavaDoc  
  4.   
  5.     @SuppressWarnings({"unchecked"})  
  6.     public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {  
  7.   
  8.         Subject subject = getSubject(request, response);  
  9.         String[] rolesArray = (String[]) mappedValue;  
  10.   
  11.         if (rolesArray == null || rolesArray.length == 0) {  
  12.             //no roles specified, so nothing to check - allow access.  
  13.             return true;  
  14.         }  
  15.   
  16.         Set<String> roles = CollectionUtils.asSet(rolesArray);  
  17.         return subject.hasAllRoles(roles);  
  18.     }  
  19.   
  20. }  

上面定义了subject.hasAllRoles(roles);就是当前用户必须拥有定义的所有角色才会返回true。但有时候,我们需要当前用户拥有定义的其他一个角色就可以访问,那就需要写自己的filter。也很简单,代码以下:

  1. public class AnyRolesAuthorizationFilter extends AuthorizationFilter {  
  2.   
  3.       
  4.     @Override  
  5.     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {  
  6.   
  7.         Subject subject = getSubject(request, response);  
  8.         String[] rolesArray = (String[]) mappedValue;  
  9.   
  10.         if (rolesArray == null || rolesArray.length == 0) {  
  11.             // no roles specified, so nothing to check - allow access.  
  12.             return true;  
  13.         }  
  14.   
  15.         Set<String> roles = CollectionUtils.asSet(rolesArray);  
  16.         for (String role : roles) {  
  17.             if (subject.hasRole(role)) {  
  18.                 return true;  
  19.             }  
  20.         }  
  21.         return false;  
  22.     }  
  23.   
  24. }  

从上面的代码可以看到,当遍历,发现当前用户拥有定义的其中一个角色就立刻返回true,否则返回false。

定义好filter,只需要代码默认的roles即可。

  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.         <property name="securityManager" ref="securityManager" />  
  3.         <property name="loginUrl" value="/security/login.html" />  
  4.         <property name="successUrl" value="/home.html" />  
  5.         <property name="unauthorizedUrl" value="/security/unauthorized.html" />  
  6.         <property name="filters">  
  7.             <map>  
  8.                 <entry key="anyRoles" value-ref="anyRolesAuthorizationFilter" />  
  9.             </map>  
  10.         </property>  
  11.         <property name="filterChainDefinitions">  
  12.             <value>  
  13.                                 /admin = anyRoles[admin1,admin2]  
  14.                 /** = anon  
  15.             </value>  
  16.         </property>  
  17.     </bean>  
perms的filter也同理。看看源码:

  1. public class PermissionsAuthorizationFilter extends AuthorizationFilter {  
  2.   
  3.     //TODO - complete JavaDoc  
  4.   
  5.     public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {  
  6.   
  7.         Subject subject = getSubject(request, response);  
  8.         String[] perms = (String[]) mappedValue;  
  9.   
  10.         boolean isPermitted = true;  
  11.         if (perms != null && perms.length > 0) {  
  12.             if (perms.length == 1) {  
  13.                 if (!subject.isPermitted(perms[0])) {  
  14.                     isPermitted = false;  
  15.                 }  
  16.             } else {  
  17.                 if (!subject.isPermittedAll(perms)) {  
  18.                     isPermitted = false;  
  19.                 }  
  20.             }  
  21.         }  
  22.   
  23.         return isPermitted;  
  24.     }  
  25. }  

自定义的filter:

  1. public class AnyPermissionsAuthorizationFilter extends AuthorizationFilter {  
  2.   
  3.     @Override  
  4.     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {  
  5.         Subject subject = getSubject(request, response);  
  6.         String[] perms = (String[]) mappedValue;  
  7.   
  8.         for (String perm : perms) {  
  9.             if (subject.isPermitted(perm)) {  
  10.                 return true;  
  11.             }  
  12.         }  
  13.           
  14.         return false;  
  15.     }  
  16.   
  17. }  

配置使用自定义filter

  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.         <property name="securityManager" ref="securityManager" />  
  3.         <property name="loginUrl" value="/security/login.html" />  
  4.         <property name="successUrl" value="/home.html" />  
  5.         <property name="unauthorizedUrl" value="/security/unauthorized.html" />  
  6.         <property name="filters">  
  7.             <map>  
  8.                 <entry key="anyPerms" value-ref="anyPermissionsAuthorizationFilter" />  
  9.             </map>  
  10.         </property>  
  11.           
  12.             <value>  
  13.                 /admin/add = anyPerms["admin:delete","admin:add"]  
  14.                 /** = anon  
  15.             </value>  
  16.         </property>  
  17.     </bean>  

当用户请求/admin/add时,就会调用自定义的AnyPermissionsAuthorizationFilter来执行。

shiro的filter大概讲到这里,相信读者对shiro的filter有更深的认识。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多