Java生成随机验证码图片

一、页面准备

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>管理员登录</title>
    <link rel="stylesheet" href="http://culturestore.oss-cn-shanghai.aliyuncs.com/normalize/normalize.css">
    <link href="${basePath }/static/admin/css/dockingLogin.css" rel="stylesheet">
    <script type="text/javascript" src="${basePath }/static/easyui/jquery.min.js" ></script>
    <script type="text/javascript" src="${basePath }/static/common/js/jQuery.md5.js"></script>
    <script type="text/javascript" src="${basePath }/static/common/js/base64code.js"></script>

    <script type="text/javascript">

        function befSubmit(){
            var pwd = $("#pwd").val();
            pwd = $.md(pwd);
            var pwdmd5 = $.md5(pwd);
            $("#pwd").val(pwdmd5);

        }

        $(function(){
            var topURI = window.parent.location;
            var nowURI = window.location;
            if (topURI != nowURI){
                window.parent.location.reload();
            }
        });

        function myReload() {
            document.getElementById("CreateCheckCode").src =
                document.getElementById("CreateCheckCode").src+ "?nocache=" + new Date().getTime();
        }
    </script>

</head>
<body class="loginBg">
<form  action="${basePath}/admin/doLogin" method="post" onsubmit="return befSubmit()">
<div class="sjdj-login-bg">
    <div class="sjdj-login-main">
        <div class="sjdj-login-tit">
            <div class="wen-1">欢迎登录</div>
            <div class="wen-2">数据对接管理</div>
        </div>
        <div class="sjdj-login-wrap">
            <img class="tit-img" src="http://culturecloud.img-cn-hangzhou.aliyuncs.com/wangxiaosong/image/2020923142928JWMjOgv1v10uxFefUs43KfvA1WXDp1.png">
            <input class="txtInp" type="hidden" name="channel"  value="1"/>
            <div class="qItem clearfix">
                <input class="txtInp" type="text" placeholder="User ID" name="username">
            </div>
            <div class="qItem clearfix">
                <input class="txtInp" type="password" placeholder="Password" name="password" id="pwd">
            </div>
            <div class="qItem clearfix">
                <input class="txtInp yzmInp" type="text" placeholder="验证码" name="checkCode">
                <div class="yzmBox"><img src="${basePath }/pictureCheckCode" id="CreateCheckCode" onclick="myReload()"></div>
            </div>
            <button class="q-btn" type="submit">登 录</button>
        </div>
    </div>
</div>
</form>
</body>
</html>

二、后台画好图片以流的形式响应到页面

package com.creatoo.hn.web.servlet;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *验证码生成与更新
 */
@WebServlet("/pictureCheckCode")
public class PictureCheckCode extends HttpServlet {

    private static final long serialVersionUID = 1L;


    /* 该方法主要作用是获得随机生成的颜色 */
    public Color getRandColor(int s, int e) {
        Random random = new Random();
        if (s > 255)
            s = 255;
        if (e > 255)
            e = 255;
        int r, g, b;
        r = s + random.nextInt(e - s); // 随机生成RGB颜色中的r值
        g = s + random.nextInt(e - s); // 随机生成RGB颜色中的g值
        b = s + random.nextInt(e - s); // 随机生成RGB颜色中的b值
        return new Color(r, g, b);
    }

    private Random r = new Random();

    // 随机字符集合中不包括0和o,O,1和l,因为这些不易区分
    private String codes = "23456789abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYXZ";
    private char randomChar() {
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        // 设置不缓存图片
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "No-cache");
        response.setDateHeader("Expires", 0);

        // 指定生成的响应图片,一定不能缺少这句话,否则错误.
        response.setContentType("image/jpeg");
        int width = 80, height = 35; // 指定生成验证码的宽度和高度
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 创建BufferedImage对象,其作用相当于一图片
        Graphics g = image.getGraphics(); // 创建Graphics对象,其作用相当于画笔
        Graphics2D g2d = (Graphics2D) g; // 创建Grapchics2D对象

        Random random = new Random();
        Font mfont = new Font("楷体", Font.BOLD, 25); // 定义字体样式
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height); // 绘制背景
        g.setFont(mfont); // 设置字体
        g.setColor(getRandColor(180, 200));

        // 绘制100条颜色和位置全部为随机产生的线条,该线条为2f
        for (int i = 0; i < 100; i++) {
            int x = random.nextInt(width - 1);
            int y = random.nextInt(height - 1);
            int x1 = random.nextInt(6) + 1;
            int y1 = random.nextInt(12) + 1;
            BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL); // 定制线条样式
            Line2D line = new Line2D.Double(x, y, x + x1, y + y1);
            g2d.setStroke(bs);
            g2d.draw(line); // 绘制直线
        }


        //用来保存验证码字符串文本内容
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 4; ++i) {// 随机生成4个字符
            String sTemp = String.valueOf(randomChar());
            sb.append(sTemp);

            Color color = new Color(20 + random.nextInt(110), 20 + random.nextInt(110), random.nextInt(110));
            g.setColor(color);
            // 将生成的随机数进行随机缩放并旋转制定角度 PS.建议不要对文字进行缩放与旋转,因为这样图片可能不正常显示

            /* 将文字旋转制定角度 */
            Graphics2D g2d_word = (Graphics2D) g;
            AffineTransform trans = new AffineTransform();
            trans.rotate((45) * 3.14 / 180, 15 * i + 8, 7);

            /* 缩放文字 */
            float scaleSize = random.nextFloat() + 0.8f;
            if (scaleSize > 1f)
                scaleSize = 1f;
            trans.scale(scaleSize, scaleSize);
            g2d_word.setTransform(trans);
            g.drawString(sTemp, 15 * i + 18, 14);
        }

        HttpSession session = request.getSession(true);
        //把验证码放到Session域中
        session.setAttribute("randCheckCode", sb.toString());
        System.out.println("sRand="+sb.toString());
        g.dispose(); // 释放g所占用的系统资源
        ImageIO.write(image, "JPEG", response.getOutputStream()); // 输出图片
    }

}

三、后台校验

//检查验证码            
if("".equals(checkCode) || !checkCode.equalsIgnoreCase((String) session.getAttribute("randCheckCode"))){
      opsForValue.increment("SHIRO_LOGIN_COUNT"+username, 1);
      int count=Integer.parseInt(opsForValue.get("SHIRO_LOGIN_COUNT"+username));
      if(count==1) {
          stringRedisTemplate.expire("SHIRO_LOGIN_COUNT" + username, 10, TimeUnit.MINUTES);
      }
      //计数大于5时,设置用户被锁定一小时
      if(Integer.parseInt(opsForValue.get("SHIRO_LOGIN_COUNT"+username))>=5){
          opsForValue.set("SHIRO_IS_LOCK"+username, "LOCK");
          stringRedisTemplate.expire("SHIRO_IS_LOCK"+username, 1, TimeUnit.HOURS);
      }

      view.addObject("msg", "验证码错误!");
      if(count>=3 && count<5){
          view.addObject("msg", "您已经登录失败"+count+"次,失败5次账号将被锁定1小时!");
      }else if(count==5){
          view.addObject("msg", "您的账号已经被锁定,请1小时后再操作!");
      }
      view.setViewName("admin/login");
      return view;
  }

四、效果图

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值