springsecurity3和JCaptcha的整合

JCaptcha是一个验证码的框架.
照着白衣的springside3的例子鼓捣了半天,弄出来感觉不复杂但是很有用.
不多说,放货.

创建一个jcaptcha包
在jcaptcha包里创建2个类:GMailEngine 和 JCaptchaFilter
GMailEngine :是JCaptcha验证码图片生成引擎,仿照JCaptcha2.0编写类似GMail验证码的样式.
JCaptchaFilter:是针对 JCaptcha 专门的过滤器(Filter).

另外 remember-me 这个功能我测试用 把系统时间更改下,确实是可以实现在两周之类免登录.


包结构
springsecurity3和JCaptcha的整合_第1张图片


GMailEngine.java
Java代码 复制代码  收藏代码
  1. package com.sjax.myapp.jcaptcha;   
  2.   
  3. import java.awt.Color;   
  4. import java.awt.Font;   
  5. import java.awt.image.ImageFilter;   
  6.   
  7. import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;   
  8. import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;   
  9. import com.octo.captcha.component.image.color.RandomListColorGenerator;   
  10. import com.octo.captcha.component.image.deformation.ImageDeformation;   
  11. import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;   
  12. import com.octo.captcha.component.image.fontgenerator.FontGenerator;   
  13. import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;   
  14. import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;   
  15. import com.octo.captcha.component.image.textpaster.TextPaster;   
  16. import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;   
  17. import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;   
  18. import com.octo.captcha.component.image.wordtoimage.WordToImage;   
  19. import com.octo.captcha.component.word.FileDictionary;   
  20. import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;   
  21. import com.octo.captcha.component.word.wordgenerator.WordGenerator;   
  22. import com.octo.captcha.engine.image.ListImageCaptchaEngine;   
  23. import com.octo.captcha.image.gimpy.GimpyFactory;   
  24.   
  25. /**  
  26.  * JCaptcha验证码图片生成引擎,仿照JCaptcha2.0编写类似GMail验证码的样式.  
  27.  *   
  28.  * @author liukai  
  29.  *   
  30.  */  
  31. public class GMailEngine extends ListImageCaptchaEngine {   
  32.   
  33.     @Override  
  34.     protected void buildInitialFactories() {   
  35.         int minWordLength = 4;   
  36.         int maxWordLength = 5;   
  37.         int fontSize = 50;   
  38.         int imageWidth = 250;   
  39.         int imageHeight = 100;   
  40.         WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(   
  41.                 new FileDictionary("toddlist"));   
  42.   
  43.         // word2image components   
  44.         TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength,   
  45.                 maxWordLength, new RandomListColorGenerator(new Color[] {   
  46.                         new Color(2317027), new Color(2203411),   
  47.                         new Color(2367172) }), new TextDecorator[] {});   
  48.         BackgroundGenerator background = new UniColorBackgroundGenerator(   
  49.                 imageWidth, imageHeight, Color.white);   
  50.         FontGenerator font = new RandomFontGenerator(fontSize, fontSize,   
  51.                 new Font[] { new Font("nyala", Font.BOLD, fontSize),   
  52.                         new Font("Bell MT", Font.PLAIN, fontSize),   
  53.                         new Font("Credit valley", Font.BOLD, fontSize) });   
  54.         ImageDeformation postDef = new ImageDeformationByFilters(   
  55.                 new ImageFilter[] {});   
  56.         ImageDeformation backDef = new ImageDeformationByFilters(   
  57.                 new ImageFilter[] {});   
  58.         ImageDeformation textDef = new ImageDeformationByFilters(   
  59.                 new ImageFilter[] {});   
  60.   
  61.         WordToImage word2image = new DeformedComposedWordToImage(font,   
  62.                 background, randomPaster, backDef, textDef, postDef);   
  63.         addFactory(new GimpyFactory(dictionnaryWords, word2image));   
  64.     }   
  65.   
  66. }  


