在spring security中,可以结合jcaptcha进行使用,具体方法如下:
1.java类如下:
- package com.spring.security.jcaptcha;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.image.ImageFilter;
- import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
- import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
- import com.octo.captcha.component.image.color.RandomListColorGenerator;
- import com.octo.captcha.component.image.deformation.ImageDeformation;
- import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
- import com.octo.captcha.component.image.fontgenerator.FontGenerator;
- import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
- import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
- import com.octo.captcha.component.image.textpaster.TextPaster;
- import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
- import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
- import com.octo.captcha.component.image.wordtoimage.WordToImage;
- import com.octo.captcha.component.word.FileDictionary;
- import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;
- import com.octo.captcha.component.word.wordgenerator.WordGenerator;
- import com.octo.captcha.engine.image.ListImageCaptchaEngine;
- import com.octo.captcha.image.gimpy.GimpyFactory;
- /**
- * JCaptcha验证码图片生成引擎, 仿照JCaptcha2.0编写类似GMail验证码的样式.
- */
- public class GMailEngine extends ListImageCaptchaEngine {
- @Override
- protected void buildInitialFactories() {
- // 图片和字体大小设置
- int minWordLength = 4 ;
- int maxWordLength = 5 ;
- int fontSize = 20 ;
- int imageWidth = 100 ;
- int imageHeight = 36 ;
- WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(
- new FileDictionary( "toddlist" ));
- // word2image components
- TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength,
- maxWordLength, new RandomListColorGenerator( new Color[] {
- new Color( 23 , 170 , 27 ), new Color( 220 , 34 , 11 ),
- new Color( 23 , 67 , 172 ) }), new TextDecorator[] {});
- BackgroundGenerator background = new UniColorBackgroundGenerator(
- imageWidth, imageHeight, Color.white);
- FontGenerator font = new RandomFontGenerator(fontSize, fontSize,
- new Font[] { new Font( "nyala" , Font.BOLD, fontSize),
- new Font( "Bell MT" , Font.PLAIN, fontSize),
- new Font( "Credit valley" , Font.BOLD, fontSize) });
- ImageDeformation postDef = new ImageDeformationByFilters(
- new ImageFilter[] {});
- ImageDeformation backDef = new ImageDeformationByFilters(
- new ImageFilter[] {});
- ImageDeformation textDef = new ImageDeformationByFilters(
- new ImageFilter[] {});
- WordToImage word2image = new DeformedComposedWordToImage(font,
- background, randomPaster, backDef, textDef, postDef);
- addFactory(new GimpyFactory(dictionnaryWords, word2image));
- }
- }
过滤器如下:
- package com.spring.security.jcaptcha;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import javax.imageio.ImageIO;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.commons.lang.StringUtils;
- import org.apache.log4j.Logger;
- import org.springframework.context.ApplicationContext;
- import org.springframework.web.context.support.WebApplicationContextUtils;
- import com.octo.captcha.service.CaptchaService;
- import com.octo.captcha.service.CaptchaServiceException;
- /**
- * 针对 JCaptcha 专门的过滤器(Filter)
- *
- */
- public class JCaptchaFilter implements Filter {
- // web.xml中的参数名定义
- public static final String PARAM_CAPTCHA_PARAMTER_NAME = "captchaParamterName" ;
- public static final String PARAM_CAPTCHA_SERVICE_ID = "captchaServiceId" ;
- public static final String PARAM_FILTER_PROCESSES_URL = "filterProcessesUrl" ;
- public static final String PARAM_FAILURE_URL = "failureUrl" ;
- public static final String PARAM_AUTO_PASS_VALUE = "autoPassValue" ;
- // 默认值定义
- public static final String DEFAULT_FILTER_PROCESSES_URL = "/j_spring_security_check" ;
- public static final String DEFAULT_CAPTCHA_SERVICE_ID = "captchaService" ;
- public static final String DEFAULT_CAPTCHA_PARAMTER_NAME = "j_captcha" ;
- protected static Logger logger = Logger.getLogger( "service" );
- private String failureUrl;
- private String filterProcessesUrl = DEFAULT_FILTER_PROCESSES_URL;
- private String captchaServiceId = DEFAULT_CAPTCHA_SERVICE_ID;
- private String captchaParamterName = DEFAULT_CAPTCHA_PARAMTER_NAME;
- private String autoPassValue;
- private CaptchaService captchaService;
- /**
- * Filter回调初始化函数.
- */
- public void init(FilterConfig filterConfig) throws ServletException {
- // TODO Auto-generated method stub
- initParameters(filterConfig);
- initCaptchaService(filterConfig);
- }
- public void doFilter(ServletRequest theRequest,ServletResponse theResponse, FilterChain chain) throws IOException,
- ServletException {
- HttpServletRequest request = (HttpServletRequest) theRequest;
- HttpServletResponse response = (HttpServletResponse) theResponse;
- String servletPath = request.getServletPath();
- // 符合filterProcessesUrl为验证处理请求,其余为生成验证图片请求.
- if (StringUtils.startsWith(servletPath, filterProcessesUrl)) {
- boolean validated = validateCaptchaChallenge(request);
- if (validated) {
- chain.doFilter(request, response);
- } else {
- redirectFailureUrl(request, response);
- }
- } else {
- genernateCaptchaImage(request, response);
- }
- }
- /**
- * Filter回调退出函数.
- */
- public void destroy() {
- // TODO Auto-generated method stub
- }
- /**
- * 初始化web.xml中定义的filter init-param.
- */
- protected void initParameters( final FilterConfig fConfig) {
- if (StringUtils.isBlank(fConfig.getInitParameter(PARAM_FAILURE_URL))) {
- throw new IllegalArgumentException( "CaptchaFilter缺少failureUrl参数" );
- }
- failureUrl = fConfig.getInitParameter(PARAM_FAILURE_URL);
- if (StringUtils.isNotBlank(fConfig
- .getInitParameter(PARAM_FILTER_PROCESSES_URL))) {
- filterProcessesUrl = fConfig
- .getInitParameter(PARAM_FILTER_PROCESSES_URL);
- }
- if (StringUtils.isNotBlank(fConfig
- .getInitParameter(PARAM_CAPTCHA_SERVICE_ID))) {
- captchaServiceId = fConfig
- .getInitParameter(PARAM_CAPTCHA_SERVICE_ID);
- }
- if (StringUtils.isNotBlank(fConfig
- .getInitParameter(PARAM_CAPTCHA_PARAMTER_NAME))) {
- captchaParamterName = fConfig
- .getInitParameter(PARAM_CAPTCHA_PARAMTER_NAME);
- }
- if (StringUtils.isNotBlank(fConfig
- .getInitParameter(PARAM_AUTO_PASS_VALUE))) {
- autoPassValue = fConfig.getInitParameter(PARAM_AUTO_PASS_VALUE);
- }
- }
- /**
- * 从ApplicatonContext获取CaptchaService实例.
- */
- protected void initCaptchaService( final FilterConfig fConfig) {
- ApplicationContext context = WebApplicationContextUtils
- .getWebApplicationContext(fConfig.getServletContext());
- captchaService = (CaptchaService) context.getBean(captchaServiceId);
- }
- /**
- * 生成验证码图片.
- */
- protected void genernateCaptchaImage( final HttpServletRequest request,
- final HttpServletResponse response) throws IOException {
- setDisableCacheHeader(response);
- response.setContentType("image/jpeg" );
- ServletOutputStream out = response.getOutputStream();
- try {
- String captchaId = request.getSession(true ).getId();
- BufferedImage challenge = (BufferedImage) captchaService
- .getChallengeForID(captchaId, request.getLocale());
- ImageIO.write(challenge, "jpg" , out);
- out.flush();
- } catch (CaptchaServiceException e) {
- logger.error(e.getMessage(), e);
- } finally {
- if (out!= null ){
- out.close();
- }
- }
- }
- /**
- * 验证验证码.
- */
- protected boolean validateCaptchaChallenge( final HttpServletRequest request) {
- try {
- String captchaID = request.getSession().getId();
- String challengeResponse = request
- .getParameter(captchaParamterName);
- // 自动通过值存在时,检验输入值是否等于自动通过值
- if (StringUtils.isNotBlank(autoPassValue)&& autoPassValue.equals(challengeResponse)) {
- return true ;
- }
- return captchaService.validateResponseForID(captchaID,challengeResponse);
- } catch (CaptchaServiceException e) {
- logger.error(e.getMessage(), e);
- return false ;
- }
- }
- /**
- * 跳转到失败页面.
- *
- * 可在子类进行扩展, 比如在session中放入SpringSecurity的Exception.
- */
- protected void redirectFailureUrl( final HttpServletRequest request, final HttpServletResponse response) throws IOException {
- response.sendRedirect(request.getContextPath() + failureUrl);
- }
- /**
- * 设置禁止客户端缓存的Header.
- */
- public static void setDisableCacheHeader(HttpServletResponse response) {
- // Http 1.0 header
- response.setDateHeader("Expires" , 1L);
- response.addHeader("Pragma" , "no-cache" );
- // Http 1.1 header
- response.setHeader("Cache-Control" , "no-cache, no-store, max-age=0" );
- }
- }
web.xml 配置如下:
- <? xml version = "1.0" encoding = "UTF-8" ?>
- < web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns = "http://java.sun.com/xml/ns/javaee" xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id = "WebApp_ID" version = "2.5" >
- < display-name > springSecurityIII </ display-name >
- <!--******************************** -->
- <!--*******log4j日志信息的配置****** -->
- <!--******************************* -->
- < context-param >
- < param-name > log4jConfigLocation </ param-name >
- < param-value > classpath:log4j.xml </ param-value >
- </ context-param >
- <!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond,可以不设置 -->
- < context-param >
- < param-name > log4jRefreshInterval </ param-name >
- < param-value > 60000 </ param-value >
- </ context-param >
- <!--******************************** -->
- <!--*******spring bean的配置******** -->
- <!--******************************* -->
- < context-param >
- < param-name > contextConfigLocation </ param-name >
- < param-value > classpath:applicationContext.xml </ param-value >
- </ context-param >
- < listener >
- < listener-class > org.springframework.web.util.Log4jConfigListener </ listener-class >
- </ listener >
- < listener >
- < listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >
- </ listener >
- < listener >
- < listener-class > org.springframework.web.util.IntrospectorCleanupListener </ listener-class >
- </ listener >
- <!--******************************** -->
- <!--*******字符集 过滤器************ -->
- <!--******************************* -->
- < filter >
- < filter-name > CharacterEncodingFilter </ filter-name >
- < filter-class > org.springframework.web.filter.CharacterEncodingFilter </ filter-class >
- < init-param >
- < param-name > encoding </ param-name >
- < param-value > UTF-8 </ param-value >
- </ init-param >
- < init-param >
- < param-name > forceEncoding </ param-name >
- < param-value > true </ param-value >
- </ init-param >
- </ filter >
- < filter-mapping >
- < filter-name > CharacterEncodingFilter </ filter-name >
- < url-pattern > /* </ url-pattern >
- </ filter-mapping >
- <!--******************************** -->
- <!--*******session的配置************ -->
- <!--******************************* -->
- < session-config >
- < session-timeout > 30 </ session-timeout >
- </ session-config >
- < filter >
- < filter-name > jcaptchaFilter </ filter-name >
- < filter-class > com.spring.security.jcaptcha.JCaptchaFilter </ filter-class >
- < init-param >
- < param-name > failureUrl </ param-name >
- < param-value > /login.jsp </ param-value >
- </ init-param >
- </ filter >
- < filter-mapping >
- < filter-name > jcaptchaFilter </ filter-name >
- < url-pattern > /jcaptcha.jpg </ url-pattern >
- </ filter-mapping >
- < filter-mapping >
- < filter-name > jcaptchaFilter </ filter-name >
- < url-pattern > /j_spring_security_check </ url-pattern >
- </ filter-mapping >
- < filter >
- < filter-name > springSecurityFilterChain </ filter-name >
- < filter-class > org.springframework.web.filter.DelegatingFilterProxy </ filter-class >
- </ filter >
- < filter-mapping >
- < filter-name > springSecurityFilterChain </ filter-name >
- < url-pattern > /* </ url-pattern >
- </ filter-mapping >
- < listener >
- < listener-class > org.springframework.security.web.session.HttpSessionEventPublisher </ listener-class >
- </ listener >
- < welcome-file-list >
- < welcome-file > index.jsp </ welcome-file >
- </ welcome-file-list >
- </ web-app >
login.jsp
- <%@ include file= "/common/taglibs.jsp" %>
- <%@ page language="java" contentType= "text/html; charset=UTF-8"
- pageEncoding="UTF-8" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
- <html>
- <head>
- <meta http-equiv="Content-Type" content= "text/html; charset=UTF-8" >
- <title>登 录</title>
- <script type="text/javascript" >
- /*==============================================
- * refreash the captcha to general new picture
- *==============================================*/
- function refreshCaptcha() {
- $('#captchaImg' ).hide().attr(
- 'src' ,
- '<c:url value="/jcaptcha.jpg"/>' + '?' + Math.floor(Math.random() * 100 )).fadeIn();
- }
- </script>
- </head>
- <body>
- <center>
- <div class = "login-error" >
- ${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
- </div>
- <form action="${pageContext.request.contextPath}/j_spring_security_check" method= "post" >
- <table style="width: 60%" >
- <tr>
- <td>用户名:</td>
- <td>
- <input class = "login-smallInput" type= 'text' name= 'j_username' />
- </td>
- </tr>
- <tr>
- <td>密 码:</td>
- <td>
- <input class = "login-smallInput" type= 'password' name= 'j_password' />
- </td>
- </tr>
- <tr>
- <td>验证码:</td>
- <td>
- <input type='text' name= 'j_captcha' size= "5" />
- <img id="captchaImg" style= "vertical-align:middle" src= "<c:url value=" /jcaptcha.jpg "/>" />
- <a href="javascript:refreshCaptcha()" >看不清楚换一张</a>
- </td>
- </tr>
- <tr>
- <td>
- <input id="_spring_security_remember_me" name= "_spring_security_remember_me" type= "checkbox" />
- </td>
- <td>
- <label for = "_spring_security_remember_me" >Remember Me?</label>
- </td>
- </tr>
- <tr>
- <td colspan="2" >
- <input type="submit" name= "submit" value= "登录" />
- </td>
- </tr>
- </table>
- </form>
- </center>
- </body>
- </html>