亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

【Web】Java生成中文GIF動態驗證碼-集成SpringMVC

2019-11-06 06:11:21
字體:
來源:轉載
供稿:網友

轉載請注明出處:http://blog.csdn.net/QQ_26525215本文源自【大學之旅_諳憶的博客】

說明

GIF驗證碼相對于JPG圖片驗證碼來說,要更難破解一些,加大了破解的代價。 從昨天到現在,寫了一個小小的GIF驗證碼項目(中文成語)。 當然,你可以自己修改成字母數字的。我只是單純的覺得中文驗證碼的破解代價更高一點~

我在這里生成GIF圖片的類,用到了國外牛人的三個類,也就是: AnimatedGifEncoder LZWEncoder 和NeuQuant,這三個類。

沒辦法,誰讓自己還沒有那個本事寫出這樣的類呢,只能用別人的,不過挺好用飛,大家可以搜索一下這3個類,一下就能搜出源碼的。 在這里,我就不貼出這三個類的源碼了,需要的,可以在本文最后的項目鏈接拿整個項目,其中有所有源代碼。

本來一開始是寫的字母和數字生成的GIF驗證碼,后來還是改成了漢字成語驗證碼。

在這里,我并沒有用數據庫來存儲成語,因為重點不在哪里,所以就只是建立了一個靜態塊來先寫入成語。 (如果是實際開發,我可能會這樣做: 以便于管理員在后臺可以添加成語到驗證碼成語庫,以及可以刷新驗證碼到成語庫中,所以,可以在一個請求方法中操作成語。 如果用來Redis,基本上也是一樣,實現同步就行。)

GIF驗證碼類

