要实现验证码有多种方式处理,我还是认为覆写原来的用户密码的过滤器最为合理
首先修改一定要删除 <security:form-login/>
替换成
<security:custom-filter ref="usernamePasswordFilter" position="FORM_LOGIN_FILTER" />
<!-- 用户名密码验证码拦截器 -->
<bean id="usernamePasswordFilter" class="com.aolong.common.security.UsernamePasswordCaptchaAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler">
<bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/" />
<property name="alwaysUseDefaultTargetUrl" value="true"/>
</bean>
</property>
<property name="authenticationFailureHandler">
<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.html?error=1" />
</bean>
</property>
</bean>
com.aolong.common.security.UsernamePasswordCaptchaAuthenticationFilter
这就是重写的验证拦截器
public class UsernamePasswordCaptchaAuthenticationFilter extends
UsernamePasswordAuthenticationFilter {
@Resource
private ImageCaptchaService imageCaptchaService;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{
String captchaId = request.getSession().getId();
String code = request.getParameter("code");
Boolean isCorrect = imageCaptchaService.validateResponseForID(captchaId, code);
if (!isCorrect){
throw new BadCaptchaException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCaptcha", "Bad captcha"));
}
return super.attemptAuthentication(request, response);
}
}
这里用到了一个验证码的服务,需要一个配置
<!-- 图片验证码 -->
<bean class="com.octo.captcha.service.multitype.GenericManageableCaptchaService">
<constructor-arg index="0" ref="imageEngine" />
<constructor-arg type="int" index="1" value="180" /><!--超时时间 秒 -->
<constructor-arg type="int" index="2" value="20000" /><!--最大并发数 -->
<constructor-arg type="int" index="3" value="20000" />
</bean>
<bean id="imageEngine" class="com.aolong.common.security.ImageGenericCaptchaEngine"/>
com.aolong.common.security.ImageGenericCaptchaEngine这是一个生成验证码的服务,也有人用配置实现,但是配置内容实在是太长了,看的头晕
public class ImageGenericCaptchaEngine extends ListImageCaptchaEngine {
@Override
protected void buildInitialFactories() {
int minWordLength = 4;
int maxWordLength = 5;
int fontSize = 50;
int imageWidth = 152;
int imageHeight = 100;
WordGenerator wordGenerator = new RandomWordGenerator(
"23456789abcdefghijkmnpqrstuvwxyz");
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(wordGenerator, word2image));
}
}
还需要一个登录页面的验证码方法服务
@Controller
public class HomeController extends BaseController{
@Resource
private ImageCaptchaService imageCaptchaService;
@RequestMapping(value = "/captcha", method = RequestMethod.GET)
public void getCode(HttpServletRequest request, HttpServletResponse response) {
try {
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
String captchaId = request.getSession().getId();
BufferedImage challenge = (BufferedImage) imageCaptchaService.getChallengeForID(captchaId,request.getLocale());
ImageIO.write(challenge, "jpeg", jpegOutputStream);
byte[] captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
ServletOutputStream responseOutputStream = response.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
} catch (Exception e) {
logger.error("generate captcha image error: {}", e.getMessage());
}
}
}
login.jsp
<div>
<input type="text" class="form-control" style="display:inline-block;width:50%" name="code" placeholder="验证码">
<img src="captcha" οnclick="this.src='captcha?t='+new Date()*1" height="30" width="70" />
</div>
完整源码下载
https://github.com/skyrocks/a-spring