Java如何實(shí)現(xiàn)驗(yàn)證碼驗(yàn)證功能呢?日常生活中,驗(yàn)證碼隨處可見,他可以在一定程度上保護(hù)賬號安全,那么他是怎么實(shí)現(xiàn)的呢?
10年積累的成都做網(wǎng)站、網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先建設(shè)網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有撫順縣免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
Java實(shí)現(xiàn)驗(yàn)證碼驗(yàn)證功能其實(shí)非常簡單:用到了一個(gè)Graphics類在畫板上繪制字母,隨機(jī)選取一定數(shù)量的字母隨機(jī)生成,然后在畫板上隨機(jī)生成幾條干擾線。
首先,寫一個(gè)驗(yàn)證碼生成幫助類,用來繪制隨機(jī)字母:
import?java.awt.Color;
import?java.awt.Font;
import?java.awt.Graphics;
import?java.awt.image.BufferedImage;
import?java.io.IOException;
import?java.io.OutputStream;
import?java.util.Random;
import?javax.imageio.ImageIO;
public?final?class?GraphicHelper?{
/**
*?以字符串形式返回生成的驗(yàn)證碼,同時(shí)輸出一個(gè)圖片
*
*?@param?width
*????????????圖片的寬度
*?@param?height
*????????????圖片的高度
*?@param?imgType
*????????????圖片的類型
*?@param?output
*????????????圖片的輸出流(圖片將輸出到這個(gè)流中)
*?@return?返回所生成的驗(yàn)證碼(字符串)
*/
public?static?String?create(final?int?width,?final?int?height,?final?String?imgType,?OutputStream?output)?{
StringBuffer?sb?=?new?StringBuffer();
Random?random?=?new?Random();
BufferedImage?image?=?new?BufferedImage(width,?height,?BufferedImage.TYPE_INT_RGB);
Graphics?graphic?=?image.getGraphics();
graphic.setColor(Color.getColor("F8F8F8"));
graphic.fillRect(0,?0,?width,?height);
Color[]?colors?=?new?Color[]?{?Color.BLUE,?Color.GRAY,?Color.GREEN,?Color.RED,?Color.BLACK,?Color.ORANGE,
Color.CYAN?};
//?在?"畫板"上生成干擾線條?(?50?是線條個(gè)數(shù))
for?(int?i?=?0;?i??50;?i++)?{
graphic.setColor(colors[random.nextInt(colors.length)]);
final?int?x?=?random.nextInt(width);
final?int?y?=?random.nextInt(height);
final?int?w?=?random.nextInt(20);
final?int?h?=?random.nextInt(20);
final?int?signA?=?random.nextBoolean()???1?:?-1;
final?int?signB?=?random.nextBoolean()???1?:?-1;
graphic.drawLine(x,?y,?x?+?w?*?signA,?y?+?h?*?signB);
}
//?在?"畫板"上繪制字母
graphic.setFont(new?Font("Comic?Sans?MS",?Font.BOLD,?30));
for?(int?i?=?0;?i??6;?i++)?{
final?int?temp?=?random.nextInt(26)?+?97;
String?s?=?String.valueOf((char)?temp);
sb.append(s);
graphic.setColor(colors[random.nextInt(colors.length)]);
graphic.drawString(s,?i?*?(width?/?6),?height?-?(height?/?3));
}
graphic.dispose();
try?{
ImageIO.write(image,?imgType,?output);
}?catch?(IOException?e)?{
e.printStackTrace();
}
return?sb.toString();
}
}?
接著,創(chuàng)建一個(gè)servlet,用來固定圖片大小,以及處理驗(yàn)證碼的使用場景,以及捕獲頁面生成的驗(yàn)證碼(捕獲到的二維碼與用戶輸入的驗(yàn)證碼一致才能通過)。
import?java.io.OutputStream;
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(urlPatterns?=?"/verify/regist.do"?)
public?class?VerifyCodeServlet?extends?HttpServlet?{
private?static?final?long?serialVersionUID?=?3398560501558431737L;
@Override
protected?void?service(HttpServletRequest?request,?HttpServletResponse?response)
throws?ServletException,?IOException?{
//?獲得?當(dāng)前請求?對應(yīng)的?會(huì)話對象
HttpSession?session?=?request.getSession();
//?從請求中獲得?URI?(?統(tǒng)一資源標(biāo)識符?)
String?uri?=?request.getRequestURI();
System.out.println("hello?:?"?+?uri);
final?int?width?=?180;?//?圖片寬度
final?int?height?=?40;?//?圖片高度
final?String?imgType?=?"jpeg";?//?指定圖片格式?(不是指MIME類型)
final?OutputStream?output?=?response.getOutputStream();?//?獲得可以向客戶端返回圖片的輸出流
//?(字節(jié)流)
//?創(chuàng)建驗(yàn)證碼圖片并返回圖片上的字符串
String?code?=?GraphicHelper.create(width,?height,?imgType,?output);
System.out.println("驗(yàn)證碼內(nèi)容:?"?+?code);
//?建立?uri?和?相應(yīng)的?驗(yàn)證碼?的關(guān)聯(lián)?(?存儲(chǔ)到當(dāng)前會(huì)話對象的屬性中?)
session.setAttribute(uri,?code);
System.out.println(session.getAttribute(uri));
}
}?
接著寫一個(gè)HTML注冊頁面用來檢驗(yàn)一下:
html
head
meta?charset="UTF-8"
title注冊/title
link?rel="stylesheet"?href="styles/general.css"
link?rel="stylesheet"?href="styles/cell.css"
link?rel="stylesheet"?href="styles/form.css"
script?type="text/javascript"?src="js/ref.js"/script
style?type="text/css"?
.logo-container?{
margin-top:?50px?;
}
.logo-container?img?{
width:?100px?;
}
.message-container?{
height:?80px?;
}
.link-container?{
height:?40px?;
line-height:?40px?;
}
.link-container?a?{
text-decoration:?none?;
}
/style
/head
body
div?class="container?form-container"
form?action="/wendao/regist.do"?method="post"
div?class="form"?!--?注冊表單開始?--
div?class="form-row"
span?class="cell-1"
i?class="fa?fa-user"/i
/span
span?class="cell-11"?style="text-align:?left;"
input?type="text"?name="username"?placeholder="請輸入用戶名"
/span
/div
div?class="form-row"
span?class="cell-1"
i?class="fa?fa-key"/i
/span
span?class="cell-11"?style="text-align:?left;"
input?type="password"?name="password"?placeholder="請輸入密碼"
/span
/div
div?class="form-row"
span?class="cell-1"
i?class="fa?fa-keyboard-o"/i
/span
span?class="cell-11"?style="text-align:?left;"
input?type="password"?name="confirm"?placeholder="請確認(rèn)密碼"
/span
/div
div?class="form-row"
span?class="cell-7"
input?type="text"?name="verifyCode"?placeholder="請輸入驗(yàn)證碼"
/span
span?class="cell-5"?style="text-align:?center;"
img?src="/demo/verify/regist.do"?onclick="myRefersh(this)"
/span
/div
div?class="form-row"?style="border:?none;"
span?class="cell-6"?style="text-align:?left"
input?type="reset"?value="重置"
/span
span?class="cell-6"??style="text-align:right;"
input?type="submit"?value="注冊"
/span
/div
/div?!--?注冊表單結(jié)束?--
/form
/div
/body
/html
效果如下圖:
在控制臺(tái)接收到的圖片中驗(yàn)證碼的變化如下:
當(dāng)點(diǎn)擊刷新頁面的時(shí)候,驗(yàn)證碼也會(huì)隨著變化,但我們看不清驗(yàn)證碼時(shí),只要點(diǎn)擊驗(yàn)證碼就會(huì)刷新,這樣局部的刷新可以用JavaScript來實(shí)現(xiàn)。
在img
src="/demo/verify/regist.do"中,添加一個(gè)問號和一串后綴數(shù)字,當(dāng)刷新時(shí)讓后綴數(shù)字不斷改變,那么形成的驗(yàn)證碼也會(huì)不斷變化,我們可以采用的一種辦法是后綴數(shù)字用date代替,date獲取本機(jī)時(shí)間,時(shí)間是隨時(shí)變的,這樣就保證了刷新驗(yàn)證碼可以隨時(shí)變化。
代碼如下:
function?myRefersh(?e?)?{
const?source?=?e.src?;?//?獲得原來的?src?中的內(nèi)容
//console.log(?"source?:?"?+?source??)?;
var?index?=?source.indexOf(?"?"?)?;??//?從?source?中尋找???第一次出現(xiàn)的位置?(如果不存在則返回?-1?)
//console.log(?"index?:?"?+?index??)?;
if(?index??-1?)?{?//?如果找到了????就進(jìn)入內(nèi)部
var?s?=?source.substring(?0?,?index?)?;?//?從?source?中截取?index?之前的內(nèi)容?(?index?以及?index?之后的內(nèi)容都被舍棄?)
//console.log(?"s?:?"?+?s??)?;
var?date?=?new?Date();?//?創(chuàng)建一個(gè)?Date?對象的?一個(gè)?實(shí)例
var?time?=?date.getTime()?;?//?從?新創(chuàng)建的?Date?對象的實(shí)例中獲得該時(shí)間對應(yīng)毫秒值
e.src?=?s?+?"?time="?+?time?;?//?將?加了?尾巴?的?地址?重新放入到?src?上
//console.log(?e.src?)?;
}?else?{
var?date?=?new?Date();
e.src?=?source?+?"?time="?+?date.getTime();
}
}
如回答不詳細(xì)可追問
script type="text/javascript" src="../js/jquery-1.4.1.min.js"/script
script type="text/javascript" src="../js/jquery.validate.min.js"/script
script type="text/javascript"
$(function(){
$("#f").validate({
rules:{
email:{
required:true,
email:true
},
nickname:{
required:true,
minlength:4,
maxlength:20
},
password:{
required:true,
minlength:6,
maxlength:20
},
password1:{
required:true,
equalTo:"#txtPassword"
},
number:{
required:true,
remote:"checkCode.action" }
},
messages:{
email:{
required:"登錄名必須填寫",
email:"請?zhí)顚懻_的Email格式"
},
nickname:{
required:"昵稱必須填寫",
minlength:"昵稱長度不得小于4位",
maxlength:"昵稱長度不得超過20位"
},
password:{
required:"密碼必須填寫",
minlength:"密碼長度不得小于6位",
maxlength:"密碼長度不得超過20位"
},
password1:{
required:"請輸入密碼驗(yàn)證",
equalTo:"必須與上面密碼相同"
},
number:{
required:"驗(yàn)證碼必須填寫",
remote:"驗(yàn)證碼輸入錯(cuò)誤"
}
}
});
});
/script
這是用jquery的一個(gè)jquery.validate.min.js插件寫的 其實(shí)可以用js完成
ajaxurl : "manageAction!checkAccount.action?account="+$("#account").val();這樣寫就可以了應(yīng)該。