單一功能學習----簡單的驗證碼,----驗證碼
一、驗證碼的作用
1、防止大量重複請求。一般在登入的時候需要驗證碼,驗證碼的作用就是拖延時間,讓每次登入的操作時間間隔變長,這樣可以防止有人暴力破解密碼登入。
二、設計思路
1、最簡單的驗證碼,就是一串數字了。小時候看到的就是這個樣子的,4個數字。
2、這串數字應該是隨機的。
3、這串數字是可以更換的(以前看到的換一張按鈕)。
4、要有一個輸入框,輸入驗證碼。
5、每登入一次,若失敗應該更換驗證碼。
6、稍微進階一點,驗證碼可以變成一張圖片,防止惡意軟體直接從前端代碼擷取驗證碼值。
7、更進階的驗證碼,可以改變驗證的內容:比如驗證中文,驗證計算結果等;可以改變驗證的方式,比如12306看名稱選圖,比如拖拽圖片驗證;可以改變驗證碼的擷取方式,比如把驗證碼通過簡訊或電話發到使用者的手機,通過郵件發到使用者的郵箱等。(難度略大,在這裡忽略掉這一條)
三、代碼實現
1、最簡單的驗證碼
①前端
1 <div class="yanzhengma">2 <span>驗證碼:</span>3 <input type="text" name="yanzhengma" placeholder="請輸入驗證碼">4 <span id="yanzhengmaInfo">1234</span>5 <span onclick="changeYanzhengmaInfo();">換一張</span>6 </div>
// 改變驗證碼的值function changeYanzhengmaInfo() { var url = contextPath + '/changeYanzhengmaInfo.html?' + new Date().getTime(); $.post(url,function(data) { $("#yanzhengmaInfo").text(data); });}
②後端
1 // 產生驗證碼 2 @Action("/changeYanzhengmaInfo") 3 public void changeYanzhengmaInfo() { 4 // 產生隨機數,四位元,不足四位元(小於1000)的,給設一個值,大於9999的給設一個值 5 Random random = new Random(); 6 int r = random.nextInt(10000); 7 if (r < 1000) { 8 r = 2018; 9 } else if (r > 9999) {10 r = 9999;11 }12 final String yanzhengma = random.nextInt(10000) + "";13 // 把值儲存到session14 final HttpSession session = ServletActionContext.getRequest().getSession();15 session.setAttribute("captcha", yanzhengma);16 // 把值返回到前端17 this.sendResponseMsg(yanzhengma);18 }19 20 /**21 * 驗證驗證碼.22 *23 * @throws UnsupportedEncodingException24 * @author 25 */26 @Action("/checkCaptcha")27 public void checkCaptcha() throws UnsupportedEncodingException {28 this.request.setCharacterEncoding(ENCODE_UTF_8);29 this.response.setContentType(CONTENT_TYPE);30 final String yanzhengma = this.request.getParameter("yanzhengma");31 32 String captcha = this.session.get("captcha");33 if (captcha == null) {34 sendFailMsg("", "驗證碼不存在,請重新整理!");35 return;36 }37 if (captcha.equals(yanzhengma)) {38 this.sendSuccessMsg();39 } else {40 this.sendFailMsg(null, "驗證碼錯誤!");41 }42 }
2、圖片形式的驗證碼
①前端
與上邊的不同,這裡擷取的驗證碼是一張圖片,所以這裡要從後台擷取到的資料應該是驗證碼圖片的連結。通過換連結的方式來達到換驗證碼的效果。
<li> <label class="u_label">驗證碼:</label> <input id="captcha" class="text-input captcha" name="captcha" type="text" placeholder="請輸入驗證碼"> <a href="javascript:;" style="margin-left:20px;"><img id="captcha-img" width="80" height="36" src="${contextPath}/captchaImage.html" /></a> <span><a href="javascript:changeCaptchaImg();" style="height: 40px; line-height: 40px; margin-left: 10px;">換一張</a></span> </li> <span id="captchadwrong" style="margin-left:84px;color:red;display: none">請輸入正確的驗證碼</span>
1 // 改擷取圖片的連結 2 function changeCaptchaImg() { 3 var imgUrl = contextPath + '/captchaImage.html?' + new Date().getTime(); 4 $('#captcha-img').attr('src', imgUrl); 5 } 6 7 // 驗證驗證碼 8 function checkCaptcha() { 9 var captchaValue = $("input[name='captcha']").val();10 var captcha = false;11 var captchadwrong = $('#captchadwrong');12 $.ajax({13 url: contextPath + '/checkCaptcha.html',14 type: 'post',15 dataType: 'json',16 async: false,17 data: { captcha: captchaValue },18 success: function(text) {19 captcha = text.success;20 }21 });22 if (captcha == false) { //失敗23 captchadwrong.css('display', "inline-block");24 captchadwrong.text("請輸入正確的驗證碼");25 return false;26 } else { //成功27 captchadwrong.css('display', "none");28 return true;29 }30 }
②後端
首先,需要引入一個jar包:simplecaptcha-1.2.1.jar
1 @Action("/captchaImage") 2 public void createCaptchaImage() { 3 // 自訂設定字型顏色和大小 最簡單的效果 多種字型隨機顯示 4 final List<java.awt.Color> textColors = Arrays.asList(this.getRandColor(50, 200), this.getRandColor(50, 200)); 5 final List<Font> fontList = Lists.newArrayList(); 6 fontList.add(new Font("Viner Hand ITC", Font.TYPE1_FONT, 52));// 可以設定斜體之類的 7 fontList.add(new Font("Kristen ITC", Font.ITALIC, 45)); 8 fontList.add(new Font("Bradley Hand ITC", Font.HANGING_BASELINE, 52)); 9 fontList.add(new Font("Comic Sans ms", Font.PLAIN, 45));10 // 圖片的背景(漸層,從 white 色到 white 色)11 final GradiatedBackgroundProducer gbp = new GradiatedBackgroundProducer(Color.white, Color.white);12 // 產生驗證碼對象:包括值Answer,時間Timestamp,圖片Image,圖片裡包括顏色,寬高等資訊13 final Captcha captcha = new Captcha.Builder(CAPTCHA_WIDTH, CAPTCHA_HEIGHT).addNoise().addNoise()14 // .gimp(new ShearGimpyRenderer15 // (this.getRandColor(50, 200)))16 .addText(new DefaultTextProducer(RANDOM_NUMBER, MY_CHARS),17 new DefaultWordRenderer(textColors, fontList))18 .addBackground(gbp).build();19 // // 在session中儲存產生的驗證碼20 final HttpSession session = ServletActionContext.getRequest().getSession();21 OutputStream out = null;22 try {23 out = this.response.getOutputStream();24 this.response.reset();25 this.response.setContentType("image/jpeg");26 this.response.setHeader("Pragma", "No-cache");27 this.response.setHeader("Cache-Control", "no-cache");28 this.response.setDateHeader("Expires", 0);29 ImageIO.write(captcha.getImage(), "JPG", out);30 session.setAttribute(CAPTCHA, captcha);31 out.flush();32 out.close();33 this.response.flushBuffer();34 } catch (final IOException e) {35 CaptchaImageAction.LOGGER.error("發送驗證碼IO異常", e);36 } finally {37 if (out != null) {38 try {39 out.close();40 } catch (final IOException e) {41 CaptchaImageAction.LOGGER.error("發送驗證碼IO異常", e);42 }43 }44 }45 }46 47 48 /*49 * 給定範圍獲得隨機顏色50 */51 private Color getRandColor(final int fc, final int bc) {52 int tmpFc = fc;53 int tmpBc = bc;54 final Random random = new Random();55 if (tmpFc > MAX_RANDOM_NUMBER) {56 tmpFc = MAX_RANDOM_NUMBER;57 }58 if (tmpBc > MAX_RANDOM_NUMBER) {59 tmpBc = MAX_RANDOM_NUMBER;60 }61 final int r = tmpFc + random.nextInt(tmpBc - tmpFc);62 final int g = tmpFc + random.nextInt(tmpBc - tmpFc);63 final int b = tmpFc + random.nextInt(tmpBc - tmpFc);64 return new Color(r, g, b);65 }66 67 68 /**69 * 驗證驗證碼.70 *71 * @throws UnsupportedEncodingException72 * @author73 */74 @Action("/checkCaptcha")75 public void checkCaptcha() throws UnsupportedEncodingException {76 this.request.setCharacterEncoding(ENCODE_UTF_8);77 this.response.setContentType(CONTENT_TYPE);78 final String captcha = this.request.getParameter(CaptchaImageAction.CAPTCHA);79 80 Object object = this.session.get(CaptchaImageAction.CAPTCHA);81 if (object == null) {82 sendFailMsg("", "驗證碼不存在,請重新整理!");83 return;84 }85 final Captcha captchaInSession = (Captcha) object;86 final String answer = captchaInSession.getAnswer();87 // 忽略大小寫比較88 if (answer.equalsIgnoreCase(captcha)) {89 this.sendSuccessMsg();90 } else {91 this.sendFailMsg(null, "驗證碼錯誤!");92 }93 }
③