java生成圖形驗證碼(算數運算圖形驗證碼 + 隨機字元圖形驗證碼)
阿新 • • 發佈:2020-12-22
平凡也就兩個字: 懶和惰;
成功也就兩個字: 苦和勤;
優秀也就兩個字: 你和我。
跟著我從0學習JAVA、spring全家桶和linux運維等知識,帶你從懵懂少年走向人生巔峰,迎娶白富美!
關注微信公眾號【IT特靠譜】,每天都會分享技術心得~
生成圖形驗證碼(算數運算圖形驗證碼 + 隨機字元圖形驗證碼)
1 場景
在使用者登入、忘記密碼、使用者註冊、修改使用者資訊....等場景需要對使用者進行圖形化驗證。防止別有用心的人或機器通過介面來進行攻擊或惡意操作。
本示例講解通過java生成兩種圖形驗證碼:算數運算的圖形驗證碼和定長隨機字元圖形驗證碼!
2 編寫程式碼
2.1 建立生成指定長度的隨機字串工具類
建立生成指定長度的隨機字串工具類:RandomCodeUtil.java,該工具類在之前的部落格中講到過。
import java.util.Random; /** * 生成指定長度的隨機字串 */ public class RandomCodeUtil { /** * 生成指定長度的隨機字串(不包含數字0,和字母l、o和i) * * @param capacity 驗證碼長度 */ public static String genCode(Integer capacity) { //隨機字符集(不包含數字0和字母o、i和l) String str = "abcdefghjkmnpqrstuvwxyz123456789"; Random rand = new Random(); StringBuilder a = new StringBuilder(); for (int i = 0; i < capacity; i++) { char c = str.charAt(rand.nextInt(str.length())); a.append(c); } return a.toString(); } public static void main(String[] args) { //生產6位長度的隨機驗證碼 System.out.println(RandomCodeUtil.genCode(6)); } }
2.2 建立圖形驗證碼工具類
建立圖形驗證碼工具類:ImgCodeUtil.java
import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; /** * 生成圖形驗證碼工具類 */ public class ImgCodeUtil { /** * 圖片的寬度 */ private Integer width = 120; /** * 圖片的高度 */ private Integer height = 40; /** * 驗證碼干擾線條數 */ private Integer lineCount = 8; /** * 驗證碼code */ private String validateCode = null; /** * 驗證碼圖片Buffer */ private BufferedImage buffImg = null; /** * 構造方法 */ public ImgCodeUtil(String validateCode) { this.validateCode = validateCode; this.createCode(); } /** * 構造方法 */ public ImgCodeUtil(String validateCode, int width, int height) { this.width = width; this.height = height; this.validateCode = validateCode; this.createCode(); } /** * 生成驗證碼圖片 */ private void createCode() { int x = 0; int fontHeight; int codeY = 0; int red = 0; int green = 0; int blue = 0; int codeCount = validateCode.length(); //每個字元的寬度 x = width / codeCount; //字型的高度 fontHeight = height - 2; codeY = height - 4; // 影象buffer buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = buffImg.createGraphics(); // 生成隨機數 Random random = new Random(); // 將影象填充為白色 g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); //圖片劃線 for (int i = 0; i < lineCount; i++) { int xs = random.nextInt(width / 2); int ys = random.nextInt(height); int xe = random.nextInt(width / 2) + width / 2; int ye = random.nextInt(height); red = random.nextInt(255); green = random.nextInt(255); blue = random.nextInt(255); g.setColor(new Color(red, green, blue)); g.drawLine(xs, ys, xe, ye); } Font font = new Font("Arial", Font.BOLD, fontHeight); g.setFont(font); // 將驗證碼寫入圖片 for (int i = 0; i < codeCount; i++) { red = random.nextInt(255); green = random.nextInt(255); blue = random.nextInt(255); g.setColor(new Color(red, green, blue)); g.drawString(String.valueOf(validateCode.charAt(i)), i * x, codeY); } } /** * 輸出圖片到指定路徑 */ public void write(String path) throws IOException { OutputStream outputStream = new FileOutputStream(path); this.write(outputStream); } /** * 將圖片輸出到輸出流中 */ public void write(OutputStream outputStream) throws IOException { ImageIO.write(buffImg, "png", outputStream); outputStream.close(); } public BufferedImage getBuffImg() { return buffImg; } }
2.3 建立圖形驗證碼介面類
建立圖形驗證碼介面類:ValidateCodeService.java
import com.xxx.alltest.dto.CheckCode;
import com.xxx.alltest.entity.ValidateCode;
/**
* 圖形驗證碼介面類
*/
public interface ValidateCodeService {
/**
* 生成算數運算圖形驗證碼
*/
ValidateCode generateMathImgCode(Integer width, Integer height);
/**
* 生成隨機字串圖形驗證碼
*/
ValidateCode generateRandomImgCode(Integer width, Integer height);
/**
* 校驗圖形驗證碼值
*/
String checkValidateCode(CheckCode checkCode);
}
2.4 建立圖形驗證碼介面實現類
圖形驗證碼介面實現類:ValidateCodeServiceImpl.java
import com.xxx.alltest.dto.CheckCode;
import com.xxx.alltest.entity.ValidateCode;
import com.xxx.alltest.service.ValidateCodeService;
import com.xxx.alltest.utils.ImgCodeUtil;
import com.xxx.alltest.utils.RandomCodeUtil;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;
import java.util.UUID;
import javax.imageio.ImageIO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
/**
* 圖形驗證碼介面實現類
*/
@Slf4j
@Service
public class ValidateCodeServiceImpl implements ValidateCodeService {
/**
* 驗證碼過期時間:5分鐘
*/
private static final Long EXPIRE_TIME = 5 * 60 * 1000L;
/**
* 生成算數運算圖形驗證碼
*/
@Override
public ValidateCode generateMathImgCode(Integer width, Integer height) {
Integer firstNum = RandomUtils.nextInt() % 10 + 1;
Integer secondNum = RandomUtils.nextInt() % 10 + 1;
Integer validateCode = firstNum + secondNum;
ImgCodeUtil imgCodeUtil = new ImgCodeUtil(firstNum + "+" + secondNum + "=?", width, height);
BufferedImage buffImg = imgCodeUtil.getBuffImg();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String base64ImgCode = null;
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
try {
ImageIO.write(buffImg, "png", byteArrayOutputStream);
byte[] bytes = byteArrayOutputStream.toByteArray();
base64ImgCode = Base64Utils.encodeToString(bytes);
//將生成的驗證碼快取起來
// redisTemplate.set(String.join(":", "mathImgCode", uuid), validateCode.toString(), EXPIRE_TIME);
} catch (IOException var10) {
log.error("生成算數運算圖形驗證碼失敗");
}
return ValidateCode.builder()
.base64ImgCode(base64ImgCode)
.uuid(uuid)
.build();
}
/**
* 生成隨機字串圖形驗證碼
*/
@Override
public ValidateCode generateRandomImgCode(Integer width, Integer height) {
String validateCode = RandomCodeUtil.genCode(4);
ImgCodeUtil imgCodeUtil = new ImgCodeUtil(validateCode, width, height);
BufferedImage buffImg = imgCodeUtil.getBuffImg();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String base64ImgCode = null;
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
try {
ImageIO.write(buffImg, "png", byteArrayOutputStream);
byte[] bytes = byteArrayOutputStream.toByteArray();
base64ImgCode = Base64Utils.encodeToString(bytes);
//將生成的驗證碼快取起來
// redisTemplate.set(String.join(":", "randomImgCode", uuid), validateCode, EXPIRE_TIME);
} catch (IOException var10) {
log.error("生成隨機字串圖形驗證碼失敗");
}
return ValidateCode.builder()
.base64ImgCode(base64ImgCode)
.uuid(uuid)
.build();
}
/**
* 校驗圖形驗證碼值
*/
@Override
public String checkValidateCode(CheckCode checkCode) {
String redisCode = null;
// String redisCode = redisTemplate.get(String.join(":", "randomImgCode", checkCode.getUuid()));
if (StringUtils.isEmpty(redisCode)) {
return "驗證碼已過期";
}
if (!Objects.equals(checkCode.getValidateCode(), redisCode)) {
return "驗證碼錯誤";
}
return null;
}
}
2.5 建立驗證碼相關api介面類
建立驗證碼相關api介面類:ValidateCodeController.java
import com.xxx.alltest.all.oss.common.Result;
import com.xxx.alltest.dto.CheckCode;
import com.xxx.alltest.entity.ValidateCode;
import com.xxx.alltest.service.ValidateCodeService;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 驗證碼相關api介面
*/
@RestController
@RequestMapping("/validate")
public class ValidateCodeController {
@Autowired
private ValidateCodeService validateCodeService;
/**
* 生成圖形驗證碼
*
* @param type 0-普通字元圖形驗證碼(如:1a4h) 1-算數圖形驗證碼(1+8=?)
*/
@GetMapping("generate")
public Result<ValidateCode> generate(@RequestParam(value = "type", defaultValue = "0") String type,
@RequestParam(value = "width", defaultValue = "100") Integer width,
@RequestParam(value = "height", defaultValue = "40") Integer height) {
ValidateCode validateCode = null;
if (Objects.equals("0", type)) {
validateCode = validateCodeService.generateRandomImgCode(width, height);
} else {
validateCode = validateCodeService.generateMathImgCode(width, height);
}
if (StringUtils.isEmpty(validateCode.getBase64ImgCode())) {
return Result.failed("生成圖形驗證碼失敗");
} else {
return Result.ok(validateCode);
}
}
/**
* 校驗圖形驗證碼
*/
@PostMapping("check")
public Result check(@RequestBody CheckCode checkCode) {
String msg = validateCodeService.checkValidateCode(checkCode);
if (!StringUtils.isEmpty(msg)) {
return Result.failed(msg);
}
return Result.ok();
}
}
如果你有疑問或需要技術支援,關注公眾號聯絡我吧~