開始敲代碼前,先簡單介紹下大致的想法實現:
生成驗證碼:
提供一個接口, 這個接口里,我們將生成的驗證碼存入session,然后將驗證碼以圖片格式或者base64編碼串返回給調用端。
校驗驗證碼:
提供一個接口,這個接口里,我們收到調用端傳過來的校驗碼,然后從session取出驗證碼,兩個驗證碼都全部轉小寫,進行無大小寫區分匹配校驗,返回true/flase 。
存儲驗證碼:
生成的驗證碼,在未生成圖片的時候,就將4位驗證碼字符先存入session,以‘JCCODE’作為存取session的key。
OK,不廢話,開始敲代碼:
首先創建工具類,ValidateCodeUtil.java:
可以看注釋,里面包含了設置驗證碼圖片的寬高,干擾線數量,驗證碼個數;返回圖片,返回base6編碼串,存入session域等等。
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.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.Random;
/**
* @Author : JCccc
* @CreateTime : 2019/9/25
* @Description :
**/
public class ValidateCodeUtil {
private static Random random = new Random();
private int width = 165; //驗證碼的寬
private int height = 45; //驗證碼的高
private int lineSize = 30; //驗證碼中夾雜的干擾線數量
private int randomStrNum = 4; //驗證碼字符個數
private String randomString = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ";
private final String sessionKey = "JCCODE";
//字體的設置
private Font getFont() {
return new Font("Times New Roman", Font.ROMAN_BASELINE, 40);
}
//顏色的設置
private static Color getRandomColor(int fc, int bc) {
fc = Math.min(fc, 255);
bc = Math.min(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 - 12);
return new Color(r, g, b);
}
//干擾線的繪制
private void drawLine(Graphics g) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(20);
int yl = random.nextInt(10);
g.drawLine(x, y, x + xl, y + yl);
}
//隨機字符的獲取
private String getRandomString(int num){
num = num > 0 ? num : randomString.length();
return String.valueOf(randomString.charAt(random.nextInt(num)));
}
//字符串的繪制
private String drawString(Graphics g, String randomStr, int i) {
g.setFont(getFont());
g.setColor(getRandomColor(108, 190));
//System.out.println(random.nextInt(randomString.length()));
String rand = getRandomString(random.nextInt(randomString.length()));
randomStr += rand;
g.translate(random.nextInt(3), random.nextInt(6));
g.drawString(rand, 40 * i + 10, 25);
return randomStr;
}
//生成隨機圖片
public void getRandomCodeImage(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
// BufferedImage類是具有緩沖區的Image類,Image類是用於描述圖像信息的類
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
g.setColor(getRandomColor(105, 189));
g.setFont(getFont());
// 干擾線
for (int i = 0; i < lineSize; i++) {
drawLine(g);
}
// 隨機字符
String randomStr = "";
for (int i = 0; i < randomStrNum; i++) {
randomStr = drawString(g, randomStr, i);
}
System.out.println("隨機字符:"+randomStr);
g.dispose();
//移除之前的session中的驗證碼信息
session.removeAttribute(sessionKey);
//重新將驗證碼放入session
session.setAttribute(sessionKey, randomStr);
try {
// 將圖片以png格式返回,返回的是圖片
ImageIO.write(image, "PNG", response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
//生成隨機圖片的base64編碼字符串
public String getRandomCodeBase64(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
// BufferedImage類是具有緩沖區的Image類,Image類是用於描述圖像信息的類
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
g.setColor(getRandomColor(105, 189));
g.setFont(getFont());
//干擾線
for (int i = 0; i < lineSize; i++) {
drawLine(g);
}
//隨機字符
String randomStr = "";
for (int i = 0; i < randomStrNum; i++) {
randomStr = drawString(g, randomStr, i);
}
System.out.println("隨機字符:"+randomStr);
g.dispose();
session.removeAttribute(sessionKey);
session.setAttribute(sessionKey, randomStr);
String base64String = "";
try {
// 直接返回圖片
// ImageIO.write(image, "PNG", response.getOutputStream());
//返回 base64
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", bos);
byte[] bytes = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
base64String = encoder.encodeToString(bytes);
} catch (Exception e) {
e.printStackTrace();
}
return base64String;
}
}
接下來寫接口,創建一個ValidateCodeController.java,
先是生成驗證碼,返回圖片的接口:
import com.example.demo.util.ValidateCodeUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @Author : JCccc
* @CreateTime : 2019/9/25
* @Description :
**/
@RestController
public class ValidateCodeController {
//返回驗證碼圖片
@GetMapping("/getCaptchaImg")
public void getCaptchaImg(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
try {
response.setContentType("image/png");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Expire", "0");
response.setHeader("Pragma", "no-cache");
ValidateCodeUtil validateCode = new ValidateCodeUtil();
// getRandomCodeImage方法會直接將生成的驗證碼圖片寫入response
validateCode.getRandomCodeImage(request, response);
// System.out.println("session里面存儲的驗證碼為:"+session.getAttribute("JCCODE"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
用postman來調用下接口,
可以看到控制台的打印,這個驗證碼字符串已經存入了session(在后面的驗證接口有介紹取值)
OK,接下來是編寫一個校驗驗證碼接口:
//驗證碼校驗
@GetMapping("/checkCaptcha")
public boolean getCheckCaptcha(@RequestParam("code") String code, HttpSession session) {
try {
//toLowerCase() 不區分大小寫進行驗證碼校驗
String sessionCode= String.valueOf(session.getAttribute("JCCODE")).toLowerCase();
System.out.println("session里的驗證碼:"+sessionCode);
String receivedCode=code.toLowerCase();
System.out.println("用戶的驗證碼:"+receivedCode);
return !sessionCode.equals("") && !receivedCode.equals("") && sessionCode.equals(receivedCode);
} catch (Exception e) {
return false;
}
}
用postman調下接口,先生成驗證碼模擬返回給頁面了,
然后調用校驗驗證碼接口,模擬用戶在頁面輸入驗證碼,
可以看到校驗正確。
最后,再補一個返回base64編碼串的接口,
// 生成驗證碼,返回的是 base64
@GetMapping("/getCaptchaBase64")
public Object getCaptchaBase64(HttpServletRequest request, HttpServletResponse response) {
Map result = new HashMap();
try {
response.setContentType("image/png");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Expire", "0");
response.setHeader("Pragma", "no-cache");
ValidateCodeUtil validateCode = new ValidateCodeUtil();
// 返回base64
String base64String = validateCode.getRandomCodeBase64(request, response);
result.put("url", "data:image/png;base64," + base64String);
result.put("message", "created successfull");
//http://tool.chinaz.com/tools/imgtobase/ base64直接轉為圖片網站
System.out.println("結果:" + result.get("url"));
} catch (Exception e) {
System.out.println(e);
}
return result;
}
用postman調用一下,
控制台打印:
將url取出來,
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAAAtCAIAAABAqjw4AAACjklEQVR42u3bzW7DIAwHcB57x0l7hG67TVp37juySpFQlPDxj21sKEacWrRQfhDAsBDh9H372HIcJj3+vp45eoJTmNp7r+7wq3if4d1+Yu/74w3PPugX9fY5fkpvJranKb2liq25HdjXmeWdPunXD56KzSZWHt+VlcGwHSJVjO59wO6hvhGC3uPs/gW3Ce/32zML9lGKd9a130AHvfetXMr6u3/aczfmlI3n75KoCfnhZW64BZd66AHb3lt/Tdf0fsnAyyVv8Jf28lZbxtcn76nhS96lRYPNfkzTG1+Zz6h+yRskfwVvweXVln4/f7IZL5At5t4G3jh8kwq0JEi7d8cwS0W9yYkUUHufI+TTe3fdTbl3A/L5vEox2eWSQlgNeWM33/mC3s19udn45uwRNV/mODmhAAf77H2Ow1wd/cLe+8HN2SMOMrjB4VtfnwsG2irf2ninMtsjzzPijN7ICFbwphWQ8a7HzyuBLSlv5QPQJme2ABM7YvHUjt518soaLTHLeqvFuZDhm43JaHqD5IFQD8Kxt2w4c38AijyUfzDa5DwU4GPjY7e7N3OPy4QvHYCSa4J0Bdw7zegjeJ9/jrY3EtWivcy7HocgnGTvUodjemcbxMybjGR1ewn3Zg7uBC8yvg/NG+JUyfDqMT/WZvU+J95PbXZJNW+r3pY4S3P/mN6Rdj91HHVbb06Bft7IBHrtfurV6WdBb6mVuVS8RXW95v+xV98BCnrjNyCC2k8dsN35ZrJ/7WrsbP8VeEAV9Bt6zDEnZS9bwyz59pTsh2PFW1ZY1vWwR469o/j9NU+jdSz3Xp3cvZ3cvRcmd++1yMPg/dGTbKsGq8q5ugl5sK2fqyuT29xncnXlBk/5HyEm10e/qyfBAAAAAElFTkSuQmCC
去base64編碼串轉圖片的網站去看看,對應的驗證碼圖:
OK,生成驗證碼和校驗的相關教程到此結束。
————————————————
版權聲明:本文為CSDN博主「小目標青年」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_35387940/article/details/101368003