前言:
近期项目进行了渗透测试,结果要求登录界面的验证码需有一次性使用、过期的功能。
小项目,也没必要为了个验证码使用redis,所以原有设想是将验证码储存在session中,但是前后端分离,项目又有设置内外网,会导致同会话内的sessionid不一致,所以将生成的验证码储存在本地使用
目录
添加工具类,在获取验证码的时候和登录使用的时候对储存的验证码进行删除
代码:
1.获取验证码图片,并对验证码的值进行储存
public void kaptcha(HttpServletRequest request, HttpServletResponse response) {
try {
// 数字类型
RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
lineCaptcha.setGenerator(randomGenerator);
// 重新生成code
lineCaptcha.createCode();
lineCaptcha.write(response.getOutputStream());
SessionContextUtils sessionContextUtils = SessionContextUtils.getInstance();
HttpSession session = request.getSession();
session.removeAttribute("checkCode");
session.setAttribute("checkCode",lineCaptcha.getCode());
session.setMaxInactiveInterval(40);
sessionContextUtils.addSession(session);
// 关闭流
response.getOutputStream().close();
} catch (IOException e) {
log.error(e.getMessage());
e.printStackTrace();
}
}
2.对验证码进行验证
public boolean check(String kaptcha) {
if (StringUtils.isEmpty(kaptcha)) {
return false;
}
try {
SessionContextUtils sessionContextUtils = SessionContextUtils.getInstance();
return sessionContextUtils.getSession(kaptcha);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
3.添加工具类,在获取验证码的时候和登录使用的时候对储存的验证码进行删除
package com.xinke.sunshine_ebid.common.utils;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
public class SessionContextUtils {
private static SessionContextUtils instance;
private HashMap<String, Map<String , Object>> sessionMap;
private SessionContextUtils() {
sessionMap = new HashMap<>();
}
public static SessionContextUtils getInstance() {
if (instance == null) {
instance = new SessionContextUtils();
}
return instance;
}
public synchronized void addSession(HttpSession session) {
// 30秒删除
sessionMap.values().removeIf(key -> (Long.parseLong(key.get("expireTime").toString()) + 30 * 1000) < System.currentTimeMillis());
if (session != null) {
Map<String , Object> sessions = new HashMap<>();
String expireTime = String.valueOf(System.currentTimeMillis());
sessions.put("expireTime", expireTime);
sessions.put("session", session);
String name = (String)session.getAttribute("checkCode");
if (name != null){
sessionMap.put(name, sessions);
}
}
}
public synchronized void delSession(HttpSession session) {
if (session != null) {
sessionMap.remove(session.getId());
}
}
public synchronized boolean getSession(String sessionName) {
// 40秒删除
sessionMap.values().removeIf(key -> (Long.parseLong(key.get("expireTime").toString()) + 60 * 1000) < System.currentTimeMillis());
if (sessionName == null) {
return false;
}
Map session = sessionMap.get(sessionName.toLowerCase());
if (session != null && session.size() > 0 ){
sessionMap.remove(sessionName.toLowerCase());
return true;
}else {
return false;
}
}
}
package com.xinke.sunshine_ebid.common.utils;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener {
private SessionContextUtils sessionContext= SessionContextUtils.getInstance();
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
sessionContext.addSession(session);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
sessionContext.delSession(session);
}
}