閱讀52 返回首頁    go 阿裏雲 go 技術社區[雲棲]


jsp-servlet圖像驗證碼

實現圖像驗證碼類ImageValidateCode:

package com.myhome;


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;


import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 * 防止暴力破解,使用的圖像驗證碼
 * */
public class ImageValidateCode extends HttpServlet 
{


/**
* 實現java.io.Serializable這個接口是為序列化,
* serialVersionUID 用來表明實現序列化類的不同版本間的兼容性。
* 如果你修改了此類, 要修改此值。否則以前用老版本的類序列化的類恢複時會出錯。
* 為了在反序列化時,確保類版本的兼容性。序列化時為了保持版本的兼容性,

* 即在版本升級時反序列化仍保持對象的唯一性。
*/
private static final long serialVersionUID = 5403703649596352260L;
//產生隨機數
private Random random =new Random();
//定義圖形驗證碼中繪製字符的字體,字體名稱,字體樣式,字體大小l;如:"Arial Black"或"Fixedsys", Font.CENTER_BASELINE, 18
private final Font mFont=new Font("Arial Black", Font.PLAIN, 24);
//定義驗證碼的大小,即高度和寬度
private final int IMG_WIDTH=90;
private final int IMG_HEIGHT=25;
//幹擾線的數量
private final int LineSize=50;
//產生的隨機字符數量
private int stringNum = 4;  
/**
* 獲取隨機顏色的方法
* */
private Color getRandColor(int fc,int bc)
{
if(fc>255)
{
fc=255;
}
if(bc>255)
{
bc=255;
}
//產生隨機的RGB三原色
int r=fc+random.nextInt(bc-fc-16);
int g=fc+random.nextInt(bc-fc-14);
int b=fc+random.nextInt(bc-fc-18);
return new Color(r, g, b);
}
/**
* 獲取大、小寫字母和數字隨機字符串方法
* */
private String getRandString()
{
//Math.random()---random()方法,是返回一個[0,1)的浮點數。

//一般我們是這樣運用的,比如我要取一個1~9的隨機數int a=(int)(Math.random()*10)注意是是乘上10再轉。
//Math.round()方法,round 就是四舍五入,

//math.round(-8.9) -9;math.round(-8.1) -8;math.round(8.9) 9;math.round(8.1) 8
//生成0、1、2的隨機數字
int randi=(int) Math.round(Math.random()*2);
//用來存儲數據的ASC碼
long itmp=0;
//用於存儲字符
char ctmp='\u0000';

//以“\u”開頭的是一個Unicode碼的字符,每一個'\u0000'都代表了一個空格。

//Unicode可同時包含65536個字符,ASCII/ANSI隻包含255個字符,實際上是Unicode的一個子集。

//Unicode字符通常用十六進製編碼方案表示,範圍在'\u0000'到'\uFFFF'之間。

//\u0000到\u00FF表示ASCII/ANSI字符。

//“\u”表示這是一個Unicode值.\u0000代表的應該是NULL,輸出控製台是一個空格...
switch(randi)
{
//生成大寫字母
case 1:
itmp=Math.round(Math.random()*25+65);//long類型
ctmp=(char) itmp;//char類型
return String.valueOf(ctmp);//String類型
//生成小寫字母
case 2:
itmp=Math.round(Math.random()*25+97);
ctmp=(char) itmp;
return String.valueOf(ctmp);
//生成數字
default :
itmp=Math.round(Math.random()*9);
return itmp+"";//將整型數字連接成字符串
}
}
/**
* 繪製隨機字符串
* */
private String drawString(Graphics g,String randomString,int i)
{
g.setFont(mFont);//設置字符串字體
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));//設置字符串顏色
String rands=getRandString();
randomString+=rands;
g.translate(random.nextInt(3), random.nextInt(2));//設置畫在圖片上的文字的x,y坐標,隨即偏移值
g.drawString(rands, 18*i+5, 18);//字符間距設置為15px
,使用此圖形上下文的當前字體和顏色繪製由指定 string 給定的文本。最左側字符的基線位於此圖形上下文坐標係統的 (x, y) 位置處。即:str - 要繪製的 string。x - x 坐標。y - y 坐標。//從圖像左麵10個像素個像素(後15*i+10),距上麵16個像素的位置開始從左到右的方向輸出rands的值。
return randomString;
}
/**
* 繪製幹擾線
* */
private void drawLine1(Graphics g)
{
//參數:x1 - 第一個點的 x 坐標。y1 - 第一個點的 y 坐標。x2 - 第二個點的 x 坐標。y2 - 第二個點的 y 坐標。x1和x2是起點坐標,x2和y2是終點坐標
int x=random.nextInt(IMG_WIDTH);
int y=random.nextInt(IMG_HEIGHT);
int x1=random.nextInt(13);
int y1=random.nextInt(15);
g.drawLine(x, y, x+x1, y+y1);
}
private void drawLine2(Graphics g)
{
//參數:x1 - 第一個點的 x 坐標。y1 - 第一個點的 y 坐標。x2 - 第二個點的 x 坐標。y2 - 第二個點的 y 坐標。x1和x2是起點坐標,x2和y2是終點坐標
int x=random.nextInt(IMG_WIDTH);
int y=random.nextInt(IMG_HEIGHT);
int x1=random.nextInt(13);
int y1=random.nextInt(15);
g.drawLine(x, y, x-x1, y-y1);
}
/**
* 圖像驗證碼的生成
* */
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException 
{
System.out.println("驗證碼開始生成了");
//設置禁止緩存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");//設置輸出流內容格式為圖片格式
/*禁用IE緩存
* HTTP消息報頭包括普通報頭、請求報頭、響應報頭、實體報頭。
* 普通報頭中的Cache-Control用於指定緩存指令,緩存指令是單向的(響應中出現的緩存指令在請求中未必會出現),且是獨立的(一個消息的緩存指令不會影響另一個消息處理的緩存機製),HTTP1.0使用的類似的報頭域為Pragma。
* 請求時的緩存指令包括:no-cache(用於指示請示或響應消息不能緩存)、no-store、max-age、max-stale、min-fresh、only-if-cached;
* 響應時的緩存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。
* 例:為了指示IE瀏覽器(客戶端)不要緩存頁麵,服務器端的jsp程序可以編寫如下:response.setHeader(“Cache-Control”, “no-cache”);//response.setHeader(“Pragma”, “no-cache”);
* 作用相當於上行代碼,通常兩者合用Expires實體報頭域給出響應過期的日期和時間。為了讓代理服務器或瀏覽器在一段時間以後更新緩存中(再次訪問曾訪問過的頁麵時,直接從緩存中加載,縮短響應時間和降低服務器負載)的頁麵,我們可以使用Expires實體報頭域指定頁麵過期時間。
* 例:Expires:Thu,15 Sep 2006 16:23:12 GMTHTTP1.1的客戶端和緩存必須將其他非法的日期格式(包括0)看作已經過期。
* 如:為了讓瀏覽器不要緩存頁麵,也可以利用Expires實體報關域,設置為0,jsp程序如下:response.setDateHeader(“Expires”, “0”);
* */
//在內存中創建一副圖像,寬90像素,高25像素,rgb模式的色彩
BufferedImage image=new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB);
//在內存中創建一個畫筆
Graphics g=image.getGraphics();
//設置畫筆顏色
g.setColor(getRandColor(200, 250));
//填充背景色,使用當前的畫筆顏色修改圖片背景色 
g.fillRect(1, 1, IMG_WIDTH-1, IMG_HEIGHT-1);//4個參數的意思分別為,起始X坐標,起始Y坐標,寬度,高度。
//為圖形驗證碼繪製邊框
g.setColor(new Color(155,155,155));
g.drawRect(0, 0, IMG_WIDTH,IMG_HEIGHT);
//生成隨機幹擾線
g.setColor(getRandColor(110, 133));
for(int i=0;i<=LineSize;i++){
drawLine1(g);
drawLine2(g);
}
//用於保存係統生成的隨機字符串
String randomString = "";
//繪製隨機字符串
for(int j=0;j<stringNum;j++){
randomString=drawString(g, randomString, j);
}
//獲取HttpSesssion對象
HttpSession session=request.getSession(true);
//getSession(true):true: 如果session存在,則返回該session,否則創建一個新的session;false: 如果session存在,則返回該session,否則返回null.
//將隨機字符串放入到HttpSession對象中,驗證碼中的隨機數不區分大小寫
session.setAttribute("rand", randomString.toLowerCase());
String rands=(String) session.getAttribute("rand");
System.out.println("驗證碼生成成功"+rands);
System.out.println("驗證碼生成成功"+randomString.toLowerCase().toString());
//釋放畫筆對象
g.dispose();
//向輸出流中輸出圖像
ImageIO.write(image, "JPEG", response.getOutputStream());
}
}

