1. 程式人生 > >response生成圖片驗證碼

response生成圖片驗證碼

伺服器對客戶端瀏覽器做出的響應被封裝成一個HttpResponse物件。要對瀏覽器進行操作,只需要操作HttpRespones物件,通過HttpServletResponse.getWriter()獲得PrintWriter,該物件為outputStream的子類。然後使用該物件輸出資訊即可。 

本例將使用Servlet輸出圖片驗證碼。圖片驗證碼的原理是,伺服器生成一個包含隨即的字串圖片發給客戶端,客戶端提交資料時需要填寫字串作為驗證資訊。由於字串儲存在圖片裡,因此機器很難識別,從而達到防止有人使用計算機程式惡意傳送資訊的目的。 

本帖由卡菲牛奶撰寫,原文請訪問http://fuchangle.iteye.com/blog/1325408 


開始正文 
Servlet輸出圖片時,需要呼叫getOutputStream輸出圖片,程式碼如下: 

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
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;

public class IdentityServlet extends HttpServlet{
	public static final char[] CHARS={'2','3','4','5','6','7','8','9','A','B','C',
		'D','E','F','G','H','K','M','L','N','L','X','Y','Z','Q'};
	public static Random random=new Random();
	
	public static String getRandomString(){
		StringBuffer buffer=new StringBuffer();
		//隨即產生6位數
		for(int i=0;i<6;i++){
			buffer.append(CHARS[random.nextInt(CHARS.length)]);
		}
		System.out.println(buffer.toString());
		return buffer.toString();
	}
	//獲取隨即的顏色
	public static Color getRandomColor(){
		return new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255));
	}
	//返回某顏色的反色
	public static Color getReverseColor(Color c){
		return new Color(255-c.getRed(), 255-c.getGreen(),255-c.getBlue());
	}
	
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("image/jpeg");
		
		String randomString=getRandomString();
		request.getSession().setAttribute("randomString", randomString);
		int width=100;//圖片寬度
		int height=30;//圖片高度
		
		Color color=getRandomColor();	//隨即顏色。用於背景顏色
		Color reverse=getReverseColor(color);//反色,用於前背景
		//建立一個彩色圖片
		BufferedImage bi=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//獲取繪圖物件
		Graphics2D g=bi.createGraphics();
		g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));//設定字型
		g.setColor(color);	//設定顏色
		g.fillRect(0, 0, width, height);//繪製背景
		g.setColor(reverse);//設定顏色
		g.drawString(randomString, 18, 20);
		
		for(int i=0;i<100;i++){
			g.drawRect(random.nextInt(width), random.nextInt(height),1, 1); //隨即噪音點
		}
		
		ServletOutputStream out=response.getOutputStream();	//轉換JPEG格式
		
		JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(out); //編碼器
		encoder.encode(bi);
		out.flush();	//輸出到客戶端
	}
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
	}
}


程式碼中利用一個隨機數生成Random與char[]型別的字元字典生成隨即字串,字元字典裡將比較容易混淆的0和O,1和I等都去掉,然後生成一個長100寬30的圖片利用隨即顏色填充背景,利用反色在前面繪製隨即字元,並畫出100個位置隨即 的噪點,增加圖片的識別難度  

該Servlet需要配置到web.xml中,程式碼如下: 
web.xml 

  <servlet>
  		<servlet-name>IdentityServlet</servlet-name>
  		<servlet-class>com.shxt.IdentityServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  		<servlet-name>IdentityServlet</servlet-name>
  		<url-pattern>/servlet/IdentityServlet</url-pattern>
  </servlet-mapping>

然後訪問該Servlet就可以預覽圖片啦。為了演示方面,下面用一個HTML檔案引用這個圖片驗證碼,程式碼如下:

   <script type="text/javascript">
		function reloadImage(){
			document.getElementById('btn').disabled=true;
			document.getElementById('identity').src='servlet/IdentityServlet?ts='+new Date().getTime();
		}
	
	</script>

     <body>
  		<img  src="servlet/IdentityServlet" id="identity" onload="btn.disabled=false;">
  		<input type="button" value="更換圖片" onclick="reloadImage()" id="btn">
  </body>

我們搞定了!自己測試吧!