Java Web開發(fā)過程中登陸模塊的驗(yàn)證碼的實(shí)現(xiàn)方式總結(jié)
驗(yàn)證碼及它的作用
驗(yàn)證碼為全自動區(qū)分計算機(jī)和人類的圖靈測試的縮寫,是一種區(qū)分用戶是計算機(jī)的公共全自動程序,這個問題可以由計算機(jī)生成并評判,但是必須只有人類才能解答.可以防止惡意破解密碼、刷票、論壇灌水、有效防止某個黑客對某一個特定注冊用戶用特定程序暴力破解方式進(jìn)行不斷的登錄。
圖文驗(yàn)證碼的原理
在servlet中隨機(jī)生成一個指定位置的驗(yàn)證碼,一般為四位,然后把該驗(yàn)證碼保存到session中.在通過Java的繪圖類以圖片的形式輸出該驗(yàn)證碼。為了增加驗(yàn)證碼的安全級別,可以輸出圖片的同時輸出干擾線,最后在用戶提交數(shù)據(jù)的時候,在服務(wù)器端將用戶提交的驗(yàn)證碼和Session保存的驗(yàn)證碼進(jìn)行比較。
實(shí)現(xiàn)方式總結(jié)
1 驗(yàn)證碼生成類RandomCode
RandomCode是一個生成驗(yàn)證碼的工具類,支持英文和數(shù)字驗(yàn)證碼,驗(yàn)證碼包括英文大小寫和數(shù)組,其中英文i、o和數(shù)字0、1因?yàn)槿菀桩a(chǎn)生混淆,不包括在生成驗(yàn)證碼中。RandomCode支持輸出jpg/bmp/png/gif圖片格式的驗(yàn)證碼。
/**
* RandomCode驗(yàn)證碼可以通過靜態(tài)方法和實(shí)例方法生成。
*
* 靜態(tài)方法:
*
* //生成長度為4的隨機(jī)驗(yàn)證碼
* String code = RandomCode.randomString(4);
*
* //把驗(yàn)證碼圖片輸入到response輸出流中
* //圖片格式j(luò)pg
* OutputStream os = response.getOutputStream();
* RandomCode.write(code, 120, 30, os, "jpg");
*
* 實(shí)例方法:
*
* //實(shí)例化驗(yàn)證碼類
* RandomCode rc = new RandomCode(4);
*
* //把驗(yàn)證碼圖片輸入到response輸出流中
* //圖片格式j(luò)pg
* OutputStream os = response.getOutputStream();
* rc.write(120, 30, os, "jpg");
*
* //獲取驗(yàn)證碼字符串
* String code = rc.getCode();
*
*/
public class RandomCode {
/**
* 隨機(jī)驗(yàn)證碼字符
*/
private static String base = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
/**
* 隨機(jī)驗(yàn)證碼長度
*/
private int length = 4;
/**
* 驗(yàn)證碼字符串
*/
private String code;
/**
* 4位隨機(jī)驗(yàn)證碼
*/
public RandomCode(){
this.code = RandomCode.randomString(this.length);
}
public RandomCode(int length){
if(length > 0){
this.length = length;
}
this.code = RandomCode.randomString(this.length);
}
/**
* 生成驗(yàn)證碼圖片
* @param width 圖片寬度
* @param height 圖片高度
* @return
*/
public BufferedImage toImage(int width, int height){
return RandomCode.toImage(this.code, width, height);
}
/**
* 輸出驗(yàn)證碼圖片,默認(rèn)圖片格式j(luò)peg
* @param width
* @param height
* @param os
* @throws IOException
*/
public void write(int width, int height, OutputStream os) throws IOException{
RandomCode.write(code, width, height, os, "jpeg");
}
/**
* 輸出驗(yàn)證碼圖片
* @param width
* @param height
* @param os
* @param format 圖片格式,支持jpg/jpeg/bmp/gif/png
* @throws IOException
*/
public void write(int width, int height, OutputStream os, String format) throws IOException{
RandomCode.write(code, width, height, os, format);
}
public int getLength() {
return length;
}
public String getCode() {
return code;
}
/**
* 靜態(tài)方法
* 生成隨機(jī)字符串
* @param length 字符串長度
* @return 隨機(jī)字符串
*/
public static String randomString(int length){
Random random = new Random();
StringBuffer sb = new StringBuffer();
for(int i = 0; i < length; i++){
sb.append(base.charAt(random.nextInt(base.length())));
}
return sb.toString();
}
/**
* 靜態(tài)方法
* 輸出驗(yàn)證碼圖片
* @param code 驗(yàn)證碼字符串
* @param width 圖片寬度
* @param height 圖片高度
* @param os 圖片輸出流
* @param format 圖片格式,支持jpg/jpeg/bmp/gif/png
* @throws IOException
*/
public static void write(String code, int width, int height, OutputStream os, String format) throws IOException{
BufferedImage image = toImage(code, width, height);
ImageIO.write(image, format, os);
}
/**
* 靜態(tài)方法
* 輸出驗(yàn)證碼圖片,默認(rèn)圖片格式j(luò)peg
* @param code 驗(yàn)證碼字符串
* @param width 圖片寬度
* @param height 圖片高度
* @param os 圖片輸出流
* @throws IOException
*/
public static void write(String code, int width, int height, OutputStream os) throws IOException{
write(code, width, height, os, "jpeg");
}
/**
* 靜態(tài)方法
* 字符串轉(zhuǎn)成驗(yàn)證碼圖片
* @param code 驗(yàn)證碼字符串
* @param width 驗(yàn)證碼圖片寬度,單位像素
* @param height 驗(yàn)證碼圖片高度,單位像素
* @return
*/
public static BufferedImage toImage(String code, int width, int height){
//字體大小
int fontSize = (int)Math.ceil(height * 0.9);
if(fontSize < 20){
fontSize = 20;
}
//字體在Y坐標(biāo)上的位置
int positionY = (int)Math.ceil(height * 0.8);
int lenCode = code.length();
//計算字體寬度
int fontWidth = width / (lenCode + 2);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
//圖片背景隨機(jī)顏色
g.setColor(randomColor(new Random(), 200, 250));
g.fillRect(0, 0, width, height);
//設(shè)置字體
g.setFont(new Font("Times New Roman", Font.BOLD, fontSize));
//在圖片上畫縱橫交錯的線,達(dá)到混淆效果
drawLines(g, width, height);
//在圖片上畫驗(yàn)證碼
drawString(g, code, fontWidth, positionY);
g.dispose();
return image;
}
/**
* 靜態(tài)方法
* 在圖片上話位子
* @param g
* @param code 驗(yàn)證碼字符串
* @param fontWidth 字體寬度
* @param positionY 字體Y坐標(biāo)
*/
private static void drawString(Graphics g, String code, int fontWidth, int positionY){
int len = code.length();
Random random = new Random();
for(int i = 0; i < len; i++){
g.setColor(randomColor(random));
g.drawString(String.valueOf(code.charAt(i)), (i + 1) * fontWidth, positionY);
}
}
private static Color randomColor(Random random){
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
return new Color(r, g, b);
}
private static Color randomColor(Random random, int fc, int bc){
if(fc > 255){
fc = 255;
}
if(bc > 255){
bc = 255;
}
int diff = bc-fc;
int r = fc + random.nextInt(diff);
int g = fc + random.nextInt(diff);
int b = fc + random.nextInt(diff);
return new Color(r,g,b);
}
/**
* 靜態(tài)方法
* 畫縱橫交錯的線
* @param g
* @param width 驗(yàn)證碼圖片寬度
* @param height 驗(yàn)證碼圖片高度
*/
private static void drawLines(Graphics g, int width, int height){
Random random = new Random();
//線的數(shù)量
int count = ((int)(Math.ceil(random.nextDouble() * 100))) + 100;
for(int i = 0; i < count; i++){
int fc = 160 + (int)Math.ceil(random.nextDouble() * 40);
int bc = 200 + (int)Math.ceil(random.nextDouble() * 55);
g.setColor(randomColor(random, fc, bc));
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(width / 5);
int yl = random.nextInt(height / 5);
g.drawLine(x, y, x + xl, y + yl);
}
}
}
2 Servlet返回驗(yàn)證碼
請求路徑http://<網(wǎng)站路徑>/random/code/servlet
@WebServlet("/random/code/servlet")
public class RandomCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 驗(yàn)證碼圖片寬度,單位像素
int width = 120;
// 驗(yàn)證碼圖片高度,單位像素
int height = 30;
// 驗(yàn)證碼圖片格式
String format = "png";
// 驗(yàn)證碼字符長度
int len = 4;
// 設(shè)置圖片格式
response.setContentType("image/" + format);
// 禁止瀏覽器緩存圖片
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
String code = RandomCode.randomString(len);
// 把圖片輸出到response輸出流
RandomCode.write(code, width, height, response.getOutputStream(), format);
}
}
3 Strust2返回驗(yàn)證碼
public class RandomCodeAction extends ActionSupport {
private static final long serialVersionUID = -7515645222798283236L;
/**
* 獲取驗(yàn)證碼
*/
public void generateCode() {
HttpServletResponse response = ServletActionContext.getResponse();
// 驗(yàn)證碼圖片寬度,單位像素
int width = 120;
// 驗(yàn)證碼圖片高度,單位像素
int height = 30;
// 驗(yàn)證碼圖片格式
String format = "png";
// 驗(yàn)證碼字符長度
int len = 4;
// 設(shè)置圖片格式
response.setContentType("image/" + format);
// 禁止瀏覽器緩存圖片
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
String code = RandomCode.randomString(len);
// 把圖片輸出到response輸出流
try {
RandomCode.write(code, width, height, response.getOutputStream(), format);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Struts2的驗(yàn)證碼配置
<package name="pkg-random-code" namespace="/" extends="struts-default">
<action name="randomCode_*" method="{1}" class="com.rhui.web.action.RandomCodeAction"></action>
</package>
請求路徑http://<網(wǎng)站路徑>/randomCode_generateCode.do
4 SpringMVC返回驗(yàn)證碼
請求路徑http://<網(wǎng)站路徑>/random/code/generate.do
package com.rhui.web.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.rhui.util.RandomCode;
@Controller
@RequestMapping("/random/code")
public class RandomCodeController {
@RequestMapping("/generate.do")
public void generateCode(HttpServletResponse response) {
// 驗(yàn)證碼圖片寬度,單位像素
int width = 120;
// 驗(yàn)證碼圖片高度,單位像素
int height = 30;
// 驗(yàn)證碼圖片格式
String format = "png";
// 驗(yàn)證碼字符長度
int len = 4;
// 設(shè)置圖片格式
response.setContentType("image/" + format);
// 禁止瀏覽器緩存圖片
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
String code = RandomCode.randomString(len);
// 把圖片輸出到response輸出流
try {
RandomCode.write(code, width, height, response.getOutputStream(), format);
} catch (IOException e) {
e.printStackTrace();
}
}
}

相關(guān)文章
peewee創(chuàng)建連接前的前置操作wireshark抓包實(shí)現(xiàn)
這篇文章主要為大家介紹了peewee創(chuàng)建連接前的前置操作wireshark?抓包實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Python上下文管理器類和上下文管理器裝飾器contextmanager用法實(shí)例分析
這篇文章主要介紹了Python上下文管理器類和上下文管理器裝飾器contextmanager用法,結(jié)合實(shí)例形式分析了上下文管理器類定義、使用、sqlalchemy實(shí)現(xiàn)數(shù)據(jù)庫的自動提交和回滾相關(guān)操作技巧,需要的朋友可以參考下2019-11-11
Python如何實(shí)現(xiàn)拆分?jǐn)?shù)據(jù)集
這篇文章主要介紹了Python如何實(shí)現(xiàn)拆分?jǐn)?shù)據(jù)集問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
python實(shí)點(diǎn)云分割k-means(sklearn)詳解
這篇文章主要為大家詳細(xì)介紹了Python實(shí)點(diǎn)云分割k-means,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-05-05
python中pandas.DataFrame排除特定行方法示例
這篇文章主要給大家介紹了關(guān)于python中pandas.DataFrame排除特定行的方法,文中給出了詳細(xì)的示例代碼,相信對大家的理解和學(xué)習(xí)具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03
Pytorch中Softmax與LogSigmoid的對比分析
這篇文章主要介紹了Pytorch中Softmax與LogSigmoid的對比分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
Python Web框架之Django框架cookie和session用法分析
這篇文章主要介紹了Python Web框架之Django框架cookie和session用法,結(jié)合實(shí)例形式分析了Django框架cookie和session的常見使用技巧與操作注意事項,需要的朋友可以參考下2019-08-08

