Spring mvc 验证码的做法

2025-10-29 09:40:55

1、第一:前端页面编写

效果图:

Spring mvc 验证码的做法

2、代码:

<form id="loginInputForm" method="post">

<hr/>

用户名:<input type="text" id="accountNumber" name="accountNumber" value="" />

<hr/>

密       码:<input type="password" id="password" name="password" value=""/>

<hr/>

验证码:<input type="text" size="10px"  name="VerificationCode" placeholder="请输入验证码"  id="VerificationCode"/>

      <span  style="padding: 0px;">

<a href="javascript:void(0);" onclick="VerificationCode()"><img id="randCodeImage" src="VerificationCode/generate.action"/></a>

</span>

</form>

Spring mvc 验证码的做法

3、解释:

首先验证码图片是一个img,而它的src肯定是一个动态生成图片的路径,我们可以固定一个专门只为做验证码的方法,这里以VerificationCode/generate.action方法为例,这个方法是生成图片的方法,这样进入这个页面就会有一个初始的图片,当我们点击这个图片的时候就会不停的更换不一样的图片,就是利用异步提交的方式进行,下面是js代码

/**

*验证码刷新

*/

function VerificationCode(){

var rad = Math.floor(Math.random() * Math.pow(10, 8));

//uuuy是随便写的一个参数名称,后端不会做处理,作用是避免浏览器读取缓存的链接

$("#randCodeImage").attr("src", "VerificationCode/generate.action?uuuy="+rad);

}

为什么要在后面加一个随机数?因为如果不加一个随机数,每次不停的访问同一个一模一样的方法的时候,实际上不会去执行这个方法,因为它取得是缓存,所以有时候点击验证码图片刷新图片却不动,就是这个原因,加上验证就会让系统知道你的访问地址发生了变化,就不会取缓存了。

Spring mvc 验证码的做法

4、第二:后端代码编写

代码:

@Controller

@RequestMapping("/VerificationCode")

public class VerificationCodeController extends HttpServlet{

private static final long serialVersionUID = 1L;

/**

 * 这里用作存入session的名称

 */

private static final String SESSION_KEY_OF_RAND_CODE = "randCode"; // 定义一个存入全局变量中的session的名字

    

/**

 * 随机产生干扰线,就是前端页面显示的小点点的个数

 */

private static final int count = 200;

/**

     * 定义图形大小(宽)

     */

    private static final int width = 105;

/**

 * 定义图形大小(高)

 */

private static final int height = 35;

/**

 * 干扰线的长度=1.414*lineWidth

 */

private static final int lineWidth = 1;

@RequestMapping(value = "/generate", method = { RequestMethod.POST,

RequestMethod.GET })

public void VerificationCode( HttpServletRequest request,

HttpServletResponse response) throws ServletException,

IOException {

// 设置页面不缓存

response.setHeader("Pragma", "No-cache");

response.setHeader("Cache-Control", "no-cache");

response.setDateHeader("Expires", 0);

// response.setContentType("image/png");  这个根据项目配置环境自由设置,这个方法中没用到

// 在内存中创建图象

final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

// 获取图形上下文

final Graphics2D graphics = (Graphics2D) image.getGraphics();

// 设定背景颜色

graphics.setColor(Color.WHITE); // ---1.Color.WHITE为白色

graphics.fillRect(0, 0, width, height);//填充衍射

// 设定边框颜色

//graphics.setColor(getRandColor(100, 200)); // ---2.这是以数字型来设置颜色,颜色模式是指使用三种基色:红、绿、蓝,通过三种颜色的调整得出其它各种颜色,这三种基色的值范围为0~255

graphics.drawRect(0, 0, width - 1, height - 1);

final Random random = new Random();

// 随机产生干扰线,使图象中的认证码不易被其它程序探测到

for (int i = 0; i < count; i++) {

graphics.setColor(getRandColor(150, 200)); // ---3.

final int x = random.nextInt(width - lineWidth - 1) + 1; // 保证画在边框之内

final int y = random.nextInt(height - lineWidth - 1) + 1;

final int xl = random.nextInt(lineWidth);

final int yl = random.nextInt(lineWidth);

graphics.drawLine(x, y, x + xl, y + yl);

}

// 取随机产生的认证码(4位数字)

final String resultCode = exctractRandCode();

for (int i = 0; i < resultCode.length(); i++) {

// 将认证码显示到图象中,调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成

// graphics.setColor(new Color(20 + random.nextInt(130), 20 + random

// .nextInt(130), 20 + random.nextInt(130)));

            // 设置字体颜色

graphics.setColor(Color.BLACK);

            // 设置字体样式

//graphics.setFont(new Font("Arial Black", Font.ITALIC, 18));

            graphics.setFont(new Font("Times New Roman", Font.BOLD, 24));

            // 设置字符,字符间距,上边距

            System.out.print(resultCode.charAt(i));

graphics.drawString(String.valueOf(resultCode.charAt(i)), (23 * i) + 8, 26);

}

System.out.println("直接输出:"+resultCode);

// 将认证码存入SESSION

request.getSession().setAttribute(SESSION_KEY_OF_RAND_CODE, resultCode);

// 图象生效

graphics.dispose();

// 输出图象到页面

ImageIO.write(image, "JPEG", response.getOutputStream());  

}

/**

 * @return 随机码

 */

private String exctractRandCode() {

final String randCodeType = ResourceUtil.getRandCodeType();

        int randCodeLength = Integer.parseInt(ResourceUtil.getRandCodeLength());

        if (randCodeType == null) {

return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);

} else {

switch (randCodeType.charAt(0)) {

case '1':

return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);

case '2':

return RandCodeImageEnum.LOWER_CHAR.generateStr(randCodeLength);

case '3':

return RandCodeImageEnum.UPPER_CHAR.generateStr(randCodeLength);

case '4':

return RandCodeImageEnum.LETTER_CHAR.generateStr(randCodeLength);

case '5':

return RandCodeImageEnum.ALL_CHAR.generateStr(randCodeLength);

default:

return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);

}

}

}