package cn.hncu.utils;import java.awt.*;import java.awt.image.BufferedImage;import java.io.IOException;import java.io.OutputStream;import java.util.ArrayList;import java.util.List;/** * Created with IntelliJ IDEA. * User: 陳浩翔. * Date: 2017/3/6. * Time: 下午 8:23. * Explain:Gif驗證碼類 */public class GifCaptcha { PRivate Font font = new Font("宋體", Font.BOLD, 20); // 字體 private int width = 160; // 驗證碼顯示長度 private int height = 40; // 驗證碼顯示高度 private String Word = ""; // 當前的字符串 private int delay = 100; // 幀延遲 (默認100) private int quality = 10;//量化器取樣間隔 - 默認是10ms private int repeat = 0; // 幀循環次數 private int minColor =0;//設置隨機顏色時,最小的取色范圍 private int maxColor = 255;//設置隨機顏色時,最大的取色范圍 private int right = 0; //設置字符最右邊的相對位置---相對原始位置 ,默認為0 private static java.util.List<String> words = new ArrayList<String>();// 所有成語 //這里應該去數據庫中讀取成語,然后存儲在內存中 //在實際開發中,應該是可以在后臺中添加成語,以及刷新成語到內存中去!利用訪問某個方法來實現 static { words.add("一唱一和"); words.add("一呼百應"); words.add("一干二凈"); words.add("一舉兩得"); words.add("一落千丈"); words.add("兩面三刀"); words.add("六神無主"); words.add("千辛萬苦"); words.add("萬無一失"); words.add("拔刀相助"); words.add("過時黃花"); words.add("地動山搖"); words.add("不可多得"); words.add("滄海一粟"); words.add("水泄不通"); words.add("不可計數"); } /** * 空參構造函數 */ public GifCaptcha() { } /** * 可以設置驗證碼寬度,高度的構造函數 * @param width -驗證碼寬度 * @param height -驗證碼高度 */ public GifCaptcha(int width, int height) { this.width = width; this.height = height; } /** * * @param width -驗證碼寬度 * @param height -驗證碼高度 * @param font -字體 */ public GifCaptcha(int width, int height, Font font) { this(width, height); this.font = font; } /** * @param width -驗證碼寬度 * @param height -驗證碼高度 * @param font -字體 * @param delay -幀延遲 */ public GifCaptcha(int width, int height, Font font,int delay) { this(width, height,font); this.delay = delay; } public Font getFont() { return font; } /** * 設置字體 * @param font */ public void setFont(Font font) { this.font = font; } public int getWidth() { return width; } /** * 設置驗證碼寬度 * @param width */ public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } /** * 設置驗證碼高度 * @param height */ public void setHeight(int height) { this.height = height; } public String getWord() { return word; } /** * 設置驗證碼字符 * @param chars */ public void setWord(String chars) { this.word = chars; } public int getDelay() { return delay; } /** * 設置每一幀之間的延遲時間,或改變它的后續幀(適用于最后一幀添加)。 * @param delay 單位是毫秒 */ public void setDelay(int delay) { this.delay = delay; } public int getQuality() { return quality; } /** * 設置圖像的顏色量化(轉換質量 由GIF規范允許的最大256種顏色)。 * 低的值(最小值= 1)產生更好的顏色,但處理顯著緩慢。 * 10是默認,并產生良好的顏色而且有以合理的速度。 * 值更大(大于20)不產生顯著的改善速度 * @param quality 大于1 */ public void setQuality(int quality) { if(quality<1){ quality=1; } this.quality = quality; } public int getRepeat() { return repeat; } /** * 設置GIF幀應該播放的次數。 * 默認是 0; 0意味著無限循環。 * 必須在添加的第一個圖像之前被調用。 * @param repeat 必須大于等于0 */ public void setRepeat(int repeat) { if (repeat>=0) { this.repeat = repeat; } } public int getRight() { return right; } public void setRight(int right) { this.right = right; } public int getMaxColor() { return maxColor; } public void setMaxColor(int maxColor) { this.maxColor = maxColor; } public int getMinColor() { return minColor; } public void setMinColor(int minColor) { this.minColor = minColor; } /** * 給定一個輸出流 輸入圖片 * @param os */ public void out(OutputStream os) { try { AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder();// gif編碼類 //生成字符 gifEncoder.start(os); gifEncoder.setQuality(quality);//設置量化器取樣間隔 gifEncoder.setDelay(delay);//設置幀延遲 gifEncoder.setRepeat(repeat);//幀循環次數 BufferedImage frame; char[] rands = createWordChar(); Color fontcolor[] = new Color[word.length()]; for (int i = 0; i < word.length(); i++) { fontcolor[i] = getRandomColor(minColor,maxColor); } for (int i = 0; i < word.length(); i++) { frame = graphicsImage(fontcolor, rands, i); gifEncoder.addFrame(frame); frame.flush(); } gifEncoder.finish(); } finally { try { os.close(); } catch (IOException e) { // TODO 異常處理 e.printStackTrace(); } } } /** * 畫隨機碼圖 * * @param fontcolor 隨機字體顏色 * @param strs 字符數組 * @param flag 透明度使用 * @return BufferedImage */ private BufferedImage graphicsImage(Color[] fontcolor, char[] strs, int flag) { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //或得圖形上下文 Graphics2D g2d=image.createGraphics(); //Graphics2D g2d = (Graphics2D) image.getGraphics(); //利用指定顏色填充背景 g2d.setColor(Color.WHITE); g2d.fillRect(0, 0, width, height); AlphaComposite ac; float y = (height >> 1) + (font.getSize() >> 1) ;// 字符的y坐標 float m = (width-(word.length()*font.getSize()))/word.length(); float x = m/2;//字符的x坐標 g2d.setFont(font); for (int i = 0; i < word.length(); i++) { ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getPellucidity(flag, i)); g2d.setComposite(ac); g2d.setColor(fontcolor[i]); g2d.drawOval(Randoms.num(width), Randoms.num(height), Randoms.num(5,30), 5 + Randoms.num(5,30));//繪制橢圓邊框 g2d.drawString(strs[i] + "",x+(font.getSize()+m)*i+right,y); } g2d.dispose(); return image; } /** * 獲取透明度,從0到1,自動計算步長 * @return float 透明度 */ private float getPellucidity(int i, int j) { int num = i + j; float r = (float) 1 / word.length(), s = (word.length() + 1) * r; return num > word.length() ? (num * r - s) : num * r; } /** * 生成隨機字符數組 * @return 字符數組 */ protected char[] createWordChar() { word = words.get(Randoms.num(words.size())); return word.toCharArray(); } /** * 通過給定范圍獲得隨機的顏色 * @return Color 獲得隨機的顏色 */ protected Color getRandomColor(int min, int max) { if (min > 255) { min = 255; } if (max > 255) { max = 255; } if(min<0){ min=0; } if(max<0){ max=0; } if(min>max){ min=0; max=255; } return new Color(min + Randoms.num(max - min), min + Randoms.num(max - min), min + Randoms.num(max - min)); }}

注釋沒寫很多~有點懶~

請求GIF驗證碼的Controller類

package cn.hncu.controller;import cn.hncu.utils.GifCaptcha;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Httpsession;import java.awt.*;import java.io.IOException;/** * Created with IntelliJ IDEA. * User: 陳浩翔. * Date: 2017/3/6. * Time: 下午 8:26. * Explain:演示GIF驗證碼的控制器 */@Controllerpublic class CaptchaController { private Logger logger = LoggerFactory.getLogger(CaptchaController.class); /** * 獲取Gif驗證碼 * @param response */ @RequestMapping(value = "gifCaptcha",method= RequestMethod.GET) public void getGifCaptcha(HttpServletResponse response,HttpServletRequest request){ //告訴客戶端,輸出的格式 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/gif"); GifCaptcha gifCaptcha = new GifCaptcha(200,80,new Font("宋體", Font.BOLD, 40),100); try { gifCaptcha.out(response.getOutputStream()); logger.info("獲取驗證碼!驗證碼字符為:"+gifCaptcha.getWord()); HttpSession session = request.getSession(true); //存入Session session.setAttribute("captchaWord",gifCaptcha.getWord()); } catch (IOException e) { e.printStackTrace(); } } @RequestMapping("index") public String index() { return "index"; }}

jsp頁面

<%-- Created by IntelliJ IDEA. User: 陳浩翔 Date: 2017/3/6 Time: 下午 8:24 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>演示動態驗證碼</title> <script type="text/Javascript"> var path = "${pageScope.basePath}"; function changImg() { var img = document.getElementById("servletImg"); var d = new Date(); var time = d.getTime();//如果沒有這個,下面的img.src = path + "gifCaptcha?" + time;不會起作用,因為瀏覽器的緩存技術,圖片可能并不會刷新 img.src = "";//解決火狐下驗證碼刷不出的問題 img.src = path + "gifCaptcha?" + time; //?號后面的東西是通過get方式傳遞的 } </script></head><body>演示動態驗證碼:<a onclick="javascript:changImg();" href="javascript:void(0);"> <img id="servletImg" src="gifCaptcha" alt="UIFuture驗證碼"/></a></body></html>

演示效果

大家其實可以看到,在我點擊驗證碼的時候,有一個小停頓,會顯示alt的內容,那是因為我在JS中,2次賦值給img的src屬性。 原因是為了解決火狐瀏覽器顯示GIF圖的一個問題,如果我不加那個img.src = “”;,在刷新驗證碼2次后,驗證碼gif圖只顯示第一幀!也就是變成了靜態圖~但是接收到的圖片其實還是GIF動圖。 我加img.src = “”;,就只是為了解決火狐上驗證碼刷新2次后會變成靜圖的問題,該問題在谷歌瀏覽器,以及360瀏覽器上沒有出現!

有知道原因的請評論,謝謝

出問題的是下面這樣的情況,在第三次點擊圖片刷新時(此時用的是同一張圖片,隨機圖片出現的問題是一樣的,也就是只顯示GIF動圖的第一幀圖片)(火狐瀏覽器) 谷歌瀏覽器,360瀏覽器沒有出現該問題。

本篇博客涉及到的源碼鏈接:

【->點擊訪問源碼-?CHX】

本文章由[諳憶]編寫, 所有權利保留。 歡迎轉載,分享是進步的源泉。

轉載請注明出處:http://blog.csdn.net/qq_26525215本文源自【大學之旅_諳憶的博客】


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久视频在线| 日韩欧美在线国产| 成人午夜在线视频一区| 国产精品久久久久久久久久新婚| 成人免费视频97| 国产精品久久久久国产a级| 欧美性视频精品| 久久久久北条麻妃免费看| 91精品国产高清久久久久久| 久热精品在线视频| 中文字幕日韩欧美在线视频| 亚洲精品自在久久| 久久久国产精品免费| 国产精品久久久久久中文字| 久久精品99久久久香蕉| 欧美性xxxxx极品娇小| 欧美日韩在线视频观看| 欧美怡春院一区二区三区| 538国产精品一区二区在线| 亚洲色图欧美制服丝袜另类第一页| 久久国产精品视频| 久久久久久久久国产| 成人中文字幕在线观看| 国产成人精品最新| 欧美日韩国产成人在线| 中文字幕亚洲欧美日韩在线不卡| 日本国产高清不卡| 欧美激情视频在线观看| 日韩中文在线不卡| 91国语精品自产拍在线观看性色| 日韩欧美成人免费视频| 亚洲国产三级网| 国产精品成熟老女人| 91久久精品视频| 777精品视频| 亚洲全黄一级网站| 久久亚洲影音av资源网| 国产欧美一区二区三区久久人妖| 日韩在线观看免费| 亚洲综合最新在线| 亚洲成人网av| 国产精品久久久久免费a∨大胸| 国产一区二区激情| 久久久久久久久久av| 92裸体在线视频网站| 色诱女教师一区二区三区| 国产成人av网址| 亚洲精品久久久久久久久久久| 国产女人精品视频| 伊人亚洲福利一区二区三区| 国产亚洲精品久久久久久| 97国产在线视频| 欧美极品少妇xxxxⅹ免费视频| 久久躁日日躁aaaaxxxx| 欧美乱大交xxxxx另类电影| 亚洲色图18p| www.欧美精品| 欧美在线观看视频| 中文国产成人精品| 亚洲天堂av在线免费观看| 亚洲欧美999| 亚洲国产97在线精品一区| 欧美一区二区大胆人体摄影专业网站| 国产精品日韩在线一区| …久久精品99久久香蕉国产| 欧美一级大胆视频| 欧美伊久线香蕉线新在线| 国产精品久久久久影院日本| 欧美激情第1页| 国产精品久久久久久亚洲影视| 久久99精品视频一区97| 亚洲免费小视频| 国内揄拍国内精品少妇国语| 久久久久女教师免费一区| 琪琪第一精品导航| 日韩电影中文字幕在线观看| 日本精品久久久久久久| 国内揄拍国内精品少妇国语| 6080yy精品一区二区三区| 亚洲欧美日韩在线高清直播| 日韩大陆欧美高清视频区| 国产精品∨欧美精品v日韩精品| 国产亚洲福利一区| 精品日本高清在线播放| 91精品国产乱码久久久久久蜜臀| 国产精品青青在线观看爽香蕉| 欧美放荡办公室videos4k| 97人洗澡人人免费公开视频碰碰碰| 国内精品小视频| 国产成人激情小视频| 精品欧美一区二区三区| 疯狂欧美牲乱大交777| 91免费看片网站| 久久国产精品久久精品| 久久久久久久激情视频| 国产精品老牛影院在线观看| 91精品在线影院| 91国自产精品中文字幕亚洲| 国产精品亚洲综合天堂夜夜| 久久影院资源站| 福利一区视频在线观看| 国产精品扒开腿做爽爽爽的视频| 亚洲精品永久免费精品| 亚洲国产精品资源| 国产亚洲一区二区在线| 日韩久久免费视频| 欧美黄色免费网站| 亚洲激情免费观看| 国产v综合ⅴ日韩v欧美大片| 国产精品视频一区国模私拍| 国产综合久久久久久| 亚洲国产精品久久久| 日韩免费在线视频| 成人午夜激情免费视频| 欧美午夜精品在线| 亚洲激情在线观看| 久久视频在线观看免费| 亚洲人成伊人成综合网久久久| 日韩网站免费观看| 欧美亚洲在线播放| 国产精品免费一区豆花| 国产午夜精品一区二区三区| 日韩中文字幕精品| 91av在线精品| 日韩在线精品一区| 久久影院在线观看| 日韩免费观看在线观看| 91av在线看| 欧美日韩在线视频首页| 中文国产亚洲喷潮| 黑人精品xxx一区一二区| 97精品一区二区三区| 色狠狠久久aa北条麻妃| 国产精品自拍视频| 欧美日韩在线另类| 国产成人在线视频| 91精品免费久久久久久久久| 日韩一区二区三区国产| 亚洲国产成人久久综合| 色视频www在线播放国产成人| 国产亚洲一级高清| 欧美激情在线有限公司| 国产精品视频大全| 亚洲精品国产精品国产自| 国产不卡精品视男人的天堂| 成人日韩在线电影| 国产精品久久久久久久久久新婚| 国产精品美女午夜av| 91po在线观看91精品国产性色| 日韩精品999| 国产精品亚洲一区二区三区| 一区二区三区美女xx视频| 黑人巨大精品欧美一区二区一视频| 欧美性猛交xxxx乱大交蜜桃| 777国产偷窥盗摄精品视频| 久久激情视频久久| 国产主播精品在线| 中文字幕在线成人| 久久亚洲春色中文字幕| 91国语精品自产拍在线观看性色| 久久久久久高潮国产精品视| 国产精品一区=区| 欧美极品美女电影一区| 日韩精品在线观看一区|