很多系统进行登录的时候,都会要求用户输入验证码。我们可以让springSecurity在进行用户密码校验之前进行验证码的校验,验证码验证通过再进行用户密码的校验。我们需要自定义过滤器。
1: 在jsp目录下新增一个imageCode.jsp文件,该文件用于生成验证码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Random"%>
<%@ page import="java.io.OutputStream"%>
<%@ page import="java.awt.Color"%>
<%@ page import="java.awt.Font"%>
<%@ page import="java.awt.Graphics"%>
<%@ page import="java.awt.image.BufferedImage"%>
<%@ page import="javax.imageio.ImageIO"%>
<%
int width = 80;
int height = 32;
//create the image
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
// set the background color
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, width, height);
// draw the border
g.setColor(Color.black);
g.drawRect(0, 0, width – 1, height – 1);
// create a random instance to generate the codes
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
// make some confusion
for (int i = 0; i < 50; i++) {
int x = rdm.nextInt(width);
int y = rdm.nextInt(height);
g.drawOval(x, y, 0, 0);
}
// generate a random code
String capstr = hash1.substring(0, 4);
session.setAttribute("key", capstr);
g.setColor(new Color(0, 100, 0));
g.setFont(new Font("Candara", Font.BOLD, 24));
g.drawString(capstr, 8, 24);
g.dispose();
response.setContentType("image/jpeg");
out.clear();
out = pageContext.pushBody();
OutputStream strm = response.getOutputStream();
ImageIO.write(image, "jpeg", strm);
strm.close();
%>
login.jsp文件修改增加下面代码,用于显示验证码
<input type="text" name="imageCode"/><img src="${pageContext.request.contextPath}/imageCode"><br>
MainController中增加下面方法
@RequestMapping("/imageCode")
public String imageCode() {
return "imageCode";
}
2:自定义验证码过滤器ImageCodeAuthenticationFilter,在security包下新增ImageCodeAuthenticationFilter类。
package com.xhc.security;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
*/
public class ImageCodeAuthenticationFilter extends OncePerRequestFilter {
private AuthenticationFailureHandler authenticationFailureHandler;
public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
this.authenticationFailureHandler = authenticationFailureHandler;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//判断当前请求 是否为登录请求
if( request.getRequestURI().contains("/securityLogin") ){
//校验验证码
try {
//获取用户输入的验证码
final String imageCode = request.getParameter("imageCode");
//获取系统生成的验证码
String key = (String)request.getSession().getAttribute("key");
if(StringUtils.isEmpty(imageCode.trim())){
throw new ImageCodeException( "验证码必须输入");
}
if(!imageCode.trim().equals(key.trim())){
throw new ImageCodeException( "验证码不一致");
}
}catch (AuthenticationException e){
//交给自定义AuthentFailureHandler处理
authenticationFailureHandler.onAuthenticationFailure(request,response,e);
return;
}
}
filterChain.doFilter(request,response);
}
}
同时也在security包下自定义一个验证码的异常处理类ImageCodeException
package com.xhc.security;
import org.springframework.security.core.AuthenticationException;
public class ImageCodeException extends AuthenticationException {
public ImageCodeException(String msg, Throwable t) {
super(msg, t);
}
public ImageCodeException(String msg) {
super(msg);
}
}
3: 修改spring-security.xml文件,在下面添加
<bean id="imageCodeAuthenticationFilter" class="com.xhc.security.ImageCodeAuthenticationFilter">
<property name="authenticationFailureHandler" ref="myAuthenticationFailureHandler"/>
</bean>
在security-form标签前添加
<!– 自定义验证码过滤器,在表单登录之前调用 –>
<security:custom-filter ref="imageCodeAuthenticationFilter" before="FORM_LOGIN_FILTER"/>
4: 启动项目,输入验证码进行登录,到这里就ok了。