jsp界麵實現index.jsp和validat.jsp:

 validat.jsp:

<body>
    <img src="checkServlet" /> <a href="validat.jsp" >看不清楚,換張圖片</a>
 </body>


index.jsp:

<head>

<script type="text/javascript">

//看不清圖片,重新加載一張圖像驗證碼
function reloadVercode(){
document.getElementById("authImg").src="auth.jpg?now="+new Date();
}
</script>
</head>


<body>
    <img src="auth.jpg"  /><a href="javascript:void(null)" >看不清,換一張</a>

 </body>

web.xml配置:

<!-- 定義圖像驗證碼的servlet  index.jsp配置-->
  <servlet>
  <servlet-name>img</servlet-name>
  <servlet-class>com.myhome.ImageValidateCode</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>img</servlet-name>
  <url-pattern>/auth.jpg</url-pattern>
  </servlet-mapping>
  
  <!-- 定義圖像驗證碼的servlet  validat.jsp配置-->
    <servlet>
    <servlet-name>CheckServlet</servlet-name>
    <servlet-class>com.myhome.ImageValidateCode</servlet-class>
  </servlet>
   <servlet-mapping>
    <servlet-name>CheckServlet</servlet-name>
    <url-pattern>/checkServlet</url-pattern>
  </servlet-mapping>


