臭味相投的朋友们,我在这里:
猿in小站:http://www.yuanin.net
csdn博客:https://blog.csdn.net/jiabeis
简书:https://www.jianshu.com/u/4cb7d664ec4b
微信免费订阅号“猿in”
当前互联网流行使用滑块验证码,如下图是网易严选的登录验证部分。
很多网站使用滑块验证码提高网站安全性,为了做到真正的验证,必须要走后台服务器。
下面是java实现滑块验证的核心步骤:
package com.sikong.ms.web.shiro;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* @Auther herb
* @Description 本地缓存:用户图形验证码资源
* @Date: create in ${Time} ${Date}
* @Modified By: herb
*/
@Slf4j
public class ValidateCache {
private static LoadingCache> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(365, TimeUnit.DAYS)
.build(createCacheLoader());
private static CacheLoader> createCacheLoader() {
return new CacheLoader>(){
@Override
public List load(String key) throws Exception {
return null;
}
};
}
public static void set(String key,List value){
cache.put(key,value);
}
public static List get(String key){
List value = null;
try {
value = cache.get(key);
} catch (Exception e) {
log.info("ValidateCache 缓存未查询到图片或模板!");
value = null;
}
return value;
}
public static long size(){
return cache.size();
}
public static void main(String[] args) throws UnsupportedEncodingException {
List value = new ArrayList<>();
value.add("ok".getBytes("utf-8"));
ValidateCache.set("121", value);
ValidateCache.set("111",value);
ValidateCache.set("12",value);
ValidateCache.set("113",value);
System.out.println(cache.size());
//注意缓存的最大容量
List rv = ValidateCache.get("113");
System.out.println(new String(rv.get(0),"utf-8"));
System.out.println(ValidateCache.size());
while (cache.size() > 0){
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
List rv1 = ValidateCache.get("113");
System.out.println(new String(rv1.get(0),"utf-8"));
}
}
}
package com.sikong.ms.common.captcha.validate;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
/**
* 滑块验证工具类
*
* @author: herb
* @Description:
* @Date: Created in 10:57 2018/6/25
* @Modified By:
*/
@Slf4j
public class VerifyImageUtil {
private static int ORI_WIDTH = 350; //源文件宽度
private static int ORI_HEIGHT = 213; //源文件高度
private static int X; //抠图坐标x
private static int Y; //抠图坐标y
private static int WIDTH; //模板图宽度
private static int HEIGHT; //模板图高度
private static float xPercent; //X位置移动百分比
private static float yPercent; //Y位置移动百分比
public static int getX() {
return X;
}
public static int getY() {
return Y;
}
public static float getxPercent() {
return xPercent;
}
public static float getyPercent() {
return yPercent;
}
/**
* 根据模板切图
*
* @param templateFile
* @param targetFile
* @param templateType
* @param targetType
* @return
* @throws Exception
*/
public static Map pictureTemplatesCut(byte[] templateFile, byte[] targetFile, String templateType, String targetType) throws Exception {
Map pictureMap = new HashMap<>();
// 文件类型
String templateFiletype = templateType;
String targetFiletype = targetType;
if (StringUtils.isEmpty(templateFiletype) || StringUtils.isEmpty(targetFiletype)) {
throw new RuntimeException("file type is empty");
}
// 源文件流
//File Orifile = targetFile;
//InputStream oriis = new FileInputStream(Orifile);
// 模板图
BufferedImage imageTemplate = ImageIO.read(new ByteArrayInputStream(templateFile));
WIDTH = imageTemplate.getWidth();
HEIGHT = imageTemplate.getHeight();
// 模板图
BufferedImage imageTarget = ImageIO.read(new ByteArrayInputStream(targetFile));
ORI_WIDTH = imageTarget.getWidth();
ORI_HEIGHT = imageTarget.getHeight();
generateCutoutCoordinates();
// 最终图像
BufferedImage newImage = new BufferedImage(WIDTH, HEIGHT, imageTemplate.getType());
Graphics2D graphics = newImage.createGraphics();
graphics.setBackground(Color.white);
int bold = 5;
// 获取感兴趣的目标区域
BufferedImage targetImageNoDeal = getTargetArea(X, Y, WIDTH, HEIGHT, new ByteArrayInputStream(targetFile), targetFiletype);
// 根据模板图片抠图
newImage = DealCutPictureByTemplate(targetImageNoDeal, imageTemplate, newImage);
// 设置“抗锯齿”的属性
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setStroke(new BasicStroke(bold, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
graphics.drawImage(newImage, 0, 0, null);
graphics.dispose();
ByteArrayOutputStream os = new ByteArrayOutputStream();//新建流。
ImageIO.write(newImage, templateFiletype, os);//利用ImageIO类提供的write方法,将bi以png图片的数据模式写入流。
byte[] newImages = os.toByteArray();
pictureMap.put("newImage", newImages);
// 源图生成遮罩
BufferedImage oriImage = ImageIO.read(new ByteArrayInputStream(targetFile));
byte[] oriCopyImages = DealOriPictureByTemplate(oriImage, imageTemplate, X, Y);
pictureMap.put("oriCopyImage", oriCopyImages);
pictureMap.put("X",X);
pictureMap.put("Y",Y);
return pictureMap;
}
/**
* 根据模板切图
*
* @param templateFile
* @param targetFile
* @param templateType
* @param targetType
* @return
* @throws Exception
*/
public static Map pictureTemplatesCut(File templateFile, File targetFile, String templateType, String targetType) throws Exception {
Map pictureMap = new HashMap<>();
// 文件类型
String templateFiletype = templateType;
String targetFiletype = targetType;
if (StringUtils.isEmpty(templateFiletype) || StringUtils.isEmpty(targetFiletype)) {
throw new RuntimeException("file type is empty");
}
// 源文件流
File Orifile = targetFile;
InputStream oriis = new FileInputStream(Orifile);
// 模板图
BufferedImage imageTemplate = ImageIO.read(templateFile);
WIDTH = imageTemplate.getWidth();
HEIGHT = imageTemplate.getHeight();
// 模板图
BufferedImage imageTarget = ImageIO.read(Orifile);
ORI_WIDTH = imageTarget.getWidth();
ORI_HEIGHT = imageTarget.getHeight();
generateCutoutCoordinates();
// 最终图像
BufferedImage newImage = new BufferedImage(WIDTH, HEIGHT, imageTemplate.getType());
Graphics2D graphics = newImage.createGraphics();
graphics.setBackground(Color.white);
int bold = 5;
// 获取感兴趣的目标区域
BufferedImage targetImageNoDeal = getTargetArea(X, Y, WIDTH, HEIGHT, oriis, targetFiletype);
// 根据模板图片抠图
newImage = DealCutPictureByTemplate(targetImageNoDeal, imageTemplate, newImage);
// 设置“抗锯齿”的属性
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setStroke(new BasicStroke(bold, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
graphics.drawImage(newImage, 0, 0, null);
graphics.dispose();
ByteArrayOutputStream os = new ByteArrayOutputStream();//新建流。
ImageIO.write(newImage, templateFiletype, os);//利用ImageIO类提供的write方法,将bi以png图片的数据模式写入流。
byte[] newImages = os.toByteArray();
pictureMap.put("newImage", newImages);
// 源图生成遮罩
BufferedImage oriImage = ImageIO.read(Orifile);
byte[] oriCopyImages = DealOriPictureByTemplate(oriImage, imageTemplate, X, Y);
pictureMap.put("oriCopyImage", oriCopyImages);
pictureMap.put("X",X);
pictureMap.put("Y",Y);
return pictureMap;
}
/**
* 抠图后原图生成
*
* @param oriImage
* @param templateImage
* @param x
* @param y
* @return
* @throws Exception
*/
private static byte[] DealOriPictureByTemplate(BufferedImage oriImage, BufferedImage templateImage, int x,
int y) throws Exception {
// 源文件备份图像矩阵 支持alpha通道的rgb图像
BufferedImage ori_copy_image = new BufferedImage(oriImage.getWidth(), oriImage.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
// 源文件图像矩阵
int[][] oriImageData = getData(oriImage);
// 模板图像矩阵
int[][] templateImageData = getData(templateImage);
//copy 源图做不透明处理
for (int i = 0; i < oriImageData.length; i++) {
for (int j = 0; j < oriImageData[0].length; j++) {
int rgb = oriImage.getRGB(i, j);
int r = (0xff & rgb);
int g = (0xff & (rgb >> 8));
int b = (0xff & (rgb >> 16));
//无透明处理
rgb = r + (g << 8) + (b << 16) + (255 << 24);
ori_copy_image.setRGB(i, j, rgb);
}
}
for (int i = 0; i < templateImageData.length; i++) {
for (int j = 0; j < templateImageData[0].length - 5; j++) {
int rgb = templateImage.getRGB(i, j);
//对源文件备份图像(x+i,y+j)坐标点进行透明处理
if (rgb != 16777215 && rgb <= 0) {
int rgb_ori = ori_copy_image.getRGB(x + i, y + j);
int r = (0xff & rgb_ori);
int g = (0xff & (rgb_ori >> 8));
int b = (0xff & (rgb_ori >> 16));
rgb_ori = r + (g << 8) + (b << 16) + (150 << 24);
ori_copy_image.setRGB(x + i, y + j, rgb_ori);
} else {
//do nothing
}
}
}
ByteArrayOutputStream os = new ByteArrayOutputStream();//新建流。
ImageIO.write(ori_copy_image, "png", os);//利用ImageIO类提供的write方法,将bi以png图片的数据模式写入流。
byte b[] = os.toByteArray();//从流中获取数据数组。
return b;
}
/**
* 根据模板图片抠图
*
* @param oriImage
* @param templateImage
* @return
*/
private static BufferedImage DealCutPictureByTemplate(BufferedImage oriImage, BufferedImage templateImage,
BufferedImage targetImage) throws Exception {
// 源文件图像矩阵
int[][] oriImageData = getData(oriImage);
// 模板图像矩阵
int[][] templateImageData = getData(templateImage);
// 模板图像宽度
try {
for (int i = 0; i < templateImageData.length; i++) {
// 模板图片高度
for (int j = 0; j < templateImageData[0].length; j++) {
// 如果模板图像当前像素点不是白色 copy源文件信息到目标图片中
int rgb = templateImageData[i][j];
if (rgb != 16777215 && rgb <= 0) {
targetImage.setRGB(i, j, oriImageData[i][j]);
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {/*数组越界错误处理,这样页面就不会返回图像问题。*/
log.error("X:"+X+ "||Y:"+Y,e);
} catch (Exception e) {
log.error("X:"+X+ "||Y:"+Y,e);
}
return targetImage;
}
/**
* 获取目标区域
*
* @param x 随机切图坐标x轴位置
* @param y 随机切图坐标y轴位置
* @param targetWidth 切图后目标宽度
* @param targetHeight 切图后目标高度
* @param ois 源文件输入流
* @return
* @throws Exception
*/
private static BufferedImage getTargetArea(int x, int y, int targetWidth, int targetHeight, InputStream ois,
String filetype) throws Exception {
Iterator imageReaderList = ImageIO.getImageReadersByFormatName(filetype);
ImageReader imageReader = imageReaderList.next();
// 获取图片流
ImageInputStream iis = ImageIO.createImageInputStream(ois);
// 输入源中的图像将只按顺序读取
imageReader.setInput(iis, true);
ImageReadParam param = imageReader.getDefaultReadParam();
Rectangle rec = new Rectangle(x, y, targetWidth, targetHeight);
param.setSourceRegion(rec);
BufferedImage targetImage = imageReader.read(0, param);
return targetImage;
}
/**
* 生成图像矩阵
*
* @param
* @return
* @throws Exception
*/
private static int[][] getData(BufferedImage bimg) throws Exception {
int[][] data = new int[bimg.getWidth()][bimg.getHeight()];
for (int i = 0; i < bimg.getWidth(); i++) {
for (int j = 0; j < bimg.getHeight(); j++) {
data[i][j] = bimg.getRGB(i, j);
}
}
return data;
}
/**
* 随机生成抠图坐标
*/
private static void generateCutoutCoordinates() {
Random random = new Random();
int widthDifference = ORI_WIDTH - WIDTH;
int heightDifference = ORI_HEIGHT - HEIGHT;
if (widthDifference <= 0) {
X = 5;
} else {
X = random.nextInt(ORI_WIDTH - WIDTH);
if (X < WIDTH) {/*@herb 解决切图相对位置问题*/
X = WIDTH;
}
}
if (heightDifference <= 0) {
Y = 5;
} else {
Y = random.nextInt(ORI_HEIGHT - HEIGHT);
}
NumberFormat numberFormat = NumberFormat.getInstance();
numberFormat.setMaximumFractionDigits(2);
xPercent = Float.parseFloat(numberFormat.format((float) X / (float) ORI_WIDTH));
yPercent = Float.parseFloat(numberFormat.format((float) Y / (float) ORI_HEIGHT));
}
}
package com.sikong.ms.web.controller;
import com.google.common.collect.Maps;
import com.sikong.hexuan.entity.welfare.WelEmployee;
import com.sikong.ms.common.auth.shiro.UsernamePasswordToken;
import com.sikong.ms.common.cache.jedis.JedisConfig;
import com.sikong.ms.common.cache.jedis.JedisUtils;
import com.sikong.ms.common.captcha.validate.VerifyImageUtil;
import com.sikong.ms.common.util.Digests;
import com.sikong.ms.common.util.FileUtil;
import com.sikong.ms.web.service.WelEmployeeService;
import com.sikong.ms.web.shiro.AccountAuthorizationRealm;
import com.sikong.ms.web.shiro.CacheUtils;
import com.sikong.ms.web.shiro.ValidateCache;
import com.sikong.ms.web.utils.NumberUtils;
import com.sikong.ms.web.utils.SendMessageUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.io.*;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
1. Created by yansheng on 2014/6/29.
*/
@Slf4j
@Controller
@RequestMapping("/validate")
public class ValidateController {
@Resource
private WelEmployeeService employeeService;
/**
* 生成验证码
*
* @return
*/
@RequestMapping(value = "/init")
@ResponseBody
public JSONObject init() throws IOException {
JSONObject object = new JSONObject();
/*redis实现:使用base64编码转化成字符串处理*/
// List imgList = JedisUtils.getList(JedisConfig.KEY_VALIDATE_IMG);
// List tpllist = JedisUtils.getList(JedisConfig.KEY_VALIDATE_TPL);
// if (null == imgList || imgList.size() < 1 || tpllist == null || tpllist.size() < 1) {
// imgList = new ArrayList();
// tpllist = new ArrayList();
// initValidateResources(imgList,tpllist);
// JedisUtils.setList(JedisConfig.KEY_VALIDATE_IMG,imgList,JedisConfig.JEDIS_EXPIRE*3);
// JedisUtils.setList(JedisConfig.KEY_VALIDATE_TPL,tpllist,JedisConfig.JEDIS_EXPIRE*3);
// }
/*本地缓存实现*/
List imgList = ValidateCache.get(JedisConfig.KEY_VALIDATE_IMG);
List tpllist = ValidateCache.get(JedisConfig.KEY_VALIDATE_TPL);
if (null == imgList || imgList.size() < 1 || tpllist == null || tpllist.size() < 1) {
imgList = new ArrayList();
tpllist = new ArrayList();
initValidateResources(imgList,tpllist);
ValidateCache.set(JedisConfig.KEY_VALIDATE_IMG,imgList);
ValidateCache.set(JedisConfig.KEY_VALIDATE_TPL,tpllist);
}
byte[] targetIS = null;
byte[] templateIS = null;
Random ra = new Random();
if (null != imgList){
int rd = ra.nextInt(imgList.size());
targetIS = imgList.get(rd);
}
if (null != tpllist){
int rd = ra.nextInt(tpllist.size());
templateIS = tpllist.get(rd);
}
Map pictureMap = null;
try {
pictureMap = VerifyImageUtil.pictureTemplatesCut(templateIS,targetIS , "png", "jpg");
String newImage = Base64Utils.encodeToString((byte[]) pictureMap.get("newImage"));
String sourceImage = Base64Utils.encodeToString((byte[]) pictureMap.get("oriCopyImage"));
int X = (int) pictureMap.get("X");
int Y = (int) pictureMap.get("Y");
object.put("newImage", newImage);
object.put("sourceImage", sourceImage);
//object.put("X", X);
object.put("Y", Y);
String token = UUID.randomUUID().toString().replaceAll("-", "");
Map tokenObj = new HashMap();
tokenObj.put("token", token);
tokenObj.put("X", X);
tokenObj.put("Y", Y);
//token 保存2分钟
JedisUtils.setObjectMap(JedisConfig.KEY_VALIDATE_TOKEN + ":" + token, tokenObj, 120000);
object.put("token", token);
} catch (Exception e) {
log.error("",e);
}
return object;
}
/**
* 初始化验证图形生成资源
* @param imgList
* @param tpllist
*/
private void initValidateResources(List imgList, List tpllist) throws IOException {
/*加载验证原图*/
String target = URLDecoder.decode(ValidateController.class.getClassLoader().getResource("static/image/validate/targets").getPath(),"UTF-8");
byte[] targetIS = null;
byte[] templateIS = null;
if (target.indexOf("!/") != -1) {//jar包
String jarPath = "jar:" + target;
log.debug(jarPath);
URL jarURL = new URL(jarPath);
JarURLConnection jarCon = (JarURLConnection) jarURL.openConnection();
JarFile jarFile = jarCon.getJarFile();
Enumeration jarEntrys = jarFile.entries();
while (jarEntrys.hasMoreElements()) {
JarEntry entry = jarEntrys.nextElement();
String name = entry.getName();
if (name.startsWith("static/image/validate/targets") && !name.equals("static/image/validate/targets/") && (name.endsWith(".jpg") || name.endsWith(".png"))) {
log.debug("targets=" + name);
InputStream isTemplates = jarFile.getInputStream(entry);
targetIS = IOUtils.toByteArray(jarFile.getInputStream(entry));
imgList.add(targetIS);
} else if (name.startsWith("static/image/validate/templates") && !name.equals("static/image/validate/templates/") && (name.endsWith(".jpg") || name.endsWith(".png"))) {
log.debug("templates=" + name);
InputStream isTemplates = jarFile.getInputStream(entry);
templateIS = IOUtils.toByteArray(jarFile.getInputStream(entry));
tpllist.add(templateIS);
}
}
} else {
File targetBaseFile = new File(target);
if (null != targetBaseFile) {
File[] fs = targetBaseFile.listFiles();
// Random ra = new Random();
// if (null != fs && fs.length > 0) {
// int random = ra.nextInt(fs.length);
// targetIS = IOUtils.toByteArray(new FileInputStream(fs[random]));
// }
for (File f : fs){
targetIS = IOUtils.toByteArray(new FileInputStream(f));
imgList.add(targetIS);
}
}
/*加载切图模板*/
String template = URLDecoder.decode(ValidateController.class.getClassLoader().getResource("static/image/validate/templates").getFile(),"UTF-8");
File templateBaseFile = new File(template);
if (null != templateBaseFile) {
File[] fs = templateBaseFile.listFiles();
// Random ra = new Random();
// if (null != fs && fs.length > 0) {
// int random = ra.nextInt(fs.length);
// templateIS = IOUtils.toByteArray(new FileInputStream(fs[random]));
// }
for (File f : fs){
templateIS = IOUtils.toByteArray(new FileInputStream(f));
tpllist.add(templateIS);
}
}
}
log.info("initValidateResources:template size:" + tpllist.size() + "target size:" + imgList.size());
}
/**
* 验证方法 (有验证码的方法提交,有时候也可以带上验证参数,做后端二次验证)
*
* @return
*/
@RequestMapping(value = "check",method = RequestMethod.POST)
@ResponseBody
public boolean check(String token, int X, int Y) {
JSONObject message = new JSONObject();
message.put("code", 2);
message.put("massage", "验证不通过,请重试!");
if (null == token || token.trim().length() < 1) {
message.put("code", 0);
message.put("massage", "请求参数错误:token为空!");
}
Map tokenObj = JedisUtils.getObjectMap(JedisConfig.KEY_VALIDATE_TOKEN + ":" + token);
if (null == tokenObj) {
message.put("code", -1);
message.put("massage", "验证码超期,请重新请求!");
} else {
int sX = (Integer) tokenObj.get("X");
int sY = (Integer) tokenObj.get("Y");
if (sY != Y) {
message.put("code", 0);
message.put("massage", "请求参数错误:位置信息不正确!");
} else {
if (Math.abs(sX - X) <= 2) {
message.put("code", 1);
message.put("massage", "验证通过!");
} else {
message.put("code", 2);
message.put("massage", "验证不通过,请重试!");
}
}
}
if (message.get("code")==1) {
return true;
} else {
return false;
}
}
/**
* 根据手机号查询用户是否存在
*/
@RequestMapping("/checkUserIsHave")
@ResponseBody
public String checkUserIsHave(
@RequestParam(required = false, value = "mobile") String mobile) {
String isHave = "true";
WelEmployee welEmployee = new WelEmployee();
if (StringUtils.isNotEmpty(mobile)) {
welEmployee.setMobile(mobile);
}
WelEmployee employee = employeeService.findWelEmployee(welEmployee);
if (employee == null) {
isHave = "false";
}
return isHave;
}
/**
* 获取手机验证码
*/
@RequestMapping(value = "/getMobileCode", method = RequestMethod.POST)
@ResponseBody
public Map getMobileCode(
@RequestParam(required =true, value = "account") String account) {
Map map = Maps.newHashMap();
try {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute("recordTime", System.currentTimeMillis());//设置当前时间点
log.debug("当前时间戳==" + System.currentTimeMillis());
Integer valid = NumberUtils.getRandomInt(99999);
System.out.println(valid);
session.setAttribute("mobile", account);
session.setAttribute("validCode", valid);//验证码
SendMessageUtil sms = new SendMessageUtil();//发送短信
String str = sms.sendSms(account, " 验证码为 "+valid+",请在页面中输入以完成验证。");
map.put("success", "true");
map.put("message", "一分钟后可重新获取");
} catch (InvalidSessionException e) {
log.error("获取验证码失败", e);
map.put("success", "false");
map.put("message", "获取验证码失败!");
return map;
}
return map;
}
/**
* 校验输入的短信验证码是否正确
*/
@RequestMapping(value = "/checkMobileCode", method = RequestMethod.POST)
@ResponseBody
public Map checkMobileCode(
@RequestParam(required =true, value = "bound") String bound) {
bound = bound.trim();
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
Map map = Maps.newHashMap();
Object code = session.getAttribute("validCode");//发送的验证码
Long recordTime = (Long) session.getAttribute("recordTime");//发送验证码的时候设置的时间点
if (bound == "") {
map.put("success", "false");
map.put("message", "验证码不能为空");
return map;
} else if (code == null || recordTime == null){
map.put("success", "false");
map.put("message", "未获取验证码");
return map;
}
Long now = System.currentTimeMillis();
log.debug("1时间==" + (now));
log.debug("2时间==" + (recordTime));
log.debug("记录时间==" + (now - recordTime));
if (!bound.equals(code.toString())) {
map.put("success", "false");
map.put("message", "验证码错误");
} else if ((now - recordTime) > 65000) {
map.put("success", "false");
map.put("message", "验证码已经失效");
} else {
map.put("success", "true");
}
return map;
}
/**
* 验证密码是否正确
*/
@RequestMapping("/checkPassword")
@ResponseBody
public Map checkUserIsHave(
@RequestParam(required = false, value = "password") String password,
@RequestParam(required = false, value = "employeeId") String employeeId
) {
Map map = Maps.newHashMap();
map.put("success","true");
WelEmployee welEmployee=employeeService.findWelEmployeeByEmployeeId(employeeId);
String passwordOld=welEmployee.getPassword();
boolean res= Digests.validatePassword(password,passwordOld);
if(!res){
map.put("success","false");
}
return map;
}
public static void main(String[] args) {
String stream = ValidateController.class.getClassLoader().getResource("static/image/validate/").getFile();
File validateBaseFile = new File(stream);
File vf = null;
if (null != validateBaseFile) {
File[] fs = validateBaseFile.listFiles();
Random ra = new Random();
if (null != fs && fs.length > 0) {
int random = ra.nextInt(fs.length);
vf = fs[random];
}
}
System.out.println(vf.getName());
}
}
<#macro imgValidate>
<#---->
→
向右滑动滑块填充拼图
刷新
<#--
-->
<#--
-->
#macro>
原理:https://blog.csdn.net/qq_35992956/article/details/80801962
抠图:https://blog.csdn.net/ONROAD0612/article/details/81197158