博客部分內容轉載自 LonlySnow的博客:后台java 實現驗證碼生成
1、controller方法
@RequestMapping(value = "/verifycode/img", method = RequestMethod.GET) @ApiOperation("generate image verification code") public void generateImgVerificationCode(HttpServletRequest request, HttpServletResponse response) { try { // int width = 200; // int height = 69; int width = 129; int height = 40; BufferedImage verifyImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 生成對應寬高的初始圖片 // 生成驗證碼字符並加上噪點,干擾線,返回值為驗證碼字符 String randomText = UtilFunctions.drawRandomText(width, height, verifyImg); request.getSession().setAttribute("img_verify_code", randomText.toUpperCase()); request.getSession().setAttribute("img_verify_time", System.currentTimeMillis()); response.setContentType("image/png"); // 必須設置響應內容類型為圖片,否則前台不識別 OutputStream os = response.getOutputStream(); // 獲取文件輸出流 ImageIO.write(verifyImg, "png", os); // 輸出圖片流 os.flush(); os.close(); } catch (Exception e) { UtilFunctions.log.error("msg: {}, exception: {}", e.toString(), e); UtilFunctions.reportError(e.toString(), e); } }
2、生成圖片的方法
public static String drawRandomText(int width, int height, BufferedImage verifyImg) { Graphics2D graphics = (Graphics2D) verifyImg.getGraphics(); graphics.setColor(Color.WHITE);// 設置畫筆顏色-驗證碼背景色 graphics.fillRect(0, 0, width, height);// 填充背景 // graphics.setFont(new Font("微軟雅黑", Font.BOLD, 40)); graphics.setFont(new Font("微軟雅黑", Font.BOLD, 30)); // 數字和字母的組合 //String baseNumLetter = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"; //String baseNumLetter = "2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY"; String baseNumLetter = "123456789"; StringBuffer sBuffer = new StringBuffer(); int x = 10; // 旋轉原點的 x 坐標 String ch = ""; Random random = new Random(); Color textColor = getRandomColor(); for (int i = 0; i < 4; i++) { // graphics.setColor(getRandomColor()); graphics.setColor(textColor); // 設置字體旋轉角度 int degree = random.nextInt() % 30; // 角度小於30度 int dot = random.nextInt(baseNumLetter.length()); ch = baseNumLetter.charAt(dot) + ""; sBuffer.append(ch); // 正向旋轉 graphics.rotate(degree * Math.PI / 180, x, 45); //graphics.drawString(ch, x, 45); graphics.drawString(ch, x, 30); // 反向旋轉 graphics.rotate(-degree * Math.PI / 180, x, 45); //x += 48; x += 30; } // 畫干擾線 for (int i = 0; i < 6; i++) { // 設置隨機顏色 graphics.setColor(getRandomColor()); // 隨機畫線 graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height)); } // 添加噪點 // for (int i = 0; i < 30; i++) { // int x1 = random.nextInt(width); // int y1 = random.nextInt(height); // graphics.setColor(getRandomColor()); // graphics.fillRect(x1, y1, 2, 2); // } return sBuffer.toString(); } private static Color getRandomColor() { Random ran = new Random(); Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); return color; }
3、效果
==========================================================
4、 使用java來畫圖的api
// 得到圖片緩沖區 BufferedImage bi = new BufferedImage(150, 70, BufferedImage.TYPE_INT_RGB); // 得到它的繪制環境(畫圖的筆) Graphics2D g2 = (Graphics2D) bi.getGraphics(); g2.setColor(Color.WHITE);// 設置畫筆顏色,即后面背景色為白色 g2.fillRect(0, 0, 150, 70);// 填充整張圖片(其實就是設置背景色) g2.setColor(Color.BLUE);// 設置畫筆顏色,即后面邊框顏色為藍色 g2.drawRect(0, 0, 150 - 1, 70 - 1);// 設置邊框 g2.setFont(new Font("宋體", Font.BOLD, 18));// 設置字體名稱、樣式、字號 g2.setColor(Color.BLACK);// 設置畫筆顏色,即后面字符串顏色為黑色 g2.drawString("HelloWorld", 20, 40);// 設置字符"H"左下角坐標,向圖片上寫字符串 ImageIO.write(bi, "JPEG", new FileOutputStream("D:/a.jpg"));// 保存圖片
5、生成驗證碼圖片的工具類VerifyCode
package com.oy.demo; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; public class VerifyCode { private int w = 70; private int h = 35; private Random r = new Random(); // {"宋體", "華文楷體", "黑體", "華文新魏", "華文隸書", "微軟雅黑", "楷體_GB2312"} private String[] fontNames = {"宋體", "華文楷體", "黑體", "微軟雅黑", "楷體_GB2312"}; //可選字符 private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; //背景色 private Color bgColor = new Color(255, 255, 255); private String text ; //生成隨機的顏色 private Color randomColor () { int red = r.nextInt(150); int green = r.nextInt(150); int blue = r.nextInt(150); return new Color(red, green, blue); } //生成隨機字體 private Font randomFont () { int index = r.nextInt(fontNames.length); String fontName = fontNames[index]; int style = r.nextInt(4); //生成隨機樣式,0:無樣式,1:粗體,2:斜體,3:粗體+斜體 int size = r.nextInt(5) + 24; //生成隨機字號 return new Font(fontName, style, size); } //畫干擾線 private void drawLine (BufferedImage image) { int num = 3; //總共畫三條干擾線 Graphics2D g2 = (Graphics2D)image.getGraphics(); for(int i = 0; i < num; i++) { //生成兩個點的左邊,即4個值 int x1 = r.nextInt(w); int y1 = r.nextInt(h); int x2 = r.nextInt(w); int y2 = r.nextInt(h); g2.setStroke(new BasicStroke(1.5F)); g2.setColor(Color.BLUE); //設置干擾線顏色為藍色 g2.drawLine(x1, y1, x2, y2); } } //隨機生成一個字符 private char randomChar () { int index = r.nextInt(codes.length()); return codes.charAt(index); } //創建BufferedImage private BufferedImage createImage () { BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D)image.getGraphics(); g2.setColor(this.bgColor); g2.fillRect(0, 0, w, h); return image; } public BufferedImage getImage () { BufferedImage image = createImage(); //創建圖片緩沖區 Graphics2D g2 = (Graphics2D)image.getGraphics();//得到繪制環境,畫筆 StringBuilder sb = new StringBuilder();//用來裝載生成的驗證碼文本 // 向圖片中畫4個字符 for(int i = 0; i < 4; i++) { String s = randomChar() + ""; //隨機生成一個字符 sb.append(s); float x = i * 1.0F * w / 4; //設置當前字符的x軸坐標 g2.setFont(randomFont()); //設置隨機字體 g2.setColor(randomColor()); //設置隨機顏色 g2.drawString(s, x, h-5); //畫圖 } this.text = sb.toString(); //把生成的字符串賦給this.text drawLine(image); //添加干擾線 return image; } //返回驗證碼圖片上的文本 public String getText () { return text; } //保存圖片到指定的輸出流 public static void output (BufferedImage image, OutputStream out) throws IOException { ImageIO.write(image, "JPEG", out); } }
VerifyCode的使用
@Test public void fun() throws FileNotFoundException, IOException { VerifyCode verifyCode = new VerifyCode(); BufferedImage bi = verifyCode.getImage();// 隨機的 System.out.println(verifyCode.getText());// 打印圖片上的文本內容 VerifyCode.output(bi, new FileOutputStream("d:/b.jpg")); }
創建一個Servlet:使用VerifyCode返回圖片驗證碼
public class VerifyCodeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * a、生成圖片; b、保存圖片上的文本到session域中; c、把圖片響應給客戶端。 */ VerifyCode vc = new VerifyCode(); BufferedImage bi = vc.getImage(); // 生成圖片 request.getSession().setAttribute("session_verifyCode", vc.getText()); // 保存圖片上的文本到session域中 VerifyCode.output(bi, response.getOutputStream());// 把圖片響應給客戶端 } }
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'login.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h2>登錄頁面</h2> <% /* * 查找名為"uname"的Cookie,如果存在,將該Cookie的值賦給變量uname */ String uname=""; Cookie[] cs=request.getCookies(); //獲取所有Cookie if(null!=cs){ //如果存在Cookie for(Cookie c:cs){ //遍歷所有Cookie if("uname".equals(c.getName())){ //查找名為"uname"的Cookie uname=c.getValue(); //把名為"uname"的Cookie的值賦給變量uname } } } %> <!-- 顯示登錄錯誤信息 --> <div style="color:red;"> <% String msg=(String)request.getAttribute("msg"); if(null!=msg){ out.print(msg); } %> </div> <% String message_verifyCode=""; String msg_verifyCode=(String)request.getAttribute("msg_verifyCode"); if(null!=msg_verifyCode){ message_verifyCode=msg_verifyCode; } %> <!-- 如果存在名為"uname"的Cookie,將其該Cookie的值輸出到用戶名文本框 --> <form action="/day11_2/LoginServlet" method="post"> 用戶名:<input type="text" name="username" value="<%=uname %>"/><br/> 密 碼:<input type="password" name="password"/><br/> 驗證碼:<input type="text" size="4" name="verifyCode"/> <img id="id_img" src="/day11_2/VerifyCodeServlet"/> <a href="javascript:_change()">看不清,換一張</a> <span style="color:red"><%= message_verifyCode %></span> <br/> <input type="submit" value="登錄"/> </form> </body> <script type="text/javascript"> function _change(){ //獲取<img>元素對象 var imgEle=document.getElementById("id_img"); //給<img>元素的src屬性賦值為"/day11_2/VerifyCodeServlet" //"?a="+new Date().getTime()是為了防止瀏覽器緩存的影響 imgEle.src="/day11_2/VerifyCodeServlet?a="+new Date().getTime(); //alert(1);//用來測試代碼 } </script> </html>
效果: