小博老師解析Java核心技術點-驗證碼製做

[理論知識]javascript

java程序開發中,要顯示一張圖片,主要有兩種方式。第一種是基於現成圖片,這種方式比較常見也比較簡單。第二種是使用java中java.awt包和com.sun.image包中的繪圖技術,使用代碼繪製出一張圖片,這種技術通常適用於圖片並不是固定、重複使用率較低的場景,好比驗證碼、圖片加水印、生成縮略圖、繪製各類數據分析圖(柱狀圖、餅圖、線性圖等),這些圖片並非固定的,而是根據數據的改變而隨時變化的。java

[步驟解讀一]繪製驗證碼瀏覽器

本文中,小博老師就爲你們解析一下,如何使用java繪圖技術來製做驗證碼,因爲驗證碼的功能比較經常使用,代碼又比較繁瑣,所以小博老師先爲你們封裝一個Identifying類,之後要使用驗證碼就能夠直接調用它了,核心代碼以下:session

package com.bwf.framework.javaee.imageutils;dom

import java.awt.Color;jsp

import java.awt.Font;ide

import java.awt.Graphics2D;post

import java.awt.image.BufferedImage;this

import java.io.IOException;.net

import java.util.ArrayList;

import java.util.Collections;

import java.util.Random;

import javax.servlet.ServletException;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.sun.image.codec.jpeg.JPEGCodec;

import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**

 * 驗證碼圖片生成Servlet類,直接調用該Servlet便可使用 取值的時候調用session.getAttribute("code")獲得生成的值

 * @author 博爲峯-小博老師

 * @time 2016-11-1 下午14:26:00

 */

public class Identifying extends HttpServlet {

       public Identifying(HttpServletRequest request, HttpServletResponse response){

              this.setRequest(request);

              this.setResponse(response);

       }

 

       private static final long serialVersionUID = 1L; // 對象序列號

       private int width = 120; // 畫布寬度(px)

       private int height = 30; // 畫布高度(px)

       private int lineNum = 150; // 干擾線數量

       private int pointNum = 100; // 干擾點數量

       private int wordNum = 4; // 驗證碼字符個數

       private HttpServletRequest request; // 當前請求對象

       private HttpServletResponse response; // 當前響應對象

       private String sessionName = "code"; // 正確驗證碼存放在Session對象中的key名稱

 

       /**

        * 獲取範圍內的隨機顏色

        * @param fc  顏色範圍的最大值(0~255)

        * @param bc 顏色範圍的最小值(0~255)

        * @return 隨機顏色值

        */

       private Color getRandColor(int fc, int bc) {

              Random random = new Random();

              if (fc > 255)

                     fc = 255;

              if (fc < 0)

                     fc = 0;

              if (bc > 255)

                     bc = 255;

              if (bc < 0)

                     bc = 0;

              int r = fc + random.nextInt(bc - fc);

              int g = fc + random.nextInt(bc - fc);

              int b = fc + random.nextInt(bc - fc);

              return new Color(r, g, b);

       }

 

       /**

        * 繪製驗證碼圖片

        */