JCaptchaFilter.java
Java代码 复制代码  收藏代码
  1. package com.sjax.myapp.jcaptcha;   
  2.   
  3. import java.awt.image.BufferedImage;   
  4. import java.io.IOException;   
  5.   
  6. import javax.imageio.ImageIO;   
  7. import javax.servlet.Filter;   
  8. import javax.servlet.FilterChain;   
  9. import javax.servlet.FilterConfig;   
  10. import javax.servlet.ServletException;   
  11. import javax.servlet.ServletOutputStream;   
  12. import javax.servlet.ServletRequest;   
  13. import javax.servlet.ServletResponse;   
  14. import javax.servlet.http.HttpServletRequest;   
  15. import javax.servlet.http.HttpServletResponse;   
  16.   
  17. import org.apache.commons.lang.StringUtils;   
  18. import org.slf4j.Logger;   
  19. import org.slf4j.LoggerFactory;   
  20. import org.springframework.context.ApplicationContext;   
  21. import org.springframework.web.context.support.WebApplicationContextUtils;   
  22.   
  23. import com.octo.captcha.service.CaptchaService;   
  24. import com.octo.captcha.service.CaptchaServiceException;   
  25.   
  26. /**  
  27.  * 针对 JCaptcha 专门的过滤器(Filter)  
  28.  * @author liukai  
  29.  *  
  30.  */  
  31. public class JCaptchaFilter implements Filter {   
  32.   
  33.     //web.xml中的参数名定义   
  34.     public static final String PARAM_CAPTCHA_PARAMTER_NAME = "captchaParamterName";   
  35.     public static final String PARAM_CAPTCHA_SERVICE_ID = "captchaServiceId";   
  36.     public static final String PARAM_FILTER_PROCESSES_URL = "filterProcessesUrl";   
  37.     public static final String PARAM_FAILURE_URL = "failureUrl";   
  38.     public static final String PARAM_AUTO_PASS_VALUE = "autoPassValue";   
  39.   
  40.     //默认值定义   
  41.     public static final String DEFAULT_FILTER_PROCESSES_URL = "/j_spring_security_check";   
  42.     public static final String DEFAULT_CAPTCHA_SERVICE_ID = "captchaService";   
  43.     public static final String DEFAULT_CAPTCHA_PARAMTER_NAME = "j_captcha";   
  44.        
  45.     private static Logger logger = LoggerFactory.getLogger(JCaptchaFilter.class);   
  46.        
  47.     private String failureUrl;   
  48.     private String filterProcessesUrl = DEFAULT_FILTER_PROCESSES_URL;   
  49.     private String captchaServiceId = DEFAULT_CAPTCHA_SERVICE_ID;   
  50.     private String captchaParamterName = DEFAULT_CAPTCHA_PARAMTER_NAME;   
  51.     private String autoPassValue;   
  52.   
  53.     private CaptchaService captchaService;   
  54.        
  55.     /**  
  56.      * Filter回调初始化函数.  
  57.      */  
  58.     public void init(FilterConfig filterConfig) throws ServletException {   
  59.         // TODO Auto-generated method stub   
  60.         initParameters(filterConfig);   
  61.         initCaptchaService(filterConfig);   
  62.   
  63.     }   
  64.   
  65.     public void doFilter(ServletRequest theRequest, ServletResponse theResponse,   
  66.             FilterChain chain) throws IOException, ServletException {   
  67.         HttpServletRequest request = (HttpServletRequest) theRequest;   
  68.         HttpServletResponse response = (HttpServletResponse) theResponse;   
  69.         String servletPath = request.getServletPath();   
  70.         logger.info("servletPath:"+servletPath);   
  71.         //符合filterProcessesUrl为验证处理请求,其余为生成验证图片请求.   
  72.         if (StringUtils.startsWith(servletPath, filterProcessesUrl)) {   
  73.             boolean validated = validateCaptchaChallenge(request);   
  74.             if (validated) {   
  75.                 chain.doFilter(request, response);   
  76.             } else {   
  77.                 redirectFailureUrl(request, response);   
  78.             }   
  79.         } else {   
  80.             genernateCaptchaImage(request, response);   
  81.         }   
  82.     }   
  83.   
  84.     /**  
  85.      * Filter回调退出函数.  
  86.      */  
  87.     public void destroy() {   
  88.         // TODO Auto-generated method stub   
  89.   
  90.     }   
  91.        
  92.     /**  
  93.      * 初始化web.xml中定义的filter init-param.  
  94.      */  
  95.     protected void initParameters(final FilterConfig fConfig) {   
  96.         if (StringUtils.isBlank(fConfig.getInitParameter(PARAM_FAILURE_URL))) {   
  97.             throw new IllegalArgumentException("CaptchaFilter缺少failureUrl参数");   
  98.         }   
  99.   
  100.         failureUrl = fConfig.getInitParameter(PARAM_FAILURE_URL);   
  101.         logger.info("failureUrl:"+failureUrl);   
  102.   
  103.         if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_FILTER_PROCESSES_URL))) {   
  104.             filterProcessesUrl = fConfig.getInitParameter(PARAM_FILTER_PROCESSES_URL);   
  105.         }   
  106.   
  107.         if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_CAPTCHA_SERVICE_ID))) {   
  108.             captchaServiceId = fConfig.getInitParameter(PARAM_CAPTCHA_SERVICE_ID);   
  109.         }   
  110.   
  111.         if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_CAPTCHA_PARAMTER_NAME))) {   
  112.             captchaParamterName = fConfig.getInitParameter(PARAM_CAPTCHA_PARAMTER_NAME);   
  113.         }   
  114.   
  115.         if (StringUtils.isNotBlank(fConfig.getInitParameter(PARAM_AUTO_PASS_VALUE))) {   
  116.             autoPassValue = fConfig.getInitParameter(PARAM_AUTO_PASS_VALUE);   
  117.         }   
  118.     }   
  119.        
  120.     /**  
  121.      * 从ApplicatonContext获取CaptchaService实例.  
  122.      */  
  123.     protected void initCaptchaService(final FilterConfig fConfig) {   
  124.         ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(fConfig.getServletContext());   
  125.         captchaService = (CaptchaService) context.getBean(captchaServiceId);   
  126.     }   
  127.        
  128.     /**  
  129.      * 生成验证码图片.  
  130.      */  
  131.     protected void genernateCaptchaImage(final HttpServletRequest request, final HttpServletResponse response)   
  132.             throws IOException {   
  133.   
  134.         setDisableCacheHeader(response);   
  135.         response.setContentType("image/jpeg");   
  136.   
  137.         ServletOutputStream out = response.getOutputStream();   
  138.         try {   
  139.             String captchaId = request.getSession(true).getId();   
  140.             BufferedImage challenge = (BufferedImage) captchaService.getChallengeForID(captchaId, request.getLocale());   
  141.             ImageIO.write(challenge, "jpg", out);   
  142.             out.flush();   
  143.         } catch (CaptchaServiceException e) {   
  144.             logger.error(e.getMessage(), e);   
  145.         } finally {   
  146.             out.close();   
  147.         }   
  148.     }   
  149.        
  150.     /**  
  151.      * 验证验证码.  
  152.      */  
  153.     protected boolean validateCaptchaChallenge(final HttpServletRequest request) {   
  154.         try {   
  155.             String captchaID = request.getSession().getId();   
  156.             logger.info("captchaID:"+captchaID);   
  157.             String challengeResponse = request.getParameter(captchaParamterName);   
  158.             logger.info("challengeResponse:"+challengeResponse);   
  159.             //自动通过值存在时,检验输入值是否等于自动通过值   
  160.             if (StringUtils.isNotBlank(autoPassValue) && autoPassValue.equals(challengeResponse)) {   
  161.                 return true;   
  162.             }   
  163.             return captchaService.validateResponseForID(captchaID, challengeResponse);   
  164.         } catch (CaptchaServiceException e) {   
  165.             logger.error(e.getMessage(), e);   
  166.             return false;   
  167.         }   
  168.     }   
  169.     /**  
  170.      * 跳转到失败页面.  
  171.      *   
  172.      * 可在子类进行扩展, 比如在session中放入SpringSecurity的Exception.  
  173.      */  
  174.     protected void redirectFailureUrl(final HttpServletRequest request, final HttpServletResponse response)   
  175.             throws IOException {   
  176.         logger.info("跳转到失败页面:"+request.getContextPath()+failureUrl);   
  177.         response.sendRedirect(request.getContextPath() + failureUrl);   
  178.     }   
  179.        
  180.     /**  
  181.      * 设置禁止客户端缓存的Header.  
  182.      */  
  183.     public static void setDisableCacheHeader(HttpServletResponse response) {   
  184.         //Http 1.0 header   
  185.         response.setDateHeader("Expires", 1L);   
  186.         response.addHeader("Pragma""no-cache");   
  187.         //Http 1.1 header   
  188.         response.setHeader("Cache-Control""no-cache, no-store, max-age=0");   
  189.     }   
  190.        
  191.   
  192. }  


