基于Java生成圖片驗(yàn)證碼的方法解析
使用Java生成圖片驗(yàn)證碼完全解析
在 Java 中開發(fā)圖片驗(yàn)證碼功能,您可以使用 Java 圖形處理庫,比如 Java Advanced Imaging (JAI) 或者 Java2D,來生成圖片并將文本寫入圖片。具體實(shí)現(xiàn)方法如下:
- 創(chuàng)建一個(gè) BufferedImage 對象,并設(shè)置圖片的寬度和高度。
- 獲取圖片的 Graphics2D 對象,并設(shè)置文本的顏色和字體。
- 在圖片上繪制文本。
- 對圖片進(jìn)行一些隨機(jī)處理,比如加入干擾線、噪點(diǎn)等,以增加圖片驗(yàn)證碼的難度。
- 將圖片輸出到瀏覽器,并設(shè)置相應(yīng)的 Content-Type?;蛘邔ufferedImage轉(zhuǎn)為base64編碼輸出到瀏覽器。(本次統(tǒng)一輸出到文件)
下面是一個(gè)簡單的示例代碼,可以幫助您快速開始:
import java.awt.*; import java.awt.image.*; import java.io.*; import javax.imageio.*; public class Captcha { public static void main(String[] args) throws Exception { int width = 100; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 設(shè)置文本的顏色和字體 g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 20)); // 繪制文本 g.drawString("Hello, World!", 10, 30); // 釋放 Graphics2D 對象 g.dispose(); // 將圖片輸出到瀏覽器 ImageIO.write(image, "jpeg", new File("captcha.jpeg")); } }
注意事項(xiàng)
在您的應(yīng)用中使用圖片驗(yàn)證碼功能時(shí),需要注意以下幾點(diǎn):
- 在生成圖片驗(yàn)證碼時(shí),需要使用隨機(jī)數(shù)生成文本內(nèi)容,以保證每次生成的圖片都是不同的。
- 在生成圖片時(shí),需要使用足夠復(fù)雜的算法來生成干擾線和噪點(diǎn),以增加圖片驗(yàn)證碼的難度。
- 在向用戶展示圖片驗(yàn)證碼時(shí),需要將圖片的文本內(nèi)容存儲在服務(wù)器端,以便在用戶提交表單時(shí)進(jìn)行驗(yàn)證。
- 在驗(yàn)證用戶輸入的圖片驗(yàn)證碼時(shí),需要注意大小寫敏感問題,并且需要考慮用戶輸入的可能存在的誤差。
如何加入噪點(diǎn)
在 Java 中加入噪點(diǎn)可以使用隨機(jī)數(shù)生成噪點(diǎn)的位置和顏色,然后使用 Graphics2D 的 drawLine() 方法在圖片上繪制噪點(diǎn)。
例如,下面的代碼演示了如何在圖片上隨機(jī)繪制 100 個(gè)噪點(diǎn):
import java.awt.*; import java.awt.image.*; import java.util.Random; public class Captcha { public static void main(String[] args) throws Exception { int width = 100; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 設(shè)置文本的顏色和字體 g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 20)); // 繪制文本 g.drawString("Hello, World!", 10, 30); // 創(chuàng)建隨機(jī)數(shù)生成器 Random rnd = new Random(); // 繪制噪點(diǎn) for (int i = 0; i < 100; i++) { int x = rnd.nextInt(width); int y = rnd.nextInt(height); g.drawLine(x, y, x, y); } // 釋放 Graphics2D 對象 g.dispose(); } }
上面的代碼中,我們使用了隨機(jī)數(shù)生成噪點(diǎn)的位置和顏色,并使用 Graphics2D 的 drawLine() 方法在圖片上繪制噪點(diǎn)。
如何生成干擾線
在 Java 中生成干擾線可以使用隨機(jī)數(shù)生成干擾線的起始點(diǎn)和結(jié)束點(diǎn),然后使用 Graphics2D 的 drawLine() 方法在圖片上繪制干擾線。
例如,下面的代碼演示了如何在圖片上隨機(jī)繪制 10 條干擾線:
import java.awt.*; import java.awt.image.*; import java.util.Random; public class Captcha { public static void main(String[] args) throws Exception { int width = 100; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 設(shè)置文本的顏色和字體 g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 20)); // 繪制文本 g.drawString("Hello, World!", 10, 30); // 創(chuàng)建隨機(jī)數(shù)生成器 Random rnd = new Random(); // 繪制干擾線 for (int i = 0; i < 10; i++) { int x1 = rnd.nextInt(width); int y1 = rnd.nextInt(height); int x2 = rnd.nextInt(width); int y2 = rnd.nextInt(height); g.drawLine(x1, y1, x2, y2); } // 釋放 Graphics2D 對象 g.dispose(); } }
上面的代碼中,我們使用了隨機(jī)數(shù)生成干擾線的起始點(diǎn)和結(jié)束點(diǎn),并使用 Graphics2D 的 drawLine() 方法在圖片上繪制干擾線。到了這一步其實(shí)大多數(shù)OCR已經(jīng)不能識別了。
什么樣的算法生成噪點(diǎn)比較好
在生成噪點(diǎn)時(shí),最重要的是要保證噪點(diǎn)數(shù)量足夠多,以增加圖片驗(yàn)證碼的難度。您可以使用以下算法來生成噪點(diǎn):
- 在圖片的所有像素點(diǎn)上隨機(jī)繪制一定數(shù)量的噪點(diǎn)。這種方法可以保證噪點(diǎn)數(shù)量足夠多,但會使圖片變得很雜亂,不利于用戶識別。
- 在圖片的一部分像素點(diǎn)上隨機(jī)繪制噪點(diǎn)。這種方法可以使圖片看起來清晰一些,但需要調(diào)整噪點(diǎn)的數(shù)量,以保證噪點(diǎn)數(shù)量足夠多。
- 使用圖形生成算法生成噪點(diǎn)。這種方法可以生成較為復(fù)雜的噪點(diǎn)圖形,但需要較多的計(jì)算資源。
最終選擇哪種方法取決于您的需求和系統(tǒng)的性能。
在 Java 中使用圖形生成算法生成噪點(diǎn),可以使用 Java2D 庫中的 Shape 接口和相關(guān)的實(shí)現(xiàn)類來生成各種圖形。例如,使用 Ellipse2D 類可以生成橢圓形噪點(diǎn),使用 Rectangle2D 類可以生成矩形噪點(diǎn)。
下面是一個(gè)簡單的示例代碼,演示了如何使用圖形生成算法生成噪點(diǎn):
import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.util.Random; public class Captcha { public static void main(String[] args) throws Exception { int width = 100; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 設(shè)置文本的顏色和字體 g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 20)); // 繪制文本 g.drawString("Hello, World!", 10, 30); // 創(chuàng)建隨機(jī)數(shù)生成器 Random rnd = new Random(); // 繪制噪點(diǎn) for (int i = 0; i < 100; i++) { Shape shape = new Ellipse2D.Double(rnd.nextDouble() * width, rnd.nextDouble() * height, rnd.nextDouble() * 5 + 1, rnd.nextDouble() * 5 + 1); g.fill(shape); } // 釋放 Graphics2D 對象 g.dispose(); } }
驗(yàn)證碼如何避免被ocr識別
為了避免驗(yàn)證碼被 OCR (Optical Character Recognition, 光學(xué)字符識別) 軟件識別,可以使用以下幾種方法:
- 增加噪點(diǎn):在圖片中加入噪點(diǎn)(如隨機(jī)點(diǎn)、線條等),使 OCR 軟件難以準(zhǔn)確識別文本。
- 斜放文本:將文本斜放,使 OCR 軟件難以識別。
- 改變字體:使用特殊的字體,使 OCR 軟件難以識別。
- 變換顏色:改變文本的顏色,使 OCR 軟件難以識別。
- 增加干擾元素:在圖片中加入干擾元素(如干擾線、干擾圖案等),使 OCR 軟件難以準(zhǔn)確識別文本。
如何斜放文本
單純的斜放文本只能避免某一些OCR算法,最好是每個(gè)字符都傾斜不同的角度。并且保持不同的間距。
在 Java 中斜放文本可以使用 Graphics2D 的 rotate() 方法來旋轉(zhuǎn)文本。例如,下面的代碼演示了如何在圖片上斜放文本:
import java.awt.*; import java.awt.image.*; public class Captcha { public static void main(String[] args) throws Exception { int width = 100; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 設(shè)置文本的顏色和字體 g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 20)); // 旋轉(zhuǎn)文本 g.rotate(Math.toRadians(30), width / 2, height / 2); // 繪制文本 g.drawString("Hello, World!", 10, 30); // 釋放 Graphics2D 對象 g.dispose(); } }
上面的代碼中,我們使用 Graphics2D 的 rotate() 方法將文本旋轉(zhuǎn)了 30 度。注意,旋轉(zhuǎn)角度使用的是弧度制,所以需要使用 Math.toRadians() 方法將角度轉(zhuǎn)換為弧度。
四位圖形驗(yàn)證碼
實(shí)現(xiàn)一個(gè)支持圖形干擾算法,斜放文本,使用特殊的字體,動(dòng)態(tài)文本的顏色的四位圖形驗(yàn)證碼
import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.util.Random; public class Captcha { private static final char[] CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; private static Random rnd = new Random(); public static String generateText() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { sb.append(CHARS[rnd.nextInt(CHARS.length)]); } return sb.toString(); } public static Color generateColor() { return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); } public static void main(String[] args) throws Exception { int width = 120; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 繪制背景 g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); // 繪制文本 String text = generateText(); g.setFont(new Font("Arial", Font.BOLD, 20)); g.setColor(generateColor()); g.rotate(Math.toRadians(30), width / 2, height / 2); g.drawString(text, 10, 30); // 繪制噪點(diǎn) for (int i = 0; i < 100; i++) { Shape shape = new Ellipse2D.Double(rnd.nextDouble() * width, rnd.nextDouble() * height, rnd.nextDouble() * 5 + 1, rnd.nextDouble() * 5 + 1); g.setColor(generateColor()); g.fill(shape); } // 繪制干擾線 for (int i = 0; i < 5; i++) { g.setColor(generateColor()); g.drawLine(rnd.nextInt(width), rnd.nextInt(height), rnd.nextInt(width), rnd.nextInt(height)); } // 釋放 Graphics2D 對象 g.dispose(); // 輸出圖片 ImageIO.write(image, "PNG", new File("captcha.png")); } }
上面的代碼中,我們使用了 Ellipse2D 類生成橢圓形噪點(diǎn),并使用隨機(jī)數(shù)生成噪點(diǎn)的位置和大小。我們還使用了 drawLine() 方法生成干擾線,并使用隨機(jī)數(shù)生成干擾線的位置和長度。
可以看到,雖然安全性提高了,但是辨識很困難。
調(diào)整噪點(diǎn)的透明度
在 Java 中調(diào)整噪點(diǎn)的透明度可以使用 AlphaComposite 類的靜態(tài)方法 getInstance() 來創(chuàng)建 AlphaComposite 對象,然后使用 setComposite() 方法來設(shè)置透明度。例如,下面的代碼演示了如何調(diào)整噪點(diǎn)的透明度:
import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.util.Random; public class Captcha { private static final char[] CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; private static Random rnd = new Random(); public static String generateText() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { sb.append(CHARS[rnd.nextInt(CHARS.length)]); } return sb.toString(); } public static Color generateColor() { return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); } public static void main(String[] args) throws Exception { int width = 120; int height = 40; // 創(chuàng)建 BufferedImage 對象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 獲取圖片的 Graphics2D 對象 Graphics2D g = image.createGraphics(); // 繪制背景 g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); // 繪制文本 String text = generateText(); g.setFont(new Font("Arial", Font.BOLD, 20)); g.setColor(generateColor()); g.rotate(Math.toRadians(30), width / 2, height / 2); g.drawString(text, 10, 30); // 調(diào)整噪點(diǎn)的透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); // 繪制噪點(diǎn) for (int i = 0; i < 100; i++) { Shape shape = new Ellipse2D.Double(rnd.nextDouble() * width, rnd.nextDouble() * height, rnd.nextDouble() * 5 + 1, rnd.nextDouble() * 5 + 1); g.setColor(generateColor()); g.fill(shape); } // 繪制干擾線 for (int i = 0; i < 5; i++) { g.setColor(generateColor()); g.drawLine(rnd.nextInt(width), rnd.nextInt(height), rnd.nextInt(width), rnd.nextInt(height)); } // 釋放 Graphics2D 對象 g.dispose(); // 輸出圖片 ImageIO.write(image, "PNG", new File("captcha.png")); } }
到此這篇關(guān)于基于Java生成圖片驗(yàn)證碼的方法解析的文章就介紹到這了,更多相關(guān)Java圖片驗(yàn)證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java編程實(shí)現(xiàn)漢字按字母順序排序的方法示例
這篇文章主要介紹了Java編程實(shí)現(xiàn)漢字按字母順序排序的方法,結(jié)合具體實(shí)例形式分析了java編碼轉(zhuǎn)換及字母排序相關(guān)操作技巧,需要的朋友可以參考下2017-07-07SpringBoot實(shí)現(xiàn)文件在線預(yù)覽功能的全過程
我們開發(fā)業(yè)務(wù)系統(tǒng)的時(shí)候,經(jīng)常有那種文檔文件在線預(yù)覽的需求,下面這篇文章主要給大家介紹了關(guān)于SpringBoot實(shí)現(xiàn)文件在線預(yù)覽功能的相關(guān)資料,需要的朋友可以參考下2021-11-11Java maven三種倉庫,本地倉庫,私服,中央倉庫的配置
今天給大家簡單介紹Maven三種倉庫的配置,文中有非常詳細(xì)的解釋,對Java初學(xué)者很有幫助喲,需要的朋友可以參考下,希望能夠給你帶來幫助2021-09-09Java基礎(chǔ)之Unsafe內(nèi)存操作不安全類詳解
Java是面向?qū)ο笳Z言,在使用Java編程時(shí),大多數(shù)情況下都不會直接操作內(nèi)存,而且Java也不提倡直接操作內(nèi)存,但是Java中到底有沒有可以直接操作內(nèi)存的工具類呢?有!Java中提供Unsafe類可以用來來直接操作內(nèi)存,文中詳細(xì)介紹了Unsafe內(nèi)存操作不安全類,需要的朋友可以參考下2021-06-06SpringBoot基于數(shù)據(jù)庫的定時(shí)任務(wù)統(tǒng)一管理的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot基于數(shù)據(jù)庫的定時(shí)任務(wù)統(tǒng)一管理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12