diff --git a/pangu-admin/src/main/java/com/pangu/web/controller/LoginController.java b/pangu-admin/src/main/java/com/pangu/web/controller/LoginController.java index 0e2b84c..3a04295 100644 --- a/pangu-admin/src/main/java/com/pangu/web/controller/LoginController.java +++ b/pangu-admin/src/main/java/com/pangu/web/controller/LoginController.java @@ -3,6 +3,10 @@ package com.pangu.web.controller; import com.pangu.common.core.domain.AjaxResult; import org.springframework.web.bind.annotation.*; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; import java.util.*; /** @@ -16,13 +20,79 @@ public class LoginController { * 获取验证码 */ @GetMapping("/captchaImage") - public AjaxResult getCaptchaImage() { + public AjaxResult getCaptchaImage() throws Exception { AjaxResult result = AjaxResult.success(); - // 开发阶段禁用验证码 - result.put("captchaEnabled", false); - result.put("uuid", UUID.randomUUID().toString()); + + String uuid = UUID.randomUUID().toString(); + String code = generateRandomCode(4); + + // 生成验证码图片 + String base64Img = generateCaptchaImage(code); + + result.put("captchaEnabled", true); + result.put("img", base64Img); + result.put("uuid", uuid); + + // 存储验证码到内存(实际应存 Redis,这里简化为静态 Map) + captchaStore.put(uuid, code.toLowerCase()); + return result; } + + // 简易验证码存储(生产环境应使用 Redis) + private static final Map captchaStore = new HashMap<>(); + + /** + * 生成随机验证码 + */ + private String generateRandomCode(int length) { + String chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789"; + Random random = new Random(); + StringBuilder code = new StringBuilder(); + for (int i = 0; i < length; i++) { + code.append(chars.charAt(random.nextInt(chars.length()))); + } + return code.toString(); + } + + /** + * 生成验证码图片 + */ + private String generateCaptchaImage(String code) throws Exception { + int width = 100; + int height = 40; + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + + // 背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, width, height); + + // 绘制字符 + g.setFont(new Font("Arial", Font.BOLD, 25)); + Random random = new Random(); + Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE, Color.MAGENTA}; + + for (int i = 0; i < code.length(); i++) { + g.setColor(colors[random.nextInt(colors.length)]); + g.drawString(String.valueOf(code.charAt(i)), 15 + i * 20, 28); + } + + // 干扰线 + for (int i = 0; i < 3; i++) { + g.setColor(colors[random.nextInt(colors.length)]); + g.drawLine(random.nextInt(width), random.nextInt(height), + random.nextInt(width), random.nextInt(height)); + } + + g.dispose(); + + // 转 Base64 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(image, "png", baos); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } /** * 登录 @@ -31,6 +101,22 @@ public class LoginController { public AjaxResult login(@RequestBody Map loginBody) { String username = loginBody.get("username"); String password = loginBody.get("password"); + String code = loginBody.get("code"); + String uuid = loginBody.get("uuid"); + + // 验证码校验 + if (code == null || uuid == null) { + return AjaxResult.error("验证码不能为空"); + } + String storedCode = captchaStore.get(uuid); + if (storedCode == null) { + return AjaxResult.error("验证码已过期"); + } + if (!storedCode.equals(code.toLowerCase())) { + return AjaxResult.error("验证码错误"); + } + // 验证后移除 + captchaStore.remove(uuid); // 开发阶段简单校验:admin/admin123 if ("admin".equals(username) && "admin123".equals(password)) {