我的shiro之旅:自定义filter

1. shiro的filter介绍

Filter Name Class
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter


       
       
       
       
       
       
       
           
                /admin = authc,roles[admin]
                /edit = authc,perms[admin:edit]
                /home = user
                /** = anon
           

       

   

loginUrl: 当用户没有登录的时候,会重发一个login请求,引导用户去登录
successUrl:是当用户登录成功,转发home请求
unauthorizedUrl指如果请求失败,重发/unauthorized请求,引导用户到认证异常错误页面

如我们在filterChainDefinitions里配置了/admin=authc,roles[admin],那么/admin这个请求会由org.apache.shiro.web.filter.authc.FormAuthenticationFilterorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter这两个filter来处理,其中authc,roles只是filter的别名。如要更改别名,可以通过filters来改变。如上面的配置 
 
           
               
                   
               
           
       
把PassThruAuthenticationFilter添加别名为authc,这时/admin请求会交给PassThruAuthenticationFilter处理,替换了原来由FormAuthenticationFilter来处理。

由此一来,如果有些特殊的请求需要特殊处理,就可以自己写一个filter,添加一个别名,如:

           
               
                   
               
           
       


2. shiro自定义filter

使用shiro的时候,比较常用的filter有anon,authc,roles和perms。当我们想定义某个链接是拥有某些权限的用户才可以访问的时候,我们可以这样定义。/xx = roles[A,B]。在shiro中,表示当前用户同时拥有A,B两种角色才可以访问/xx这个链接,是一种&&(与)的关系

RolesAuthorizationFilter这样一个类,这个类就是定义roles的filter。

01 public class RolesAuthorizationFilter extends AuthorizationFilter {
02  
03     //TODO - complete JavaDoc
04  
05     @SuppressWarnings({"unchecked"})
06     public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
07  
08         Subject subject = getSubject(request, response);
09         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 roles = CollectionUtils.asSet(rolesArray);
17         return subject.hasAllRoles(roles);
18     }
19  
20 }

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

01 public class AnyRolesAuthorizationFilter extends AuthorizationFilter {
02  
03      
04     @Override
05     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
06  
07         Subject subject = getSubject(request, response);
08         String[] rolesArray = (String[]) mappedValue;
09  
10         if (rolesArray == null || rolesArray.length == 0) {
11             // no roles specified, so nothing to check - allow access.
12             return true;
13         }
14  
15         Set 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即可。

01 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
02         <property name="securityManager" ref="securityManager" />
03         <property name="loginUrl" value="/security/login.html" />
04         <property name="successUrl" value="/home.html" />
05         <property name="unauthorizedUrl" value="/security/unauthorized.html" />
06         <property name="filters">
07             <map>
08                 <entry key="anyRoles" value-ref="anyRolesAuthorizationFilter" />
09             map>
10         property>
11         <property name="filterChainDefinitions">
12             <value>
13                                 /admin = anyRoles[admin1,admin2]
14                 /** = anon
15             value>
16         property>
17     bean>
perms的filter也同理。看看源码:

01 public class PermissionsAuthorizationFilter extends AuthorizationFilter {
02  
03     //TODO - complete JavaDoc
04  
05     public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
06  
07         Subject subject = getSubject(request, response);
08         String[] perms = (String[]) mappedValue;
09  
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:

01 public class AnyPermissionsAuthorizationFilter extends AuthorizationFilter {
02  
03     @Override
04     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
05         Subject subject = getSubject(request, response);
06         String[] perms = (String[]) mappedValue;
07  
08         for (String perm : perms) {
09             if (subject.isPermitted(perm)) {
10                 return true;
11             }
12         }
13          
14         return false;
15     }
16  
17 }

配置使用自定义filter

01 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
02         <property name="securityManager" ref="securityManager" />
03         <property name="loginUrl" value="/security/login.html" />
04         <property name="successUrl" value="/home.html" />
05         <property name="unauthorizedUrl" value="/security/unauthorized.html" />
06         <property name="filters">
07             <map>
08                 <entry key="anyPerms" value-ref="anyPermissionsAuthorizationFilter"/>
09             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)