SpringScurity实现图片验证码功能
程序员文章站
2022-04-27 11:02:50
前言整个小案例采用的是ssm+jsp+springscurity的技术1.导入依赖坐标 2.编写验证码功能我的验证码部分代码是写在后台的,并且封装成了一个工具类package utils;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;imp......
前言
整个小案例采用的是ssm+jsp+springscurity的技术
1.导入依赖坐标
2.编写验证码功能
我的验证码部分代码是写在后台的,并且封装成了一个工具类
package utils;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
public class CheckCodeUtils {
public static final String CHECKCODE_KEY = "checkCode_key";
private static Random random=new Random();
private static String randStr="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static int width=80 ;
private static int height=26 ;
private static int lineNum=10 ;
private static int strNum=4 ;
private String randString;
//获取随机验证码
public void getCheckCode(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
Graphics graphics = image.getGraphics();
graphics.fillRect(0,0,width,height);
graphics.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE,18));
graphics.setColor(getRandColor(160, 200));
//绘制干扰线
for(int i=0;i<=lineNum;i++){
drowLine(graphics);
}
//绘制随机字符
randString = "";
for(int i=1;i<=strNum;i++){
randString=drowString(graphics,randString,i);
}
session.removeAttribute(CHECKCODE_KEY);
session.setAttribute(CHECKCODE_KEY, randString);
graphics.dispose();
try {
//将内存中的图片通过流动形式输出到客户端
ImageIO.write(image, "JPEG", response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 获得字体
*/
private Font getFont(){
return new Font("Fixedsys",Font.CENTER_BASELINE,18);
}
/*
* 获得颜色
*/
private Color getRandColor(int fc, int bc){
if(fc > 255)
fc = 255;
if(bc > 255)
bc = 255;
int r = fc + random.nextInt(bc-fc-16);
int g = fc + random.nextInt(bc-fc-14);
int b = fc + random.nextInt(bc-fc-18);
return new Color(r,g,b);
}
/*
* 绘制字符串.
*/
private String drowString(Graphics g, String randomString, int i){
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101),random.nextInt(111),random.nextInt(121)));
String rand = String.valueOf(getRandomString(random.nextInt(randStr.length())));
randomString +=rand;
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(rand, 13*i, 16);
return randomString;
}
/*
* 绘制干扰线
*/
private void drowLine(Graphics g){
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x+xl, y+yl);
}
/*
* 获取随机的字符
*/
public String getRandomString(int num){
return String.valueOf(randStr.charAt(num));
}
/*比较*/
public String getRandString() {
return randString;
}
public void setRandString(String randomString) {
this.randString = randomString;
}
}
类似的图片验证码的工具类网络上也是一大堆,可以自行查找
3.前端页面
<!--验证码栏-->
<div class="usernameWrapDiv">
<div class="layui-form-item layui-inline" >
<label class="layui-form-label"><i class="layui-icon layui-icon-vercode"></i>验证: </label>
<div class="cardDiv">
<input id="loginCard" class="layui-input cardInput" type="text" name="loginCard" placeholder="输入验证码">
</div>
<div class="codeDiv">
<img name="imageCode" src="${pageContext.request.contextPath}/user/checkCode.do" alt="" width="100" height="32" class="layui-input codeInput" style="height:37.99px;cursor:pointer;"onclick="this.src=this.src+'?'">
</div>
</div>
</div>
4.Controller
@Controller
@RequestMapping("/user")
public class UserController {
CheckCodeUtils utils;
@RequestMapping("/checkCode.do")
public void checkCode(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置相应类型,告诉浏览器输出的内容为图片
utils = new CheckCodeUtils() ;
response.setContentType("image/jpeg");
//设置响应头信息,告诉浏览器不要缓存此内容
response.setHeader("pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expire", 0);
try {
utils.getCheckCode(request, response);//输出图片方法
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.实现自定义的图片验证码filter
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 {
String inputImageCode = request.getParameter("loginCard");
String outputImageCode = (String) request.getSession().getAttribute("checkCode_key");
if (StringUtils.isEmpty(inputImageCode.trim())) {
throw new ImageCodeException("验证码必须输入");
}
if (!inputImageCode.trim().equalsIgnoreCase(outputImageCode.trim())) {
throw new ImageCodeException("验证码错误");
}
}catch (AuthenticationException e){
authenticationFailureHandler.onAuthenticationFailure(request,response,e);
return;
}
}
filterChain.doFilter(request,response);
}
}
图片验证码异常类
public class ImageCodeException extends AuthenticationException {
public ImageCodeException(String msg, Throwable t) {
super(msg, t);
}
public ImageCodeException(String msg) {
super(msg);
}
}
自定义权限认证失败处理类
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
Map map = new HashMap();
map.put("success", false);
map.put("errorMsg", e.getMessage());
String str = objectMapper.writeValueAsString(map);
response.setContentType("text/json;charset=utf-8");
request.getRequestDispatcher("/failer.jsp").forward(request,response);
}
}
如果认证失败直接是转发到failer.jsp界面
request.getRequestDispatcher("/failer.jsp").forward(request,response);
6.SpringSecurity框架配置文件的修改
// 定义类型为imageCodeAuthenticationFilter的Filter 并且在 FORM_LOGIN_FILTER (通俗点理解成表单登录Filter)前先过滤
<security:custom-filter ref="imageCodeAuthenticationFilter" before="FORM_LOGIN_FILTER"/>
//将ImageCodeAuthenticationFilter和MyAuthenticationFailureHandler 交给Spring容器来进行管理
<bean id="imageCodeAuthenticationFilter" class="security.ImageCodeAuthenticationFilter">
<property name="authenticationFailureHandler" ref="myAuthenticationFailureHandler"/>
</bean>
<bean id="myAuthenticationFailureHandler" class="security.MyAuthenticationFailureHandler"/>
具体可以参考:https://blog.csdn.net/love1793912554/article/details/104298677
我觉得这里面一系列关于SpringSecurity的文章都写的很清晰也比较实用
本文地址:https://blog.csdn.net/weixin_44451209/article/details/110819253