/**

 * 描述:根据给定的数字生成不同的颜色

 * @param 这是以数字型来设置颜色,颜色模式是指使用三种基色:红、绿、蓝,通过三种颜色的调整得出其它各种颜色,这三种基色的值范围为0~255

 * @param 这是以数字型来设置颜色,颜色模式是指使用三种基色:红、绿、蓝,通过三种颜色的调整得出其它各种颜色,这三种基色的值范围为0~255

 * @return 描述:返回颜色

 */

private Color getRandColor(int fc, int bc) { // 取得给定范围随机颜色

final Random random = new Random();

if (fc > 255) {

fc = 255;

}

if (bc > 255) {

bc = 255;

}

final int r = fc + random.nextInt(bc - fc);

final int g = fc + random.nextInt(bc - fc);

final int b = fc + random.nextInt(bc - fc);

return new Color(r, g, b);

}

/**

 * 验证码辅助类

 *

 * @author 张国明 guomingzhang2008@gmail.com <br/>

 *         2012-2-28 下午2:15:14

 *

 */

enum RandCodeImageEnum {

/**

 * 混合字符串

 */

ALL_CHAR("0123456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), // 去除小写的l和o这个两个不容易区分的字符;

/**

 * 字符

 */

LETTER_CHAR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),

/**

 * 小写字母

 */

LOWER_CHAR("abcdefghijklmnopqrstuvwxyz"),

/**

 * 数字

 */

NUMBER_CHAR("0123456789"),

/**

 * 大写字符

 */

UPPER_CHAR("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

/**

 * 待生成的字符串

 */

private String charStr;

/**

 * @param charStr

 */

private RandCodeImageEnum(final String charStr) {

this.charStr = charStr;

}

/**

 * 生产随机验证码

 *

 * @param codeLength

 *            验证码的长度

 * @return 验证码

 */

public String generateStr(final int codeLength) {

final StringBuffer sb = new StringBuffer();

final Random random = new Random();

final String sourseStr = getCharStr();

for (int i = 0; i < codeLength; i++) {

sb.append(sourseStr.charAt(random.nextInt(sourseStr.length())));

}

return sb.toString();

}

/**

 * @return the {@link #charStr}

 */

public String getCharStr() {

return charStr;

}

}

}

/**

 * 项目参数工具类

 *

 */

public class ResourceUtil {

private static final ResourceBundle bundle = java.util.ResourceBundle.getBundle("sysConfig");

/**

     * 获取随机码的长度

     *

     * @return 随机码的长度

     */

    public static String getRandCodeLength() {

        return bundle.getString("randCodeLength");

    }

    /**

     * 获取随机码的类型

     *

     * @return 随机码的类型

     */

    public static String getRandCodeType() {

        return bundle.getString("randCodeType");

    }

Spring mvc 验证码的做法

5、解释:

 ResourceUtil这个类是一个工具类,可以把一些公用的配置参数利用这个类进行获取,比如这个类就是获取了sysConfig.properties这个配置里面的值,然后根据这个值动态控制验证码显示几位数,显示纯数字还是数字加字母的类型。

Spring mvc 验证码的做法

6、结尾:

根据上面的方法就可以动态获取验证码了

前面提到把得到的数据存入session的目的是为了前端登入的时候输入的验证码与之前存入session的值做匹配,匹配上了就通过,匹配不对就提示验证码错误,当然提示验证错误后要对验证码进行刷新,在调取一次刷新验证码的方法就可以了。

Spring mvc 验证码的做法

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