效果圖:

 

其他:

package com.myhome;


public class Test {
/**
* 產生隨機字符串
* */
private String getRandomChar()
{
int rand = (int)Math.round(Math.random() * 2);
System.out.println("隨機數:"+rand);
long itmp = 0;
char ctmp = '\u0000';
System.out.println("字符:"+ctmp);
switch (rand)
{
case 1:
itmp = Math.round(Math.random() * 25 + 65);
String s1=getType(itmp);
System.out.println(s1+itmp);
ctmp = (char)itmp;
String s2=getType(ctmp);
System.out.println(s2+itmp);
System.out.println(getType(String.valueOf(ctmp))+String.valueOf(ctmp));
return String.valueOf(ctmp);

case 2:
itmp = Math.round(Math.random() * 25 + 97);
System.out.println(itmp);
ctmp = (char)itmp;
System.out.println(ctmp);
System.out.println(String.valueOf(ctmp));
return String.valueOf(ctmp);
default :
itmp = Math.round(Math.random() * 9);
String.valueOf(itmp);
return  itmp + "";
}
}
/**
* 判斷對象的類型
* */
private <T> String getType(T t)
{
if(t instanceof String)
{
return "String";
}else if(t instanceof Integer)
{
return "int";
}else if(t instanceof Character)
{
return "char";
}else if(t instanceof Long)
{
return "long";
}else {
return "don't know Type of" +t;
}
}
public static void main(String[] args) 
{
Test t=new Test();
t.getRandomChar();
}
}


 


 


 

最後更新:2017-04-04 07:03:38

  上一篇:go 【設計模式】【代理模式,大圖片加載】
  下一篇:go ANDROID打開係統設置或信息界麵