spring security4 之 图片验证码

要实现验证码有多种方式处理,我还是认为覆写原来的用户密码的过滤器最为合理

首先修改一定要删除 <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





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值