关于Shiro的介绍网上有太多,就不赘述了,写这篇文章的目的就是记录一下使用配置的要点。

1. Web.xml配置,Shiro的filter必须放在其他filter之前



1. <filter>  
2. <filter-name>shiroFilter</filter-name>  
3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
4. <init-param>  
5. <param-name>targetFilterLifecycle</param-name>  
6. <param-value>true</param-value>  
7. </init-param>  
8. </filter>  
9. <filter-mapping>  
10. <filter-name>shiroFilter</filter-name>  
11. <url-pattern>/*</url-pattern>  
12. </filter-mapping>


2. Spring Context配置,都是官网摘来的,就不详述了。有以下问题需要注意:

     1) Shiro提供的realm没有需要的,所以自己写了个

     2) successUrl和unauthorizedUrl调试时曾经没有起作用,后来莫名其妙好了,原因不明,可能是开始代码或配置有问题,比如:为了测试权限注解,在login Action里调用了一个加上了@RequiresPermissions("account:create")的private method,不深究了。



1. <!-- shiro security -->  
2. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
3. <property name="securityManager" ref="securityManager"/>  
4. <property name="loginUrl" value="/login"/>  
5. <property name="successUrl" value="/welcome"/>  
6. <property name="unauthorizedUrl" value="/refuse"/>  
7. <property name="filterChainDefinitions">  
8. <value>  
9. refuse = anon  
10. <!-- /welcome = perms[accout:edit] -->  
11.     /** = authc  
12. </value>  
13. </property>  
14. </bean>  
15.   
16. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
17. <property name="realm" ref="customRealm"/>  
18. </bean>  
19. <bean id="customRealm" class="com.capgemini.framework.common.access.CustomShiraRealm" />  
20.   
21. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />


3. 为了支持Shiro的注释,按官方文档的介绍,在applicationContext.xml加两个bean定义:DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor。

可是测试下来却不起作用,搜了半天,终于找到原因,原来用了spring mvc的话就需要把这两个bean定义写在相应的springmvc-servlet.xml文件中,并加上SimpleMappingExceptionResolver




    1. <!-- Support Shiro Annotation -->  
    2. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">    
    3. <property name="exceptionMappings">    
    4. <props>    
    5. <prop key="org.apache.shiro.authz.UnauthorizedException">shiro-test/refuse</prop>  
    6. </props>    
    7. </property>    
    8. </bean>    
    9. <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"   
    10. depends-on="lifecycleBeanPostProcessor"/>      
    11. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
    12. <property name="securityManager" ref="securityManager"/>  
    13. </bean>


    4. 自定义的realm必须继承AuthorizingRealm,并实现两个Abstract方法doGetAuthorizationInfo和doGetAuthenticationInfo



    1. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
    2.     String username = (String) principals.fromRealm(getName()).iterator().next();  
    3. if (username != null) {  
    4. try {  
    5.             User user = userMgntService.getUserByUserCode(username);  
    6. if (user != null && user.getRole() != null) {  
    7. new SimpleAuthorizationInfo();  
    8.                 info.addRole(user.getRole().getRoleName());  
    9. "account:view");  
    10. return info;  
    11.             }  
    12. catch (AppException e) {  
    13.             logger.error(e, e);  
    14.         }  
    15.     }  
    16. return null;  
    17.   
    18. }





    1. protected AuthenticationInfo doGetAuthenticationInfo(  
    2. throws AuthenticationException {  
    3.     UsernamePasswordToken token = (UsernamePasswordToken) authcToken;  
    4.     String userName = token.getUsername();  
    5. if (userName != null && !"".equals(userName.trim())) {  
    6. try {  
    7.             User user = userMgntService.getUserByUserCode(token.getUsername());  
    8. if (user != null && user.getPassword().equals(String.valueOf(token.getPassword())))  
    9. return new SimpleAuthenticationInfo(user.getUserCode(),   
    10.                                                 user.getPassword(), getName());  
    11. catch (AppException e) {  
    12.             logger.error(e, e);  
    13.         }  
    14.     }  
    15. return null;  
    16. }


    FormAuthenticationFilter会找这三个requestparameters:username,password andrememberMe,如果非要用不一样的名字,那么就设置FormAuthenticationFilter的这几个参数




    1. <form action="${pageContext.request.contextPath}/login" method="post">  
    2.   
    3. <input type="text" name="username"/> <br/>  
    4. <input type="password" name="password"/>  
    5.    ...  
    6. <input type="checkbox" name="rememberMe" value="true"/>Remember Me?   
    7.    ...  
    8. </form>



    1. [main]  
    2. ...  
    3. authc.loginUrl = /whatever.jsp  
    4. authc.usernameParam = somethingOtherThanUsername  
    5. authc.passwordParam = somethingOtherThanPassword  
    6. authc.rememberMeParam = somethingOtherThanRememberMe  
    7. ...




    1. @RequestMapping(value = "/login")  
    2. public String login(String username, String password) {  
    3. return "shiro-test/login";  
    4. }