java springmvc實(shí)現(xiàn)驗(yàn)證碼功能
本文實(shí)例為大家分享了springmvc實(shí)現(xiàn)驗(yàn)證碼功能展示的具體代碼,供大家參考,具體內(nèi)容如下
先看效果圖:

思路:
首先驗(yàn)證碼是一張圖片,是一張有著隨機(jī)字母、數(shù)字、圖案等組成的圖片,所以這圖片肯定不是固定不變的,肯定是由后端隨機(jī)制造出來的,前端用img的src去不斷訪問這個(gè)制造的方法。
第一步:前端頁面編寫
登錄使用的是ajax方法,所以使用的是調(diào)用點(diǎn)擊事件進(jìn)行,驗(yàn)證碼的圖片放在a標(biāo)簽中是為了方便點(diǎn)擊變換驗(yàn)證碼。顯示圖片用的是img的src屬性,因?yàn)槭褂玫氖莝pingmvc所以調(diào)用后臺(tái)方法使用action的方式。
<form>
<div id="login_tip">
管理員登錄
</div>
<div><input type="text" id="user_code" name="user_code" class="username" placeholder="請(qǐng)輸入賬號(hào)"></div>
<div><input type="password" id="user_account" name="user_account" class="pwd" placeholder="請(qǐng)輸入密碼"></div>
<div id="btn_area">
<input type="text" id="VerificationCode" name="VerificationCode" placeholder="請(qǐng)輸入驗(yàn)證碼" class="verify">
<a href="javascript:void(0);" rel="external nofollow" onclick="VerificationCode()">
<img id="randCodeImage" alt="驗(yàn)證碼" 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代碼
因?yàn)榈卿洸捎玫氖莂jxa,所以后臺(tái)登錄會(huì)驗(yàn)證一些數(shù)據(jù),不正確的會(huì)返回?cái)?shù)據(jù)到登錄頁面。這里說明一下,在調(diào)用生成驗(yàn)證碼的方法后面為什么要加一個(gè)隨機(jī)數(shù),這里的隨機(jī)數(shù)以及這個(gè)隨機(jī)數(shù)的參數(shù)名稱可以隨意寫,后端不做任何操作的,這里是防止瀏覽器對(duì)一個(gè)相同方法進(jìn)行調(diào)用時(shí)取緩存的方法,而點(diǎn)擊圖片或驗(yàn)證碼輸入錯(cuò)誤不會(huì)自動(dòng)刷新而改變圖片的問題做處理。
<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是隨便寫的一個(gè)參數(shù)名稱,后端不會(huì)做處理,作用是避免瀏覽器讀取緩存的鏈接
$("#randCodeImage").attr("src", "VerificationCode/generate.action?uuuy="+rad);
$("#VerificationCode").val("").focus(); // 清空并獲得焦點(diǎn)
}
}
});
}
/**
*驗(yàn)證碼刷新
*/
function VerificationCode(){
var rad = Math.floor(Math.random() * Math.pow(10, 8));
//uuuy是隨便寫的一個(gè)參數(shù)名稱,后端不會(huì)做處理,作用是避免瀏覽器讀取緩存的鏈接
$("#randCodeImage").attr("src", "VerificationCode/generate.action?uuuy="+rad);
}
</script>
第三步:編寫后臺(tái)Controller控制類
主方法為VerificationCode,里面會(huì)用到一些隨機(jī)數(shù)生產(chǎn)的方法以及一些輔助類,全用用上就可以了,因?yàn)槲疫@里用到了可以更改類型的驗(yàn)證碼,所以用到了一個(gè)自己編寫的公共的工具類。
@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 要統(tǒng)一常量
/**
*
*/
private static final int count = 200;
/**
* 定義圖形大小(寬)
*/
private static final int width = 105;
/**
* 定義圖形大小(高)
*/
private static final int height = 35;
/**
* 干擾線的長(zhǎng)度=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 {
// 設(shè)置頁面不緩存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// response.setContentType("image/png");
// 在內(nèi)存中創(chuàng)建圖象
final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 獲取圖形上下文
final Graphics2D graphics = (Graphics2D) image.getGraphics();
// 設(shè)定背景顏色
graphics.setColor(Color.WHITE); // ---1.Color.WHITE為白色
graphics.fillRect(0, 0, width, height);//填充衍射
// 設(shè)定邊框顏色
//graphics.setColor(getRandColor(100, 200)); // ---2.這是以數(shù)字型來設(shè)置顏色,顏色模式是指使用三種基色:紅、綠、藍(lán),通過三種顏色的調(diào)整得出其它各種顏色,這三種基色的值范圍為0~255
graphics.drawRect(0, 0, width - 1, height - 1);
final Random random = new Random();
// 隨機(jī)產(chǎn)生干擾線,使圖象中的認(rèn)證碼不易被其它程序探測(cè)到
for (int i = 0; i < count; i++) {
graphics.setColor(getRandColor(150, 200)); // ---3.
final int x = random.nextInt(width - lineWidth - 1) + 1; // 保證畫在邊框之內(nèi)
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);
}
// 取隨機(jī)產(chǎn)生的認(rèn)證碼(4位數(shù)字)
final String resultCode = exctractRandCode();
for (int i = 0; i < resultCode.length(); i++) {
// 將認(rèn)證碼顯示到圖象中,調(diào)用函數(shù)出來的顏色相同,可能是因?yàn)榉N子太接近,所以只能直接生成
// graphics.setColor(new Color(20 + random.nextInt(130), 20 + random
// .nextInt(130), 20 + random.nextInt(130)));
// 設(shè)置字體顏色
graphics.setColor(Color.BLACK);
// 設(shè)置字體樣式
//graphics.setFont(new Font("Arial Black", Font.ITALIC, 18));
graphics.setFont(new Font("Times New Roman", Font.BOLD, 24));
// 設(shè)置字符,字符間距,上邊距
System.out.print(resultCode.charAt(i));
graphics.drawString(String.valueOf(resultCode.charAt(i)), (23 * i) + 8, 26);
}
System.out.println("直接輸出:"+resultCode);
// 將認(rèn)證碼存入SESSION
request.getSession().setAttribute(SESSION_KEY_OF_RAND_CODE, resultCode);
// 圖象生效
graphics.dispose();
// 輸出圖象到頁面
ImageIO.write(image, "JPEG", response.getOutputStream());
}
/**
* @return 隨機(jī)碼
*/
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);
}
}
}
/**
* 描述:根據(jù)給定的數(shù)字生成不同的顏色
* @param 這是以數(shù)字型來設(shè)置顏色,顏色模式是指使用三種基色:紅、綠、藍(lán),通過三種顏色的調(diào)整得出其它各種顏色,這三種基色的值范圍為0~255
* @param 這是以數(shù)字型來設(shè)置顏色,顏色模式是指使用三種基色:紅、綠、藍(lán),通過三種顏色的調(diào)整得出其它各種顏色,這三種基色的值范圍為0~255
* @return 描述:返回顏色
*/
private Color getRandColor(int fc, int bc) { // 取得給定范圍隨機(jī)顏色
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);
}
/**
* 驗(yàn)證碼輔助類
*/
enum RandCodeImageEnum {
/**
* 混合字符串
*/
ALL_CHAR("0123456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), // 去除小寫的l和o這個(gè)兩個(gè)不容易區(qū)分的字符;
/**
* 字符
*/
LETTER_CHAR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
/**
* 小寫字母
*/
LOWER_CHAR("abcdefghijklmnopqrstuvwxyz"),
/**
* 數(shù)字
*/
NUMBER_CHAR("0123456789"),
/**
* 大寫字符
*/
UPPER_CHAR("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
/**
* 待生成的字符串
*/
private String charStr;
/**
* @param charStr
*/
private RandCodeImageEnum(final String charStr) {
this.charStr = charStr;
}
/**
* 生產(chǎn)隨機(jī)驗(yàn)證碼
*
* @param codeLength
* 驗(yàn)證碼的長(zhǎng)度
* @return 驗(yàn)證碼
*/
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;
}
}
}
第四步:編寫公用的工具類
/**
* 項(xiàng)目參數(shù)工具類
*
*/
public class ResourceUtil {
private static final ResourceBundle bundle = java.util.ResourceBundle.getBundle("sysConfig");
/**
* 獲取隨機(jī)碼的長(zhǎng)度
*
* @return 隨機(jī)碼的長(zhǎng)度
*/
public static String getRandCodeLength() {
return bundle.getString("randCodeLength");
}
/**
* 獲取隨機(jī)碼的類型
*
* @return 隨機(jī)碼的類型
*/
public static String getRandCodeType() {
return bundle.getString("randCodeType");
}
}
第五步:配置sysConfig.properties
randCodeLength=4 randCodeType=5
第六步:到這里就大功告成了,可以試試效果了
相關(guān)文章
Spring?Boot實(shí)現(xiàn)文件上傳的兩種方式總結(jié)
應(yīng)用開發(fā)過程中,文件上傳是一個(gè)基礎(chǔ)的擴(kuò)展功能,它的目的就是讓大家共享我們上傳的文件資源,下面這篇文章主要給大家總結(jié)介紹了關(guān)于Spring?Boot實(shí)現(xiàn)文件上傳的兩種方式,需要的朋友可以參考下2023-05-05
Spring Bean三級(jí)緩存機(jī)制的技術(shù)指南
在 Spring 框架中,Bean 的創(chuàng)建和管理是容器的核心功能之一,了提高性能,Spring 采用了多級(jí)緩存機(jī)制來減少不必要的對(duì)象創(chuàng)建和配置,本文將詳細(xì)介紹 Spring 中 Bean 三級(jí)緩存的實(shí)現(xiàn)原理,并通過代碼示例幫助你理解這個(gè)機(jī)制的工作方式,需要的朋友可以參考下2025-04-04
詳解Java8?CompletableFuture的并行處理用法
Java8中有一個(gè)工具非常有用,那就是CompletableFuture,本章主要講解CompletableFuture的并行處理用法,感興趣的小伙伴可以了解一下2022-04-04
SpringBoot如何實(shí)現(xiàn)Tomcat自動(dòng)配置
這篇文章主要介紹了SpringBoot如何實(shí)現(xiàn)Tomcat自動(dòng)配置,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot框架,感興趣的朋友可以了解下2021-03-03
如何使用Idea搭建全注解式開發(fā)的SpringMVC項(xiàng)目
這篇文章主要介紹了如何使用Idea搭建全注解式開發(fā)的SpringMVC項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
java跳出多重循環(huán)的三種實(shí)現(xiàn)方式
文章主要介紹了Java中跳出多重循環(huán)的三種方式:使用`break`配合標(biāo)簽、在布爾表達(dá)式中添加判斷變量、以及使用`try-catch`制造異常,每種方式都有具體的代碼示例,并輸出了相應(yīng)的執(zhí)行結(jié)果2025-01-01
Java開發(fā)環(huán)境配置JDK超詳細(xì)整理(適合新手入門)
這篇文章主要給大家介紹了關(guān)于Java開發(fā)環(huán)境配置JDK超詳細(xì)整理的相關(guān)資料,非常適合新手入門,JDK是Java語言的軟件開發(fā)工具包,主要用于移動(dòng)設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序,需要的朋友可以參考下2023-11-11

