驗證碼基礎
一.什麼是驗證碼及它的作用
:驗證碼爲全自動區分計算機和人類的圖靈測試的縮寫,是一種區分用戶是計算機的公共全自動程序,這個問題可以由計算機生成並評判,但是必須只有人類才能解答.可以防止惡意破解密碼、刷票、論壇灌水、有效防止某個黑客對某一個特定註冊用戶用特定程序暴力破解方式進行不斷的登錄。
二.圖文驗證碼的原理
:在servlet中隨機生成一個指定位置的驗證碼,一般爲四位,然後把該驗證碼保存到session中.在通過Java的繪圖類以圖片的形式輸出該驗證碼。爲了增加驗證碼的安全級別,可以輸出圖片的同時輸出干擾線,最後在用戶提交數據的時候,在服務器端將用戶提交的驗證碼和Session保存的驗證碼進行比較。
三.驗證碼所需的技術
:i.因爲驗證碼中的文字,數字,應爲都是可變的,故要用到隨機生成數技術。
ii.如果驗證碼中包含漢字,則要用到漢字生成技術.
iii.可以使用Ajax技術實現局部刷新
iv.可以使用圖片的縮放和旋轉技術,
vi.隨機繪製干擾線(可以是折現,直線等)
vii.如果考慮到驗證碼的安全性,可以使用MD5加密.
驗證碼模塊實例
1.編寫生成英文,數字,漢字隨機生成的Servlet類.源代碼如下:
- package com.servlet;
- import java.awt.*;
- import java.awt.geom.*;
- import java.awt.image.*;
- import java.io.*;
- import java.util.*;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import javax.imageio.ImageIO;
- public class PictureCheckCode extends HttpServlet {
- private static final long serialVersionUID = 1L;
- public PictureCheckCode() {
- super();
- }
- public void destroy() {
- super.destroy();
- }
- public void init() throws ServletException {
- super.init();
- }
- /*該方法主要作用是獲得隨機生成的顏色*/
- public Color getRandColor(int s,int e){
- Random random=new Random ();
- if(s>255) s=255;
- if(e>255) e=255;
- int r,g,b;
- r=s+random.nextInt(e-s); //隨機生成RGB顏色中的r值
- g=s+random.nextInt(e-s); //隨機生成RGB顏色中的g值
- b=s+random.nextInt(e-s); //隨機生成RGB顏色中的b值
- return new Color(r,g,b);
- }
- @Override
- public void service(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- //設置不緩存圖片
- response.setHeader("Pragma", "No-cache");
- response.setHeader("Cache-Control", "No-cache");
- response.setDateHeader("Expires", 0);
- //指定生成的響應圖片,一定不能缺少這句話,否則錯誤.
- response.setContentType("image/jpeg");
- int width=86,height=22; //指定生成驗證碼的寬度和高度
- BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); //創建BufferedImage對象,其作用相當於一圖片
- Graphics g=image.getGraphics(); //創建Graphics對象,其作用相當於畫筆
- Graphics2D g2d=(Graphics2D)g; //創建Grapchics2D對象
- Random random=new Random();
- Font mfont=new Font("楷體",Font.BOLD,16); //定義字體樣式
- g.setColor(getRandColor(200,250));
- g.fillRect(0, 0, width, height); //繪製背景
- g.setFont(mfont); //設置字體
- g.setColor(getRandColor(180,200));
- //繪製100條顏色和位置全部爲隨機產生的線條,該線條爲2f
- for(int i=0;i<100;i++){
- int x=random.nextInt(width-1);
- int y=random.nextInt(height-1);
- int x1=random.nextInt(6)+1;
- int y1=random.nextInt(12)+1;
- BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL); //定製線條樣式
- Line2D line=new Line2D.Double(x,y,x+x1,y+y1);
- g2d.setStroke(bs);
- g2d.draw(line); //繪製直線
- }
- //輸出由英文,數字,和中文隨機組成的驗證文字,具體的組合方式根據生成隨機數確定。
- String sRand="";
- String ctmp="";
- int itmp=0;
- //制定輸出的驗證碼爲四位
- for(int i=0;i<4;i++){
- switch(random.nextInt(3)){
- case 1: //生成A-Z的字母
- itmp=random.nextInt(26)+65;
- ctmp=String.valueOf((char)itmp);
- break;
- case 2: //生成漢字
- String[] rBase={"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
- //生成第一位區碼
- int r1=random.nextInt(3)+11;
- String str_r1=rBase[r1];
- //生成第二位區碼
- int r2;
- if(r1==13){
- r2=random.nextInt(7);
- }else{
- r2=random.nextInt(16);
- }
- String str_r2=rBase[r2];
- //生成第一位位碼
- int r3=random.nextInt(6)+10;
- String str_r3=rBase[r3];
- //生成第二位位碼
- int r4;
- if(r3==10){
- r4=random.nextInt(15)+1;
- }else if(r3==15){
- r4=random.nextInt(15);
- }else{
- r4=random.nextInt(16);
- }
- String str_r4=rBase[r4];
- //將生成的機內碼轉換爲漢字
- byte[] bytes=new byte[2];
- //將生成的區碼保存到字節數組的第一個元素中
- String str_12=str_r1+str_r2;
- int tempLow=Integer.parseInt(str_12, 16);
- bytes[0]=(byte) tempLow;
- //將生成的位碼保存到字節數組的第二個元素中
- String str_34=str_r3+str_r4;
- int tempHigh=Integer.parseInt(str_34, 16);
- bytes[1]=(byte)tempHigh;
- ctmp=new String(bytes);
- break;
- default:
- itmp=random.nextInt(10)+48;
- ctmp=String.valueOf((char)itmp);
- break;
- }
- sRand+=ctmp;
- Color color=new Color(20+random.nextInt(110),20+random.nextInt(110),random.nextInt(110));
- g.setColor(color);
- //將生成的隨機數進行隨機縮放並旋轉制定角度 PS.建議不要對文字進行縮放與旋轉,因爲這樣圖片可能不正常顯示
- /*將文字旋轉制定角度*/
- Graphics2D g2d_word=(Graphics2D)g;
- AffineTransform trans=new AffineTransform();
- trans.rotate((45)*3.14/180,15*i+8,7);
- /*縮放文字*/
- float scaleSize=random.nextFloat()+0.8f;
- if(scaleSize>1f) scaleSize=1f;
- trans.scale(scaleSize, scaleSize);
- g2d_word.setTransform(trans);
- g.drawString(ctmp, 15*i+18, 14);
- }
- HttpSession session=request.getSession(true);
- session.setAttribute("randCheckCode", sRand);
- g.dispose(); //釋放g所佔用的系統資源
- ImageIO.write(image,"JPEG",response.getOutputStream()); //輸出圖片
- }
- }
2.配置Servlet
在web.xml中的配置如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <servlet>
- <description>輸出驗證碼</description>
- <display-name>This is the display name of my J2EE component</display-name>
- <servlet-name>PictureCheckCode</servlet-name>
- <servlet-class><SPAN style="COLOR: #ff0000">com.servlet.PictureCheckCode</SPAN></servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>PictureCheckCode</servlet-name>
- <url-pattern>/<SPAN style="COLOR: #ff0000">PictureCheckCode</SPAN></url-pattern>
- </servlet-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
3.測試驗證碼
可以編寫JSP頁面來驗證是否可以輸出驗證碼圖片,JSP代碼如下:
1.index.jsp:顯示界面
- <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>驗證碼</title>
- <script language="javascript">
- function myReload() {
- document.getElementById("CreateCheckCode").src = document
- .getElementById("CreateCheckCode").src
- + "?nocache=" + new Date().getTime();
- }
- </script>
- </head>
- <body>
- <form action="Check.jsp" method="post">
- <input name="checkCode" type="text" id="checkCode" title="驗證碼區分大小寫"
- size="8" ,maxlength="4" />
- <img src="PictureCheckCode" id="CreateCheckCode" align="middle">
- <a href="" οnclick="myReload()"> 看不清,換一個</a>
- <input type="submit" value="提交" />
- </form>
- </body>
- </html>
2.Check.jsp :主要驗證提交的數據是否和Session中保存的驗證碼是否相同
- <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
- <html>
- <head>
- <title>驗證碼校驗</title>
- </head>
- <body>
- <%
- String checkcode=request.getParameter("checkCode");
- if(checkcode.equals("")||checkcode==null){
- out.print("<script>alert('請輸入驗證碼');window.location.href('index.jsp')</script>");
- }else{
- if(!checkcode.equalsIgnoreCase((String)session.getAttribute("randCheckCode"))){
- out.print("<script>alert('驗證碼不正確,請重新輸入');history.back(-1);</script>");
- }else{
- out.print("登錄成功");
- }
- }
- %>
- </body>
- </html>
-
js實現點擊驗證碼無刷新重新加載驗證碼圖片
在需要使用驗證碼的網頁文件頭部加上這句
<script language="JavaScript">
function reloadcode(){
var verify=document.getElementById('safecode');
verify.setAttribute('src','images/chknumber.asp?'+Math.random());
//這裏必須加入隨機數不然地址相同我發重新加載
}
</script>
function reloadcode(){
var verify=document.getElementById('safecode');
verify.setAttribute('src','images/chknumber.asp?'+Math.random());
//這裏必須加入隨機數不然地址相同我發重新加載
}
</script>