java springmvc实现验证码功能
作者:qq_35572020 发布时间:2022-09-07 12:12:41
标签:java,springmvc,验证码
本文实例为大家分享了springmvc实现验证码功能展示的具体代码,供大家参考,具体内容如下
先看效果图:
思路:
首先验证码是一张图片,是一张有着随机字母、数字、图案等组成的图片,所以这图片肯定不是固定不变的,肯定是由后端随机制造出来的,前端用img的src去不断访问这个制造的方法。
第一步:前端页面编写
登录使用的是ajax方法,所以使用的是调用点击事件进行,验证码的图片放在a标签中是为了方便点击变换验证码。显示图片用的是img的src属性,因为使用的是spingmvc所以调用后台方法使用action的方式。
<form>
<div id="login_tip">
管理员登录
</div>
<div><input type="text" id="user_code" name="user_code" class="username" placeholder="请输入账号"></div>
<div><input type="password" id="user_account" name="user_account" class="pwd" placeholder="请输入密码"></div>
<div id="btn_area">
<input type="text" id="VerificationCode" name="VerificationCode" placeholder="请输入验证码" class="verify">
<a href="javascript:void(0);" rel="external nofollow" onclick="VerificationCode()">
<img id="randCodeImage" alt="验证码" src="VerificationCode/generate.action" width="100" height="40"/>
</a>
</div>
<div style="float:left;">
<input type="button" name="button" id="sub_btn" onclick="login()" value="登录"/>
</div>
<div id="verification_Code"><b></b></div>
</form>
第二步:编写JS代码
因为登录采用的是ajxa,所以后台登录会验证一些数据,不正确的会返回数据到登录页面。这里说明一下,在调用生成验证码的方法后面为什么要加一个随机数,这里的随机数以及这个随机数的参数名称可以随意写,后端不做任何操作的,这里是防止浏览器对一个相同方法进行调用时取缓存的方法,而点击图片或验证码输入错误不会自动刷新而改变图片的问题做处理。
<script type="text/javascript">
function login(){
//这是使用ajax的方式提交
$.ajax({
type:'post',
url:'Uase/query.action',
//data:$('#loginInputForm').serialize(),
data:{
'user_code' : $("#user_code").val(),
'user_account' :$("#user_account").val(),
'VerificationCode':$("#VerificationCode").val(),
},
dataType:'json',
success:function(obj){
var rad = Math.floor(Math.random() * Math.pow(10, 8));
if(obj && obj.success=='true'){
window.location.href='Uase/login.action';
}else{
document.getElementById("verification_Code"). innerHTML =obj.msg;
//uuuy是随便写的一个参数名称,后端不会做处理,作用是避免浏览器读取缓存的链接
$("#randCodeImage").attr("src", "VerificationCode/generate.action?uuuy="+rad);
$("#VerificationCode").val("").focus(); // 清空并获得焦点
}
}
});
}
/**
*验证码刷新
*/
function VerificationCode(){
var rad = Math.floor(Math.random() * Math.pow(10, 8));
//uuuy是随便写的一个参数名称,后端不会做处理,作用是避免浏览器读取缓存的链接
$("#randCodeImage").attr("src", "VerificationCode/generate.action?uuuy="+rad);
}
</script>
第三步:编写后台Controller控制类
主方法为VerificationCode,里面会用到一些随机数生产的方法以及一些辅助类,全用用上就可以了,因为我这里用到了可以更改类型的验证码,所以用到了一个自己编写的公共的工具类。
@RequestMapping("/VerificationCode")
public class VerificationCodeController extends HttpServlet{
private static final long serialVersionUID = 1L;
/**
* 这里用作存入session的名称
*/
private static final String SESSION_KEY_OF_RAND_CODE = "randCode"; // todo 要统一常量
/**
*
*/
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);
}
/**
* 验证码辅助类
*/
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");
}
}
第五步:配置sysConfig.properties
randCodeLength=4
randCodeType=5
第六步:到这里就大功告成了,可以试试效果了
来源:http://blog.csdn.net/qq_35572020/article/details/53033203


猜你喜欢
- 数学原理:  
- 本文实例讲述了Java实现的双向匹配分词算法。分享给大家供大家参考,具体如下:目前比较流行的几大分词算法有:基于字符串匹配的分词方法、基于理
- 这两天看阿里的JAVA开发手册,到多线程的时候说永远不要用 new Thread()这种方式来使用多线程。确实是这样的,我一直在用线程池,到
- 程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 完整列表如下:1. android.permi
- 本文介绍了详解Maven * Nexus的安装与使用,分享给大家,具体如下:1.安装1.1 安装docker并加速yum update &am
- 使用到的类:net.sf.json.JSONObject 使用JSON时,除了要导入JSON网站上面下载的json-lib-2.2
- 影响排序效率的一般从3个方面比较:数据比较的次数,数据移动的次数,内存空间占用的大小。我们就冒泡排序、选择排序、插入排序、快速排序做一个总的
- 今天工作中遇到一个需求,就是获取 excel 里面的内容,并且把 excel 另存为 csv,因为本人以前未接触过,所以下面整理出来的代码均
- IntelliJ IDEA最佳配置IntelliJ IDEA 分为两个版本:旗舰版(Ultimate)和社区版(Community)。旗舰版
- 常用:System:根空间,包含一些基本的类库 System.Collections:主要是和集合类相关的类库 System.Collect
- 本文是Neward & Associates的总裁Ted Neward为developerworks独家撰稿“你不知道5个……”系列
- 1.生成自己的注解(为了确定在哪些位置使用)/** * 关闭patch delete的model处理,否则会报错 */@Target({El
- 最近在用SpringMvc写项目的时候,遇到一个问题,就是方法的鉴权问题,这个问题弄了一天了终于解决了,下面看下解决方法项目需求:需要鉴权的
- 本文实例讲述了C#读写INI文件的方法。分享给大家供大家参考。具体如下:虽然微软早已经建议在WINDOWS中用注册表代替INI文件,但是在实
- 本文实例为大家分享了SpringBoot Http远程调用的具体代码,供大家参考,具体内容如下一、在实现远程调用时可以使用feign与htt
- 前言今天从github把我以前写的一个小demo下载下来了,第一次下载项目,摸索了一个多小时,才运行起来。下载有两种方法,通过git下载,或
- 本文实例为大家分享了Android Glide图片加载的具体代码,供大家参考,具体内容如下1.普通用法Glide.with(context)
- 平时项目中只要涉及表,那么一定能接触到众多各式各样的ID编号,博主整理一些常用的ID格式,整合一个ID生成工具类,供大家参考,如果有什么不足
- 概述ZXing 是一个开源 Java 类库用于解析多种格式的 1D/2D 条形码。目标是能够对QR编码、Data Matrix、UPC的1D
- 一、在学习枚举之前,首先来听听枚举的优点。1、枚举能够使代码更加清晰,它允许使用描述性的名称表示整数值。2、枚举使代码更易于维护,有助于确保