然后在springsecurity的配置文件里添加,直接把文件全部拷贝过来 JCaptcha相关的配置就一段,在最下面.

application-security.xml
Java代码 复制代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:s="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
  5.                         http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"   
  6.     default-lazy-init="true">   
  7.   
  8.     <s:authentication-manager>   
  9.         <s:authentication-provider>   
  10.             <s:password-encoder hash="md5" />   
  11.             <s:jdbc-user-service data-source-ref="dataSource" />   
  12.         </s:authentication-provider>   
  13.     </s:authentication-manager>   
  14.   
  15.     <!-- 导入自定义的springsecurity国际化文件 -->   
  16.     <bean id="messageSource"  
  17.         class="org.springframework.context.support.ReloadableResourceBundleMessageSource">   
  18.         <property name="basename" value="classpath:messages_zh_CN" />   
  19.     </bean>   
  20.     <bean id="localeResolver"  
  21.         class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" />   
  22.   
  23.     <s:http auto-config="true">   
  24.         <!-- 指定登录页面 -->   
  25.         <s:form-login login-page="/login.jsp" />   
  26.         <s:logout logout-success-url="/login.jsp" />   
  27.         <!-- 对登录页面不进行拦截,这个页面也许带有参数 -->   
  28.         <s:intercept-url pattern="/login.jsp*" filters="none" />   
  29.         <s:intercept-url pattern="/resources/**" filters="none" />   
  30.            
  31.         <s:remember-me  />   
  32.            
  33.         <!-- 会话配置管理 -->   
  34.         <s:session-management invalid-session-url="/login.jsp">   
  35.         <!-- 只允许一个人登陆,并且第二个人登陆不了 -->   
  36.             <s:concurrency-control max-sessions="1"  
  37.                 error-if-maximum-exceeded="true" />   
  38.         </s:session-management>   
  39.     </s:http>   
  40.   
  41.     <!-- 启动annotation -->   
  42.     <s:global-method-security secured-annotations="enabled" />   
  43.   
  44.   
  45.   
  46.     <!-- Jcaptcha相关的配置 -->   
  47.     <bean id="captchaService"  
  48.         class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService">   
  49.         <property name="captchaEngine">   
  50.             <bean class="com.sjax.myapp.jcaptcha.GMailEngine" />   
  51.         </property>   
  52.         <!-- 默认生成的图片180秒过期 , 可另行设置    
  53.         <property name="minGuarantedStorageDelayInSeconds" value="180" />   
  54.         -->   
  55.     </bean>   
  56.        
  57. </beans>  


