安全框架Apache Shiro学习心得

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

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

[html]  view plain copy
  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,不深究了。

[html]  view plain copy
  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

[html]  view plain copy
  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

[java]  view plain copy
  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.                 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
  8.                 info.addRole(user.getRole().getRoleName());  
  9.                 info.addStringPermission("account:view");  
  10.                 return info;  
  11.             }  
  12.         } catch (AppException e) {  
  13.             logger.error(e, e);  
  14.         }  
  15.     }  
  16.     return null;  
  17.   
  18. }  
[java]  view plain copy
  1. protected AuthenticationInfo doGetAuthenticationInfo(  
  2.         AuthenticationToken authcToken ) 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. }  

5. 如果jsp的login form按照官方文档的写法,表单元素的名字都和文档一样的话,那么login Action基本不需要做太多操作,只需要完成验证失败的跳转。验证成功的话不会回到/login,而是从realm一直往下走跳到successUrl,默认的FormAuthenticationFilter会找这三个requestparameters:username,password andrememberMe,如果非要用不一样的名字,那么就设置FormAuthenticationFilter的这几个参数

[html]  view plain copy
  1. <form action="${pageContext.request.contextPath}/login" method="post">  
  2.   
  3.    Username: <input type="text" name="username"/> <br/>  
  4.    Password: <input type="password" name="password"/>  
  5.    ...  
  6.    <input type="checkbox" name="rememberMe" value="true"/>Remember Me?   
  7.    ...  
  8. </form>  
[html]  view plain copy
  1. [main]  
  2. ...  
  3. authc.loginUrl = /whatever.jsp  
  4. authc.usernameParam = somethingOtherThanUsername  
  5. authc.passwordParam = somethingOtherThanPassword  
  6. authc.rememberMeParam = somethingOtherThanRememberMe  
  7. ...  

[java]  view plain copy
  1. @RequestMapping(value = "/login")  
  2. public String login(String username, String password) {  
  3.     return "shiro-test/login";  
  4. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值