zoukankan      html  css  js  c++  java
  • Spring Security教程 ---- 验证码功能的实现

    有三中方法可以实现验证码的功能

    第一种是自定义一个filter,放在SpringSecurity过滤器之前,在用户登录的时候会先经过这个filter,然后在这个filter中实现对验证码进行验证的功能,这种方法不推荐,因为它已经脱离了SpringSecurity

    第二种是自定义一个filter让它继承自UsernamePasswordAuthenticationFilter,然后重写attemptAuthentication方法在这个方法中实现验证码的功能,如果验证码错误就抛出一个继承自AuthenticationException的验证吗错误的异常比如(CaptchaException),然后这个异常就会被SpringSecurity捕获到并将异常信息返回到前台,这种实现起来比较简单

    [java] 
    1. @Override  
    2. public Authentication attemptAuthentication(HttpServletRequest request,  
    3.         HttpServletResponse response) throws AuthenticationException {  
    4.       
    5.     String requestCaptcha = request.getParameter(this.getCaptchaFieldName());  
    6.     String genCaptcha = (String)request.getSession().getAttribute("code");  
    7.       
    8.     logger.info("开始校验验证码,生成的验证码为:"+genCaptcha+" ,输入的验证码为:"+requestCaptcha);  
    9.       
    10.     if( !genCaptcha.equals(requestCaptcha)){  
    11.         throw new CaptchaException(  
    12.                 this.messageSource.getMessage("AbstractUserDetailsAuthenticationProvider.badCaptcha",null,"Default",null));  
    13.     }  
    14.     return super.attemptAuthentication(request, response);  
    15. }  

    然后在配置文件中配置下

    [html] 
    1. <bean id="loginFilter" class="com.zrhis.system.security.DefaultUsernamePasswordAuthenticationFilter">  
    2.     <property name="authenticationManager"  ref="authenticationManager"></property>  
    3.     <property name="authenticationSuccessHandler">  
    4.         <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">  
    5.             <property name="defaultTargetUrl" value="/index.jsp"></property>  
    6.         </bean>  
    7.     </property>  
    8.     <property name="authenticationFailureHandler">  
    9.         <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">  
    10.             <property name="defaultFailureUrl" value="/login.jsp"></property>  
    11.         </bean>  
    12.     </property>  
    13. </bean>  

    最后在http中加入custom-filter配置,将这个filter放在SpringSecurity的FORM_LOGIN_FILTER之前

     
    1. <custom-filter ref="loginFilter" before="FORM_LOGIN_FILTER"/>  

    最后一种是直接替换掉SpringSecurity的UsernamePasswordAuthenticationFilter,这种比较复杂,但是更为合理,也是我现在正在用的。

    如果用这种方法那么http 中的auto-config就必须去掉,而form-login配置也必须去掉,因为这个不需要了,里面的属性都需要我们自行注入。

    首先需要创建一个EntryPoint

    [html] 
    1. <bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">  
    2.     <property name="loginFormUrl" value="/login.jsp" />  
    3. </bean>  

    然后在http中配置下

    [html] 
    1. <sec:http access-decision-manager-ref="accessDecisionManager"  
    2.         entry-point-ref="authenticationEntryPoint">  

    然后我们来写CaptchaAuthenticationFilter,同样需要继承自UsernamePasswordAuthenticationFilter

    [java]
    1. public class CaptchaAuthenticationFilter extends UsernamePasswordAuthenticationFilter{  
    2.       
    3.     public static final String SPRING_SECURITY_FORM_CAPTCHA_KEY = "j_captcha";  
    4.     public static final String SESSION_GENERATED_CAPTCHA_KEY = Constant.SESSION_GENERATED_CAPTCHA_KEY;  
    5.       
    6.     private String captchaParameter = SPRING_SECURITY_FORM_CAPTCHA_KEY;  
    7.       
    8.     public Authentication attemptAuthentication(HttpServletRequest request,  
    9.             HttpServletResponse response) throws AuthenticationException {  
    10.           
    11.         String genCode = this.obtainGeneratedCaptcha(request);  
    12.         String inputCode = this.obtainCaptcha(request);  
    13.         if(genCode == null)  
    14.             throw new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaInvalid"));  
    15.         if(!genCode.equalsIgnoreCase(inputCode)){  
    16.             throw new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaNotEquals"));  
    17.         }  
    18.           
    19.         return super.attemptAuthentication(request, response);  
    20.     }  
    21.       
    22.     protected String obtainCaptcha(HttpServletRequest request){  
    23.         return request.getParameter(this.captchaParameter);  
    24.     }  
    25.       
    26.     protected String obtainGeneratedCaptcha (HttpServletRequest request){  
    27.         return (String)request.getSession().getAttribute(SESSION_GENERATED_CAPTCHA_KEY);  
    28.     }  
    29.       
    30. }  

    在配置文件中配置CaptchaAuthenticationFilter

    [html] 
    1. <bean id="captchaAuthenticaionFilter" class="com.zrhis.system.security.CaptchaAuthenticationFilter">  
    2.     <property name="authenticationManager" ref="authenticationManager" />  
    3.     <property name="authenticationFailureHandler" ref="authenticationFailureHandler" />  
    4.     <property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />  
    5.     <property name="filterProcessesUrl" value="/login.do" />  
    6. </bean>  
    7.   
    8. <bean id="authenticationSuccessHandler" class="com.zrhis.system.security.SimpleLoginSuccessHandler">  
    9.     <property name="defaultTargetUrl" value="/WEB-INF/app.jsp"></property>  
    10.     <property name="forwardToDestination" value="true"></property>  
    11. </bean>  
    12. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">  
    13.     <property name="defaultFailureUrl" value="/login.jsp" />  
    14. </bean>  

    从配置文件中就可以看出来authenticationManager、authenticationFailureHandler、authenticationSuccessHandler、filterProcessesUrl等都需要我们自行注入了。

    filterProcessesUrl定义的是登录验证的地址,默认的是j_spring_security_check这里我们改成login.do

    authenticationSuccessHandler中的defaultTargetUrl定义的是登录成功后跳转到的页面

    authenticationFailureHandler中的defaultTargetUrl定义的是登录失败后跳转到的页面

    我们的首页app.jsp在/WEB-INF下所以需要使用服务器跳转,所以需要将forwardToDestination设为true,因为客户端跳转是不能直接访问WEB-INF下的内容的。

    最后在http中将FORM_LOGIN_FILTER替换掉,最终http中完整的配置就变成了下面的内容

    [html]
    1. <sec:http access-decision-manager-ref="accessDecisionManager"  
    2.     entry-point-ref="authenticationEntryPoint">  
    3.       
    4.     <sec:access-denied-handler ref="accessDeniedHandler"/>  
    5.       
    6.     <sec:session-management invalid-session-url="/login.jsp" />  
    7.       
    8.     <sec:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>  
    9.     <sec:custom-filter ref="captchaAuthenticaionFilter" position="FORM_LOGIN_FILTER"/>  
    10. </sec:http>  

    custom-filter中before是在这个filter之前,after是之后,position是替换。

    这样就可以实现对验证码的验证了,效果如下

  • 相关阅读:
    HLG 1522 子序列的和【队列的应用】
    POJ 3273 Monthly Expense【二分】
    HDU 4004 The Frog's Games 【二分】
    POJ 2001 Shortest Prefixes【第一棵字典树】
    POJ 2823 Sliding Window【单调对列经典题目】
    HDU 1969 Pie 【二分】
    POJ 3125 Printer Queue【暴力模拟】
    POJ 3250 Bad Hair Day【单调栈】
    字典树【模板】
    验证码 Code
  • 原文地址:https://www.cnblogs.com/like-minded/p/5237296.html
Copyright © 2011-2022 走看看