然后是web.xml 这就不把所有的配置列出来 ,只列出和JCaptcha相关的东西

web.xml

Java代码 复制代码  收藏代码
  1. <!-- JCaptcha`s filter -->   
  2.     <filter>   
  3.         <filter-name>jcaptchaFilter</filter-name>   
  4.         <filter-class>com.sjax.myapp.jcaptcha.JCaptchaFilter</filter-class>   
  5.         <init-param>   
  6.             <param-name>failureUrl</param-name>   
  7.             <param-value>/login.jsp</param-value>   
  8.         </init-param>   
  9.     </filter>   
  10.        
  11.     <!-- jcaptcha图片生成URL. -->   
  12.     <filter-mapping>   
  13.         <filter-name>jcaptchaFilter</filter-name>   
  14.         <url-pattern>/jcaptcha.jpg</url-pattern>   
  15.     </filter-mapping>   
  16.        
  17.     <!-- jcaptcha登录表单处理URL.   
  18.                  必须放在springSecurityFilter的filter-mapping定义之前 -->   
  19.     <filter-mapping>   
  20.         <filter-name>jcaptchaFilter</filter-name>   
  21.         <url-pattern>/j_spring_security_check</url-pattern>   
  22.     </filter-mapping>  


最后就是JSP页面了
login.jsp
Java代码 复制代码  收藏代码
  1. <%@ page contentType="text/html;charset=UTF-8"%>   
  2. <%@ include file="/common/taglibs.jsp"%>   
  3. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>   
  4. <html>   
  5.     <head>   
  6.         <title>Login</title>   
  7.         <%@ include file="/common/meta.jsp"%>   
  8.         <link href="<c:url value="/resources/css/screen.css" />"  
  9.             rel="stylesheet" type="text/css" />   
  10.         <link href="<c:url value="/resources/css/ie.css" />" rel="stylesheet"  
  11.             type="text/css" />   
  12.         <script type="text/javascript"  
  13.             src="<c:url value="/resources/jquery/1.4/jquery.js" />">   
  14. </script>   
  15.     </head>   
  16.     <body>   
  17.         <div class="container">   
  18.             <%@ include file="/common/header.jsp"%>   
  19.             <div id="content">   
  20.                 <div class="span-24 last">   
  21.                     <h3>   
  22.                         用户登录   
  23.                     </h3>   
  24.                     <div class="error">   
  25.                         ${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message }   
  26.                     </div>   
  27.                     <form id="loginForm" style="margin-top: 1em;"  
  28.                         action="<c:url value="/j_spring_security_check" />" method="post"">   
  29.                         <table class="noborder">   
  30.                             <tr>   
  31.                                 <td>   
  32.                                     <label for="username">   
  33.                                         用户名:   
  34.                                     </label>   
  35.                                 </td>   
  36.                                 <td>   
  37.                                     <input type="text" name="j_username" class="required" />   
  38.                                 </td>   
  39.                                 <td rowspan="3">   
  40.                                     <img id="captchaImg" src="<c:url value="/jcaptcha.jpg"/>" />   
  41.                                 </td>   
  42.                             </tr>   
  43.                             <tr>   
  44.                                 <td>   
  45.                                     <label for="password">   
  46.                                         密码:   
  47.                                     </label>   
  48.                                 </td>   
  49.                                 <td>   
  50.                                     <input type="password" name="j_password" class="required">   
  51.                                 </td>   
  52.                             </tr>   
  53.                             <tr>   
  54.                                 <td>   
  55.                                     <label for="j_captcha">   
  56.                                         验证码:   
  57.                                     </label>   
  58.                                 </td>   
  59.                                 <td>   
  60.                                     <input type='text' name='j_captcha' class="required" size='5' />   
  61.                                 </td>   
  62.                             </tr>   
  63.                             <tr>   
  64.                                 <td colspan='3'>   
  65.                                     <input type="checkbox" name="_spring_security_remember_me" />   
  66.                                     两周内记住我   
  67.                                     <span style="margin-left: 25px"><a   
  68.                                         href="javascript:refreshCaptcha()">看不清楚换一张</a>   
  69.                                     </span>   
  70.                                 </td>   
  71.                             </tr>   
  72.                             <tr>   
  73.                                 <td colspan="2">   
  74.                                     <input type="submit" class="button" value="登录">   
  75.                                 </td>   
  76.                             </tr>   
  77.                         </table>   
  78.                     </form>   
  79.                 </div>   
  80.             </div>   
  81.             <%@ include file="/common/footer.jsp"%>   
  82.         </div>   
  83.     </body>   
  84.     <script type="text/javascript">   
  85. function refreshCaptcha() {   
  86.     $('#captchaImg').hide().attr(   
  87.             'src',   
  88.             '<c:url value="/jcaptcha.jpg"/>' + '?' + Math   
  89.                     .floor(Math.random() * 100)).fadeIn();   
  90. }   
  91. </script>   
  92.   
  93. </html>  



我的开发环境是STS+tomcat6.29,工程是maven项目.框架用的spring3.0.5



效果图1.

springsecurity3和JCaptcha的整合_第2张图片


效果图2.

springsecurity3和JCaptcha的整合_第3张图片


BTW:因为是maven项目,所以自己要配好maven路径之类的.然后install下就行了.
如果实在不喜欢或者不会用maven,源码下下来, 照着拷贝也行的.
注意要加上JCaptcha的包还有commons-lang包
其它的spring3 springsecurity3之类的包就不多说了 打开pom.xml一个一个的看吧.

  • springsecurity3和JCaptcha的整合_第4张图片
  • 大小: 52.1 KB
  • springsecurity3和JCaptcha的整合_第5张图片
  • 大小: 35.9 KB
  • springsecurity3和JCaptcha的整合_第6张图片
  • 大小: 12.3 KB
  • security.rar (111.7 KB)
  • 描述: 项目的maven源码
  • 下载次数: 288

你可能感兴趣的:(springsecurity3和JCaptcha的整合)