环境:springboot项目
思路:从后台生成图片,然后传输到前台显示,每次生成的验证码存储在session里
借鉴了别人用java生成图片的方法
直接上代码
前端刚加载登录页面时和每次点击图片获取验证码的url接口
/**生成图片验证码*/
@RequestMapping("verifyCode/ImageCode")
@ResponseBody
public JSONObject produceImageCode(HttpSession session) throws IOException {
JSONObject jobj = new JSONObject();
ImageUtil iu = new ImageUtil();
String code = iu.createImageWithVerifyCode(120,30,4,session);
code = "data:image/png;base64,"+code;
jobj.put("png_base64",code);
return jobj;
}
使用到的ImageUtil类的函数,用于生成带验证码的图片
/**生成验证码图片 转 base64 并且保存图片验证码到session里
* @param width 图片宽度
* @param height 图片高度
* @param session session域 用来保存验证码
* @param length 验证码位数
* @return 图片的base64串*/
public String createImageWithVerifyCode(int width, int height, int length,HttpSession session) throws IOException {
String png_base64="";
//绘制内存中的图片
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//得到画图对象
Graphics graphics = bufferedImage.getGraphics();
//绘制图片前指定一个颜色
graphics.setColor(getRandColor(160,200));
graphics.fillRect(0,0,width,height);
//绘制边框
graphics.setColor(Color.white);
graphics.drawRect(0, 0, width - 1, height - 1);
// 步骤四 四个随机数字
Graphics2D graphics2d = (Graphics2D) graphics;
graphics2d.setFont(new Font("宋体", Font.BOLD, 18));
Random random = new Random();
VerifyCodeUtil vcu = new VerifyCodeUtil();
String word = vcu.produceNumAndChar(length);
// 定义x坐标
int x = 10;
for (int i = 0; i < word.length(); i++) {
// 随机颜色
graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
// 旋转 -30 --- 30度
int jiaodu = random.nextInt(60) - 30;
// 换算弧度
double theta = jiaodu * Math.PI / 180;
// 获得字母数字
char c = word.charAt(i);
//将c 输出到图片
graphics2d.rotate(theta, x, 20);
graphics2d.drawString(String.valueOf(c), x, 20);
graphics2d.rotate(-theta, x, 20);
x += 30;
}
//保存验证码
session.setAttribute("img_code",word);
// 绘制干扰线
graphics.setColor(getRandColor(160, 200));
int x1;
int x2;
int y1;
int y2;
for (int i = 0; i < 30; i++) {
x1 = random.nextInt(width);
x2 = random.nextInt(12);
y1 = random.nextInt(height);
y2 = random.nextInt(12);
graphics.drawLine(x1, y1, x1 + x2, x2 + y2);
}
graphics.dispose();// 释放资源
ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
ImageIO.write(bufferedImage, "png", baos);//写入流中
byte[] bytes = baos.toByteArray();//转换成字节
BASE64Encoder encoder = new BASE64Encoder();
png_base64 = encoder.encodeBuffer(bytes).trim();
png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
return png_base64;
}
生成随机的N位数字和字母混合的验证码字符串
这里去掉了字母O和数字0 可以把字母和数字都定义在同一个字符串内
/**生成N位数字和字母混合的验证码
* @param num 验证码位数
* @return code 生成的验证码字符串*/
public String produceNumAndChar(int num){
Random random = new Random();
String code = "";
String ch = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
String n = "123456789";
for(int i=0;i<num;i++){
int flag = random.nextInt(2);
if(flag==0){//数字
code+=n.charAt(random.nextInt(n.length()));
}else{//字母
code+=ch.charAt(random.nextInt(ch.length()));
}
}
return code;
}
前端界面代码和Js代码
<div class="form-group" >
<input type="text" name="img_code" id="img_code" th:value="${img_code}" class="form-control" placeholder="验证码" style="color:gray;float:left;width:180px !important;height:30px !important;" required="required" />
<img id="img" style="float:left;margin-left:20px" onclick="javascript:imgChange()" />
</div>
$(function(){
imgChange();
});
function imgChange(){
$.ajax({
type: "POST",
dataType: "json",
url: "/verifyCode/ImageCode" ,
data:{},
success: function (result) {
$("#img").attr('src',result.png_base64)
},
error : function() {
alert("操作发生异常,请刷新页面后再试!");
}
});
}
注意
//在生成图片的时候,验证码我是保存在了Session里的
//保存验证码
session.setAttribute("img_code",word);
//在登录的时候进行验证码是否正确的判断
if(!img_code.equalsIgnoreCase((String)session.getAttribute("img_code"))){
//.......
}
//取seesion里的验证码的时候,最好捕获下session的异常
//登录成功的话进行session的销毁
try{
session.removeAttribute("img_code");
}catch(Exception e){
//.......
}