Java实现Base64格式验证码
实现登录验证码一般分为两种方式:前端实现和后端实现。前端实现由于安全性考虑,就不采用那种方式了。本文主要讲述如何以后端方式生成验证码供前端调用并加以验证。
一、创建验证码服务
/**
* @description: VerifyCodeService
* @author: zero
* @date: 2021/7/1 9:39
*/
@Service
@Slf4j
public class CaptchaService {
/**
* 宋体、新宋体、黑体、楷体、隶书
*/
private static final String[] FONT_TYPES = { "\u5b8b\u4f53", "\u65b0\u5b8b\u4f53",
"\u9ed1\u4f53", "\u6977\u4f53", "\u96b6\u4e66" };
private static final int VALIDATE_CODE_LENGTH = 4;
/**
* 设置背景颜色及大小,干扰线
*
* @param graphics graphics
* @param width width
* @param height height
*/
private static void fillBackground(Graphics graphics, int width, int height) {
// 填充背景
graphics.setColor(Color.WHITE);
//设置矩形坐标x y 为0
graphics.fillRect(0, 0, width, height);
// 加入干扰线条
for (int i = 0; i < 8; i++) {
//设置随机颜色算法参数
graphics.setColor(RandomUtil.randomColor(40, 150));
Random random = new Random();
int x = random.nextInt(width);
int y = random.nextInt(height);
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
graphics.drawLine(x, y, x1, y1);
}
}
/**
* 生成随机字符
* @param width width
* @param height height
* @param os os
* @return String
* @throws IOException IOException
*/
public String generate(int width, int height, OutputStream os) throws IOException {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
fillBackground(graphics, width, height);
String randomStr = RandomUtil.randomString(VALIDATE_CODE_LENGTH);
createCharacter(graphics, randomStr);
graphics.dispose();
//设置JPEG格式
ImageIO.write(image, "JPEG", os);
return randomStr;
}
/**
* 验证码生成
*
* @param width width
* @param height height
* @return VerifyCode
*/
public Captcha generate(int width, int height) {
Captcha captcha = null;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
String code = generate(width, height, baos);
captcha = new Captcha();
captcha.setCode(code);
captcha.setImgBytes(baos.toByteArray());
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return captcha;
}
/**
* 设置字符颜色大小
*
* @param g g
* @param randomStr randomStr
*/
private void createCharacter(Graphics g, String randomStr) {
char[] charArray = randomStr.toCharArray();
for (int i = 0; i < charArray.length; i++) {
//设置RGB颜色算法参数
g.setColor(new Color(50 + RandomUtil.nextInt(100),
50 + RandomUtil.nextInt(100), 50 + RandomUtil.nextInt(100)));
//设置字体大小,类型
g.setFont(new Font(FONT_TYPES[RandomUtil.nextInt(FONT_TYPES.length)], Font.BOLD, 26));
//设置x y 坐标
g.drawString(String.valueOf(charArray[i]), 15 * i + 5, 19 + RandomUtil.nextInt(8));
}
}
}
二、创建验证码接口
/**
* @description: LoginController
* @author: zero
* @date: 2021/4/19 15:45
*/
@Slf4j
@RestController
public class LoginController extends BaseController {
@Autowired
private LoginService loginService;
@Autowired
private CaptchaService captchaService;
/**
* 登录接口
* @param username username
* @param password password
* @param verifyCode verifyCode
* @return CommonResult<Object>
*/
@Log(module = "权限管理", description = "登录")
@GetMapping("/login")
public CommonResult<Object> login(String username, String password, String verifyCode, HttpServletRequest request) {
// 先校验验证码是否正确
String captcha = request.getSession().getAttribute("captcha").toString();
if (StringUtils.equalsIgnoreCase(verifyCode,captcha)) {
Map<String, String> data = new HashMap<>(1);
String ipAddr = IpUtil.getIpAddr(request);
String token = loginService.login(username, password, ipAddr);
if (StringUtils.isEmpty(token)) {
return fail("login failed.");
}
data.put("token", token);
return success(data);
} else {
return fail("验证码错误!");
}
}
@GetMapping("/captcha")
public CommonResult<Object> getVerifyCode(int width, int height, HttpServletRequest request, HttpServletResponse response) {
Captcha captcha = captchaService.generate(width, height);
String code = captcha.getCode();
Base64.Encoder encoder = Base64.getEncoder();
String image = encoder.encodeToString(captcha.getImgBytes());
log.info("获取到的验证码为:{}", code);
String result = "data:image/png;base64,"+image;
request.getSession().setAttribute("captcha", code);
return success(result);
}
}
三、前端验证
<template>
<el-form-item prop="verifyCode" class="form-item-bg verifyCodeItem">
<!-- <span class="svg-container">
<svg-icon icon-class="user" />
</span> -->
<el-input
v-model="loginForm.verifyCode"
placeholder="输入验证码"
type="text"
/>
<img :src="captchaUrl" @click="getCaptcha" style="height:25px;margin-right:5px; " />
</el-form-item>
</template>
<script>
export default {
methods: {
getCaptcha(){
captcha({
width:80,
height:26
}).then( res =>{
if(res.code==='0'){
this.captchaUrl = res.data
}
})
}
}
}
</script>
效果如下:
文中后端代码核心参考:https://blog.csdn.net/pengjunlee/article/details/102896114