使用Java實(shí)現(xiàn)驗(yàn)證碼程序
用java實(shí)現(xiàn)的給瀏覽器響應(yīng)驗(yàn)證碼程序。并且是實(shí)現(xiàn)了可以點(diǎn)擊驗(yàn)證碼圖片換一張驗(yàn)證碼。
最后邊給出了完整的代碼。
//首先定義一個(gè)自己的類并且去繼承HttpServlet這個(gè)類 public class CheckImg extends HttpServlet{ ?? ?//復(fù)寫HttpServlet中的doGet方法 ?? ?public void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException, ?? ?IOException{ ?? ??? ?//準(zhǔn)備一張畫紙,將驗(yàn)證碼中的數(shù)字字母寫到這張畫紙中 ?? ??? ?int width = 120; ?? ??? ?int height = 30; ?? ??? ?BufferedImage bufi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); ?? ??? ?//這里面的width、height、就是這張畫紙的長(zhǎng)寬。BufferedImage.TYPE_INT_RGB就是這張畫紙基于 ?? ??? ?//RGB三原色來進(jìn)行畫 ?? ??? ?//這個(gè)時(shí)候并沒有在這張紙上書寫任何內(nèi)容,但是已經(jīng)可以像客戶端響應(yīng)請(qǐng)求了 ?? ??? ?ImageIO.write(bufi, "jpg", resp.getOutputStream()); ?? ?} }
這時(shí)候可以在瀏覽器上看到一個(gè)長(zhǎng)120,高30的矩形小框。
//設(shè)置畫筆顏色 g.setColor(Color.WHITE); //將這個(gè)顏色填充到整個(gè)畫紙 g.fillRect(0,0,width,height);
瀏覽器上就顯示出來一個(gè)白色的小框也就是上邊定義的畫紙
開始在畫紙上畫驗(yàn)證碼了。
//定義圖片上可以寫什么數(shù)據(jù) String data = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890"; //定義書寫在畫紙上的起始位置 int x =15; int y =25; //定義一個(gè)隨機(jī)數(shù) Random r = new Random(); //定義一個(gè)StringBuilder字符串緩沖區(qū) StringBuilder sb = new StringBuilder(); //定義一個(gè)循環(huán)給畫紙上寫四個(gè)數(shù)據(jù) for(int i = 0; i < 4; i++){ //從data中隨機(jī)獲取一個(gè)下標(biāo)的數(shù)據(jù) char c = data.charAt(r.nextInt(data.length())); //每寫一個(gè)數(shù)據(jù)就將這個(gè)數(shù)放到字符串緩沖區(qū)中 sb.append(c+"") //隨機(jī)生成畫筆的顏色,RGB三原色隨機(jī)在0-256中隨機(jī)生成 g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256))); //設(shè)置字體 g.setFont(new Font("黑體",Font.BOLD,26)); //將數(shù)據(jù)寫到畫紙上 g.drawString(c+"",x,y); ?//沒寫完一個(gè)調(diào)整下一個(gè)數(shù)據(jù)寫的位置 ? x += 25; ? } //循環(huán)結(jié)束也就是所有的數(shù)據(jù)都放在字符串緩沖區(qū)中 HttpSession session = req.getSession(); session.setAttribute("checkNum",sb.toString());
再重啟tomcat在瀏覽器上能看到書寫驗(yàn)證碼了
在畫紙上添加干擾信息
//添加線類型的干擾信息 ? ? ? ? for(int i = 0; i < 15 ; i++){ ? ? ? ? ? ? //同樣設(shè)置線的顏色 ? ? ? ? ? ? g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256))); ? ? ? ? ? ? //開始劃線,這里需要的四個(gè)參數(shù)中前兩個(gè)是線開頭的左邊,后邊兩個(gè)是線結(jié)束的坐標(biāo) ? ? ? ? ? ? g.drawLine(r.nextInt(width),r.nextInt(height),r.nextInt(width),r.nextInt(height)); ? ? ? ? } ? ? ? ? //添加點(diǎn)類型干擾信息 ? ? ? ? for (int i = 0 ; i < 150 ; i++){ ? ? ? ? ? ? //設(shè)置點(diǎn)的顏色 ? ? ? ? ? ? g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256))); ? ? ? ? ? ? //開始畫點(diǎn),實(shí)質(zhì)上這是畫橢圓,將上半軸半徑,左半軸半徑設(shè)置為0就可以看成是一個(gè)點(diǎn) ? ? ? ? ? ? g.drawOval(r.nextInt(width),r.nextInt(height),0,0); ? ? ? ? }
在瀏覽器上就能看到驗(yàn)證碼上充滿點(diǎn)和橫線,降低辨識(shí)度
貌似還沒有達(dá)到想要的結(jié)果,將字體設(shè)置一點(diǎn)傾斜度就更好了
//設(shè)置數(shù)據(jù)旋轉(zhuǎn) double theta =(30 - (r.nextInt(60)))*Math.PI/180; g.rotate(theta,x,24); //將數(shù)據(jù)寫到畫紙上 g.drawString(c+"",x,y); //設(shè)置完旋轉(zhuǎn)要調(diào)回,防止數(shù)據(jù)旋轉(zhuǎn)的看不到 g.rotate(-theta,x,24);
可以看到圖片中的數(shù)據(jù)進(jìn)行了略微的傾斜
html注冊(cè)頁(yè)面代碼
這里只截取了body和script部分的代碼
<body> <fieldset id=""> ? <legend>注冊(cè)頁(yè)面</legend> ? <form action="/day02/register2" method="post" id="form" > ? ? <table> ? ? ? <tr> ? ? ? ? <td>用戶名:</td> ? ? ? ? <td><input type="text" name="userName" /><span id="span1"></span></td> ? ? ? </tr> ? ? ? <tr> ? ? ? ? <td> ? ? ? ? ? 密碼: ? ? ? ? </td> ? ? ? ? <td> ? ? ? ? ? <input type="password" name="password" /> ? ? ? ? </td> ? ? ? </tr> ? ? ? <tr> ? ? ? ? <td> ? ? ? ? ? 確認(rèn)密碼: ? ? ? ? </td> ? ? ? ? <td> ? ? ? ? ? <input type="password" name="repassword" /> ? ? ? ? ? <span id="span2"></span> ? ? ? ? </td> ? ? ? </tr> ? ? ? <tr id="tr4"> ? ? ? ? <td> ? ? ? ? ? 性別: ? ? ? ? </td> ? ? ? ? <td> ? ? ? ? ? <input type="radio" name="sex" value="男" />男 ? ? ? ? ? <input type="radio" name="sex" value="女" />女 ? ? ? ? ? <span id="span3"></span> ? ? ? ? </td> ? ? ? </tr> ? ? ? <tr> ? ? ? ? <td>愛好:</td> ? ? ? ? <td> ? ? ? ? ? <input type="checkbox" name="hobby" value="唱" />唱 ? ? ? ? ? <input type="checkbox" name="hobby" value="跳" />跳 ? ? ? ? ? <input type="checkbox" name="hobby" value="rap" />rap ? ? ? ? ? <input type="checkbox" name="hobby" value="籃球" />籃球 ? ? ? ? ? <span id="span4"></span> ? ? ? ? </td> ? ? ? </tr> ? ? ? <tr> ? ? ? ? <td>國(guó)籍:</td> ? ? ? ? <td> ? ? ? ? ? <select name="country" id="country"> ? ? ? ? ? ? <option value="none">--請(qǐng)選擇國(guó)籍--</option> ? ? ? ? ? ? <option value="中國(guó)">中國(guó)</option> ? ? ? ? ? ? <option value="韓國(guó)">韓國(guó)</option> ? ? ? ? ? ? <option value="日本">日本</option> ? ? ? ? ? ? <option value="美國(guó)">美國(guó)</option> ? ? ? ? ? </select> ? ? ? ? ? <span id="span5"></span> ? ? ? ? </td> ? ? ? </tr> ? ? ? <tr> ? ? ? ? <td>自我評(píng)價(jià):</td> ? ? ? ? <td> ? ? ? ? ? <textarea rows="10px" cols="20px" id="textarea" name="describe" ></textarea> ? ? ? ? </td> ? ? ? </tr> ? ? ? <tr> ? ? ? ? <td> ? ? ? ? ? 驗(yàn)證碼: ? ? ? ? </td> ? ? ? ? <td> ? ? ? ? ? //定義一個(gè)input標(biāo)簽,用戶輸入驗(yàn)證碼 ? ? ? ? ? <input type="text" name="check"/> ? ? ? ? ? //input標(biāo)簽后鏈接了上邊寫的驗(yàn)證碼生成Servlet程序 ? ? ? ? ? //并且更改鼠標(biāo)放在圖片上的樣式,和添加了點(diǎn)擊事件 ? ? ? ? ? <img src="/day02/demo" id="img" onclick="checkImg()" style = "cursor: pointer"> ? ? ? ? ? <a href="javascript:void(0);" onclick="checkImg()">換一張</a> ? ? ? ? </td> ? ? ? </tr> ? ? </table> ? ? <input type="submit" id="btn2" value="提交" /> ? ? <input type="button" id="btn1" value="驗(yàn)證" /> ? </form> </fieldset> </body> <script type="text/javascript"> ? function checkImg() { ? ?? ?//通過ID屬性拿到img標(biāo)簽 ? ? var img = document.getElementById("img"); ? ? //當(dāng)瀏覽器發(fā)現(xiàn)兩次請(qǐng)求的URL相同時(shí)不會(huì)主動(dòng)的向服務(wù)器請(qǐng)求圖片 ? ? //所以需要實(shí)時(shí)的更改URL,這里采用的是在URL后邊拼接一個(gè)當(dāng)前系統(tǒng)時(shí)間的毫秒值 ? ? //這樣就能保證每一毫秒的URL都不同,從而瀏覽器會(huì)給服務(wù)器發(fā)送圖片的請(qǐng)求 ? ? img.src ="/day02/demo?"+new Date().getTime() ? } </script>
完整的代碼
@WebServlet(urlPatterns = "/demo") public class CheckImg extends HttpServlet { ? ? //復(fù)寫HttpServlet中的doGet方法 ? ? public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, ? ? IOException{ ? ? ? ? //準(zhǔn)備一張畫紙,將驗(yàn)證碼中的數(shù)字字母寫到這張畫紙中 ? ? ? ? int width = 120; ? ? ? ? int height = 30; ? ? ? ? BufferedImage bufi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); ? ? ? ? //這里面的width、height、就是這張畫紙的長(zhǎng)寬。BufferedImage.TYPE_INT_RGB就是這張畫紙基于 ? ? ? ? //RGB三原色來進(jìn)行畫 ? ? ? ? //獲取一個(gè)畫筆對(duì)象,給圖片上畫畫 ? ? ? ? Graphics2D g = (Graphics2D) bufi.getGraphics(); ? ? ? ? //設(shè)置畫筆顏色 ? ? ? ? g.setColor(Color.WHITE); ? ? ? ? //將這個(gè)顏色填充到整個(gè)畫紙 ? ? ? ? g.fillRect(0,0,width,height); ? ? ? ? //定義圖片上可以寫什么數(shù)據(jù) ? ? ? ? String data = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890"; ? ? ? ? //定義書寫在畫紙上的起始位置 ? ? ? ? int x =15; ? ? ? ? int y =25; ? ? ? ? //定義一個(gè)隨機(jī)數(shù) ? ? ? ? Random r = new Random(); ? ? ? ? //定義一個(gè)循環(huán)給畫紙上寫四個(gè)數(shù)據(jù) ? ? ? ? for(int i = 0; i < 4; i++){ ? ? ? ? ? ? //從data中隨機(jī)獲取一個(gè)下標(biāo)的數(shù)據(jù) ? ? ? ? ? ? char c = data.charAt(r.nextInt(data.length())); ? ? ? ? ? ? //隨機(jī)生成畫筆的顏色,RGB三原色隨機(jī)在0-256中隨機(jī)生成 ? ? ? ? ? ? g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256))); ? ? ? ? ? ? //設(shè)置字體 ? ? ? ? ? ? g.setFont(new Font("黑體",Font.BOLD,26)); ? ? ? ? ? ?//設(shè)置數(shù)據(jù)旋轉(zhuǎn) ? ? ? ? ? ? double theta =(30 - (r.nextInt(60)))*Math.PI/180; ? ? ? ? ? ? g.rotate(theta,x,24); ? ? ? ? ? ? //將數(shù)據(jù)寫到畫紙上 ? ? ? ? ? ? g.drawString(c+"",x,y); ? ? ? ? ? ? //設(shè)置完旋轉(zhuǎn)要調(diào)回,防止數(shù)據(jù)旋轉(zhuǎn)的看不到 ? ? ? ? ? ? ?g.rotate(-theta,x,24); ? ? ? ? ? ? //將數(shù)據(jù)寫到畫紙上 ? ? ? ? ? ? g.drawString(c+"",x,y); ? ? ? ? ? ? //g.rotate(-theta,r.nextInt(width),24); ? ? ? ? ? ? //設(shè)置完旋轉(zhuǎn)要調(diào)回,防止數(shù)據(jù)旋轉(zhuǎn)的看不到 ? ? ? ? ? ? g.rotate(-((10)*3.14/180),15*i+8,7); ? ? ? ? ? ? //每寫完一個(gè)調(diào)整下一個(gè)數(shù)據(jù)寫的位置 ? ? ? ? ? ? x += 25; ? ? ? ? } ? ? ? ? //添加線類型的干擾信息 ? ? ? ? for(int i = 0; i < 15 ; i++){ ? ? ? ? ? ? //同樣設(shè)置線的顏色 ? ? ? ? ? ? g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256))); ? ? ? ? ? ? //開始劃線,這里需要的四個(gè)參數(shù)中前兩個(gè)是線開頭的左邊,后邊兩個(gè)是線結(jié)束的坐標(biāo) ? ? ? ? ? ? g.drawLine(r.nextInt(width),r.nextInt(height),r.nextInt(width),r.nextInt(height)); ? ? ? ? } ? ? ? ? //添加點(diǎn)類型干擾信息 ? ? ? ? for (int i = 0 ; i < 150 ; i++){ ? ? ? ? ? ? //設(shè)置點(diǎn)的顏色 ? ? ? ? ? ? g.setColor(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256))); ? ? ? ? ? ? //開始畫點(diǎn),實(shí)質(zhì)上這是畫橢圓,將上半軸半徑,左半軸半徑設(shè)置為0就可以看成是一個(gè)點(diǎn) ? ? ? ? ? ? g.drawOval(r.nextInt(width),r.nextInt(height),0,0); ? ? ? ? } ? ? ? ? //給客戶端響應(yīng)請(qǐng)求 ? ? ? ? ImageIO.write(bufi, "jpg", resp.getOutputStream()); ? ? } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- java登錄驗(yàn)證碼實(shí)現(xiàn)代碼
- java 圖片驗(yàn)證碼的實(shí)現(xiàn)代碼
- Java實(shí)現(xiàn)驗(yàn)證碼具體代碼
- Java 隨機(jī)生成驗(yàn)證碼(支持大小寫字母、數(shù)字、隨機(jī)字體)的實(shí)例
- JAVA實(shí)現(xiàn)利用第三方平臺(tái)發(fā)送短信驗(yàn)證碼
- Java隨機(jī)生成手機(jī)短信驗(yàn)證碼的方法
- JavaWeb簡(jiǎn)單用戶登錄注冊(cè)實(shí)例代碼(有驗(yàn)證碼)
- Java實(shí)現(xiàn)仿淘寶滑動(dòng)驗(yàn)證碼研究代碼詳解
- java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時(shí)間
- Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例代碼
相關(guān)文章
spring-boot-maven-plugin?配置有啥用
這篇文章主要介紹了spring-boot-maven-plugin?配置是干啥的,這個(gè)是SpringBoot的Maven插件,主要用來打包的,通常打包成jar或者war文件,本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08IDEA配置SpringBoot熱啟動(dòng),以及熱啟動(dòng)失效問題
這篇文章主要介紹了IDEA配置SpringBoot熱啟動(dòng),以及熱啟動(dòng)失效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11Java14對(duì)于NullPointerException的新處理方式示例解析
這篇文章主要為大家介紹了Java14對(duì)于NullPointerException的新處理方式示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Spring Boot 自動(dòng)配置的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot 自動(dòng)配置的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08Spring Boot獲取微信用戶信息的超簡(jiǎn)單方法
這篇文章主要給大家介紹了關(guān)于Spring Boot獲取微信用戶信息的超簡(jiǎn)單方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Springboot實(shí)現(xiàn)人臉識(shí)別與WebSocket長(zhǎng)連接的實(shí)現(xiàn)代碼
這篇文章主要介紹了Springboot實(shí)現(xiàn)人臉識(shí)別與WebSocket長(zhǎng)連接的實(shí)現(xiàn),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11