       public void create() throws IOException, ServletException {

              // 設置輸出類型爲圖片

              response.setContentType("image/jpeg");

              // 獲取畫布寬度和高度

              int width = this.width;

              int height = this.height;

              // 產生隨機數

              Random r = new Random();

              // 產生緩衝畫布

              BufferedImage imgbuf = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

              // 取得緩衝的繪製環境

              Graphics2D g = imgbuf.createGraphics();

              // 設置筆觸顏色 用來填充畫布的顏色

              g.setColor(getRandColor(200, 250));

              // 填充畫布

              g.fillRect(0, 0, width, height);

 

              // 設計筆觸顏色 用來繪製干擾線

              g.setColor(getRandColor(160, 200));

              // 隨機產生lineNum條幹擾線,使圖象中的認證碼不易被其它程序探測到

              for (int i = 0; i < this.lineNum; i++) {

                     int x = r.nextInt(width); // 干擾線起始點x軸座標

                     int y = r.nextInt(height); // 干擾線起始點y軸座標

                     int xl = r.nextInt(12); // 干擾線結束點x軸座標

                     int yl = r.nextInt(12); // 干擾線結束點y軸座標

                     g.drawLine(x, y, x + xl, y + yl); // 繪製干擾線

              }

 

              // 設置筆觸顏色 用來繪製干擾點

              g.setColor(getRandColor(120, 240));

              // 隨機產生pointNum個干擾點,使圖像中的驗證碼不易被其餘分析程序探測到

              for (int i = 0; i < this.pointNum; i++) {

                     int x = r.nextInt(width); // 設置干擾點中心點x軸座標

                     int y = r.nextInt(height); // 設置干擾點中心點y軸座標

                     g.drawOval(x, y, 0, 0); // 繪製干擾點,半徑0,起始角度0

              }

 

              // 設置文字樣式 用來繪製驗證碼字符

              g.setFont(new Font("Times New Roman", Font.PLAIN, 18));

              // 準備一個ArrayList 用於存放驗證碼字符庫

              ArrayList libs = new ArrayList();

              // 準備一個char[] 列出驗證碼字符庫

              char[] arr = new char[] { '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', '0', '1', '2', '3', '4', '5', '6','7', '8', '9' };

              // 將char[]中的驗證碼字符 存放到 ArrayList中

              for (int i = 0; i <= arr.length - 1; i++) {

                     libs.add(arr[i] + "");

              }

              // 隨機打亂順序

              Collections.shuffle(libs);

              // 定義字符串 用於拼接正確驗證碼

              String scode = "";

              // 循環出wordNum個驗證碼字符

              for (int i = 0; i < this.wordNum; i++) {

                     // 從隨機驗證碼字符庫 抽取一個驗證碼字符

                     String rand = String.valueOf(libs.get(i));

                     // 拼接正確驗證碼

                     scode += rand;

                     // 設置筆觸顏色 用於繪製驗證碼字符

                     g.setColor(new Color(20 + r.nextInt(110), 20 + r.nextInt(110), 20 + r.nextInt(110)));

                     // 繪製驗證碼字符

                     g.drawString(rand, (this.width / this.wordNum / 2 + 12) * i + (this.width / this.wordNum / 2),this.height / 2 + 6);

              }

              // 將正確驗證碼存放到Session對象中

              request.getSession().setAttribute(this.sessionName, scode);

              // 獲得HTTP的流

              ServletOutputStream out = response.getOutputStream();

              // 產生JPEG的圖像加碼器

              JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);

              // 將圖像畫布內容轉碼

              encoder.encode(imgbuf);

              // 輸出圖像

              out.flush();

       }

……省略getter和setter……

}

而後咱們在一個Servlet,實例化Identifying對象,調用create()方法,便可顯示出一個驗證碼圖片,核心代碼以下:

@WebServlet("/BWFIdentifying")

public class BWFIdentifyingServlet extends HttpServlet {

       protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {

              Identifying iden = new Identifying(request, response);

              iden.create();

       }

}

瀏覽器訪問效果以下:

 

 

[步驟解讀二]在登陸頁面中引入驗證碼

接下來咱們製做一個簡單的登陸頁面,引入驗證碼,咱們建立一個jsp,核心代碼以下:

<body>

       <form action="BWFCheckLogin" method="post">

              帳戶名稱:<input type="text" name="username"/><br/><br/>

              帳戶密碼:<input type="password" name="password"/><br/><br/>

              驗證&nbsp;碼:<input type="text" name="iden" style="width:60px;"/>

                     <img src="BWFIdentifying" title="看不清?點擊換一張!" style="cursor:pointer;" id="iden" /><br/><br/>

              <input type="submit" value="登  錄"/>

       </form>

</body>

訪問jsp頁面效果以下:

 

 

爲了實現驗證碼圖片點擊後能夠自動更換一張驗證碼的效果,咱們在該jsp頁面中增長javascript,核心代碼以下:

<script>

window.onload=function(){

       document.getElementById("iden").onclick=function(){

              this.src="BWFIdentifying?a="+Math.random();

       }

}

</script>

其中在URL中傳遞參數a,使用隨機數做爲值,是爲了讓該Servlet認爲每次都是新的請求。

這樣,咱們的驗證碼效果基本就作完了,當用戶點擊登陸按鈕,提交頁面後,咱們只須要獲取表單提交的用戶填寫的驗證碼,而後從Session對象(默認key爲「Code」)獲取正確的驗證碼,進行比對便可。

[步驟解讀三]Identifying類的經常使用方法

小博老師爲你們封裝的Identifying類,除了上述默認使用方式,還能夠按照本身的需求,設置經常使用參數,例如:

@WebServlet("/BWFIdentifying")

public class BWFIdentifyingServlet extends HttpServlet {

       protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {

              Identifying iden = new Identifying(request, response);

              iden.setWidth(300);                              // 設置驗證碼畫布寬度

              iden.setHeight(50);                   // 設置驗證碼畫布高度

              iden.setLineNum(30);               // 設置干擾線數量

              iden.setPointNum(50);              // 設置干擾點屬相

              iden.setWordNum(6);               // 設置驗證碼字符數量

// 設置正確驗證碼存放Session對象的key名稱

              iden.setSessionName("iden");           i

den.create();

       }

}

訪問後效果:

 

相關文章
相關標籤/搜索