spring security3 扩展验证码

security的登录参数验证主要是经过UsernamePasswordAuthenticationFilter过滤器

所以我们自己写个新的实现类类继承UsernamePasswordAuthenticationFilter,验证码工具我是使用jcaptcha,相信大家对这个也不会感觉陌生吧,至于网上也有很多这样的例子来演示如何扩展了

先来写个实现类继承UsernamePasswordAuthenticationFilter

[java] view plain copy
  1. /** 
  2.  * 重载SECURITY3的UsernamePasswordAuthenticationFilter的attemptAuthentication, 
  3.  * obtainUsername,obtainPassword方法(完善逻辑) 增加验证码校验模块 添加验证码属性 添加验证码功能开关属性 
  4.  *  
  5.  * @author shadow 
  6.  * @email [email protected] 
  7.  * @create 2012.04.28 
  8.  */  
  9. public class UsernamePasswordAuthenticationExtendFilter extends  
  10.         UsernamePasswordAuthenticationFilter {  
  11.   
  12.     // 验证码字段  
  13.     private String validateCodeParameter = "validateCode";  
  14.     // 是否开启验证码功能  
  15.     private boolean openValidateCode = false;  
  16.   
  17.     @Override  
  18.     public Authentication attemptAuthentication(HttpServletRequest request,  
  19.             HttpServletResponse response) throws AuthenticationException {  
  20.         // 只接受POST方式传递的数据  
  21.         if (!"POST".equals(request.getMethod()))  
  22.             throw new MethodErrorException("不支持非POST方式的请求!");  
  23.   
  24.         // 开启验证码功能的情况  
  25.         if (isOpenValidateCode())  
  26.             checkValidateCode(request);  
  27.   
  28.         // 获取Username和Password  
  29.         String username = obtainUsername(request);  
  30.         String password = obtainPassword(request);  
  31.   
  32.         // UsernamePasswordAuthenticationToken实现Authentication校验  
  33.         UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(  
  34.                 username, password);  
  35.   
  36.         // 允许子类设置详细属性  
  37.         setDetails(request, authRequest);  
  38.   
  39.         // 运行UserDetailsService的loadUserByUsername 再次封装Authentication  
  40.         return this.getAuthenticationManager().authenticate(authRequest);  
  41.     }  
  42.   
  43.     // 匹对验证码的正确性  
  44.     public void checkValidateCode(HttpServletRequest request) {  
  45.   
  46.         String jcaptchaCode = obtainValidateCodeParameter(request);  
  47.         if (null == jcaptchaCode)  
  48.             throw new ValidateCodeException("验证码超时,请重新获取!");  
  49.   
  50.         boolean b = CaptchaServiceSingleton.getInstance()  
  51.                 .validateResponseForID(request.getSession().getId(),  
  52.                         jcaptchaCode);  
  53.         if (!b)  
  54.             throw new ValidateCodeException("验证码不正确,请重新输入!");  
  55.     }  
  56.   
  57.     public String obtainValidateCodeParameter(HttpServletRequest request) {  
  58.         Object obj = request.getParameter(getValidateCodeParameter());  
  59.         return null == obj ? "" : obj.toString().trim();  
  60.     }  
  61.   
  62.     @Override  
  63.     protected String obtainUsername(HttpServletRequest request) {  
  64.         Object obj = request.getParameter(getUsernameParameter());  
  65.         return null == obj ? "" : obj.toString().trim();  
  66.     }  
  67.   
  68.     @Override  
  69.     protected String obtainPassword(HttpServletRequest request) {  
  70.         Object obj = request.getParameter(getPasswordParameter());  
  71.         return null == obj ? "" : obj.toString().trim();  
  72.     }  
  73.   
  74.     public String getValidateCodeParameter() {  
  75.         return validateCodeParameter;  
  76.     }  
  77.   
  78.     public void setValidateCodeParameter(String validateCodeParameter) {  
  79.         this.validateCodeParameter = validateCodeParameter;  
  80.     }  
  81.   
  82.     public boolean isOpenValidateCode() {  
  83.         return openValidateCode;  
  84.     }  
  85.   
  86.     public void setOpenValidateCode(boolean openValidateCode) {  
  87.         this.openValidateCode = openValidateCode;  
  88.     }  
  89.   
  90. }  


很明显我们在获取username跟password之前执行一个checkValidateCode()的方法,这里就是先比较验证码,如果失败就直接抛出ValidateCodeException,这个异常自己定义个,

只要继承AuthenticationException就可以了

校验成功就直接往下执行比较username,password,然后配置xml的时候class的指向就用自己新的filter,过滤链中使用新 的filter替换掉UsernamePasswordAuthenticationFilter实现类的位置,下面是我自己的xml配置

过滤链里的serverCustomUsernamePasswordAuthenticationFilter实现换成是我们自己刚写的实现类,至于com.shadow.security.handler.LoginSuccessHandler和

com.shadow.security.handler.LoginFailureHandler这里自己实现一个AuthenticationSuccessHandler接口里面逻辑根据项目需求来设计

[java] view plain copy
  1. <!-- 登录认证过滤器-->  
  2.     <bean id="usernamePasswordAuthenticationFilter"  
  3.         class="com.shadow.security.service.UsernamePasswordAuthenticationExtendFilter">  
  4.         <property name="authenticationManager"  
  5.             ref="authenticationManager" />  
  6.         <property name="sessionAuthenticationStrategy"  
  7.             ref="concurrentSessionControlStrategy" />  
  8.         <property name="usernameParameter" value="username" />  
  9.         <property name="passwordParameter" value="password" />  
  10.         <property name="validateCodeParameter" value="validateCode" />  
  11.         <property name="openValidateCode" value="true" />  
  12.         <property name="filterProcessesUrl" value="/login" />  
  13.         <property name="rememberMeServices" ref="rememberMeServices" />  
  14.         <property name="authenticationSuccessHandler">  
  15.             <bean  
  16.                 class="com.shadow.security.handler.LoginSuccessHandler">  
  17.                 <property name="indexUrl" value="/index.jsp" />  
  18.             </bean>  
  19.         </property>  
  20.         <property name="authenticationFailureHandler">  
  21.             <bean  
  22.                 class="com.shadow.security.handler.LoginFailureHandler" />  
  23.         </property>  
  24.     </bean>  


至于其他的依赖属性注入就自己根据项目来添加吧,这里就不详细说明了

猜你喜欢

转载自zhang1206.iteye.com/blog/1976589