原理
伺服器生成一個包含随機的字元串的圖檔發給用戶端,用戶端送出資料時需要填寫字元串作為驗證。在伺服器端,字元串儲存在 session 中,當擷取到用戶端上傳的字元串參數時,對比是否相等。
運作結果圖:
實作
生成圖檔驗證碼的 Servlet 類
package cn.joker.servlet;
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.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
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 implementation class IdentityServlet
*/
@WebServlet(description = "response生成圖檔驗證碼", urlPatterns = { "/IdentityServlet" })
public class IdentityServlet extends HttpServlet {
private static final long serialVersionUID = L;
//随機字元
private static final char[] CHARS = {'2','3','4','5','6','7','8','9','A','B','C','D',
'E','F','G','H','I','J'};
//随機數
private Random random = new Random();
/**
* @see HttpServlet#HttpServlet()
*/
public IdentityServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//response.getWriter().append("Served at: ").append(request.getContextPath());
// 設定輸出類型
response.setContentType("image/jpeg");
response.setDateHeader("expries", -);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
// 擷取随機字元串
String randomString = getRandomString();
//System.out.println(randomString);
// 放到session 中
request.getSession(true).setAttribute("randomString", randomString);
// 圖檔的寬度、高度
int width = ,height=;
//用于背景色
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,));
g.setColor(color);
g.fillRect(, , width, height);
g.setColor(reverse);
g.drawString(randomString, , );
// 繪制噪聲點
for(int i = ,n = random.nextInt();i<n;i++) {
g.drawRect(random.nextInt(width), random.nextInt(height), , );
}
/* 方法一:
* ServletOutputStream out = response.getOutputStream();
// 轉成JPEG格式
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
// 對圖檔進行編碼
encoder.encode(bi);
out.flush();*/
ImageIO.write(bi, "jpg", response.getOutputStream());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
/**
* 擷取六位随機字元
*/
public String getRandomString() {
StringBuffer buffer = new StringBuffer();
for(int i = ; i<;i++) {
buffer.append(CHARS[random.nextInt()]);
}
return buffer.toString();
}
/**
* 擷取随機顔色
*/
public Color getRandomColor() {
return new Color(random.nextInt(),random.nextInt(),random.nextInt());
}
/**
* 擷取某顔色的反色
*/
public Color getReverseColor(Color c) {
return new Color(-c.getRed(),-c.getGreen(),-c.getBlue());
}
}
顯示界面(作為首頁使用)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>圖檔驗證</title>
<script type="text/javascript">
function reloadImage(){
document.getElementById('btn').disabled = true;
//實時更新,保證每次都從伺服器重新請求資料
document.getElementById('identity').src = '/ServletStudy/IdentityServlet?ts='+new Date().getTime();
}
</script>
</head>
<body>
<img alt="驗證碼" src="/ServletStudy/IdentityServlet" id="identity" onload="btn.disabled = false;" />
<input type="button" id="btn" value="換個圖檔" onclick="reloadImage()">
<form action="/ServletStudy/CheckIdentity" method="post">
驗證碼: <input type="text" name="check">
<input type="submit" value="送出">
</form>
</body>
</html>
校驗驗證碼的 Servlet
package cn.joker.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class CheckIdentity
*/
@WebServlet(description = "校驗驗證碼", urlPatterns = { "/CheckIdentity" })
public class CheckIdentity extends HttpServlet {
private static final long serialVersionUID = L;
/**
* @see HttpServlet#HttpServlet()
*/
public CheckIdentity() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 擷取用戶端上傳的資料
String ch = request.getParameter("check");
// 擷取session 中儲存的資料
String id = (String) request.getSession().getAttribute("randomString");
if(ch.equals(id))
response.getWriter().append("<!DOCTYPE html>\r\n" +
"<html>\r\n" +
"<head>\r\n" +
"<meta charset=\"UTF-8\"></head>\r\n" +
"<body>").append("驗證碼通過").append("</body>\r\n" +
"</html>");
else
response.getWriter().append("<!DOCTYPE html>\r\n" +
"<html>\r\n" +
"<head>\r\n" +
"<meta charset=\"UTF-8\"></head>\r\n" +
"<body>").append("驗證碼錯誤").append("</body>\r\n" +
"</html>");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
隻要正确設定 response 輸出類型及輸出流,就能輸出很多的格式資料,例如Excel、PDF、Word、MP3等。不同的輸出類型需要聲明不同的 Content-Type 屬性,例如JPG圖檔是 “image/jpeg”,Word 則是 “application/msword”。
代碼及内容大部分來源于Java Web 整合開發 王者歸來