1. 程式人生 > >簡單的Session案例 —— 一次性驗證碼

簡單的Session案例 —— 一次性驗證碼

exception value ttr app abc [] gre dom 數字

  • 一次性驗證碼的主要目的就是為了限制人們利用工具軟件來暴力猜測密碼,其原理與利用Session防止表單重復提交的原理基本一樣,只是將表單標識號變成了驗證碼的形式,並且要求用戶將提示的驗證碼手工填寫進一個表單字段中,而不是通過表單的隱藏字段自動回傳給服務器。
  • 服務器程序接收到表單數據後,首先判斷用戶是否填寫了正確的驗證碼,只有該驗證碼與服務器端保存的驗證碼匹配時,服務器程序才開始正常的表單處理流程。
  • 密碼猜測工具要逐一嘗試每個密碼的前題條件是先輸入正確的驗證碼,而驗證碼是一次性有效的,這樣基本上就阻斷了密碼猜測工具的自動地處理過程。

表單頁面:

<%@ page contentType
="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${MessageIfo} <form action="<%=request.getContextPath()%>/checkCodeServlet" method="post"> Username:<input type="text" name="username"/>
<br><br> 驗證碼:<input type="text" name="checkCode"/> <br><br> <img src="<%=request.getContextPath()%>/validateColorServlet"> <br><br> <input type="submit" value="登錄"/> </form> </body> </html>

生成驗證碼的Servlet

package yang.mybatis.servlet.checkCode;

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.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * Created by yangshijing on 2017/11/23 0023.
 */
public class ValidateColorServlet extends HttpServlet {

    public static final String CHECK_CODE_KEY = "CHECK_CODE_KEY";

    private static final long serialVersionUID = 1L;

    //設置驗證圖片的寬度, 高度, 驗證碼的個數
    private int width = 152;
    private int height = 40;
    private int codeCount = 4;

    //驗證碼字體的高度
    private int fontHeight = 4;

    //驗證碼中的單個字符基線. 即:驗證碼中的單個字符位於驗證碼圖形左上角的 (codeX, codeY) 位置處
    private int codeX = 0;
    private int codeY = 0;

    //驗證碼由哪些字符組成
    char [] codeSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz23456789".toCharArray();

    //初始化驗證碼圖形屬性
    public void init(){
        fontHeight = height - 2;
        codeX = width / (codeCount + 2);
        codeY = height - 4;
    }

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //定義一個類型為 BufferedImage.TYPE_INT_BGR 類型的圖像緩存
        BufferedImage buffImg = null;
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);

        //在 buffImg 中創建一個 Graphics2D 圖像
        Graphics2D graphics = null;
        graphics = buffImg.createGraphics();

        //設置一個顏色, 使 Graphics2D 對象的後續圖形使用這個顏色
        graphics.setColor(Color.WHITE);

        //填充一個指定的矩形: x - 要填充矩形的 x 坐標; y - 要填充矩形的 y 坐標; width - 要填充矩形的寬度; height - 要填充矩形的高度
        graphics.fillRect(0, 0, width, height);

        //創建一個 Font 對象: name - 字體名稱; style - Font 的樣式常量; size - Font 的點大小
        Font font = null;
        font = new Font("", Font.BOLD, fontHeight);
        //使 Graphics2D 對象的後續圖形使用此字體
        graphics.setFont(font);

        graphics.setColor(Color.BLACK);

        //繪制指定矩形的邊框, 繪制出的矩形將比構件寬一個也高一個像素
        graphics.drawRect(0, 0, width - 1, height - 1);

        //隨機產生 15 條幹擾線, 使圖像中的認證碼不易被其它程序探測到
        Random random = null;
        random = new Random();
        graphics.setColor(Color.GREEN);
        for(int i = 0; i < 15; i++){
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(20);
            int y1 = random.nextInt(20);
            graphics.drawLine(x, y, x + x1, y + y1);
        }

        //創建 randomCode 對象, 用於保存隨機產生的驗證碼, 以便用戶登錄後進行驗證
        StringBuffer randomCode;
        randomCode = new StringBuffer();

        for(int i = 0; i < codeCount; i++){
            //得到隨機產生的驗證碼數字
            String strRand = null;
            strRand = String.valueOf(codeSequence[random.nextInt(36)]);

            //把正在產生的隨機字符放入到 StringBuffer 中
            randomCode.append(strRand);

            //用隨機產生的顏色將驗證碼繪制到圖像中
            graphics.setColor(Color.BLUE);
            graphics.drawString(strRand, (i + 1)* codeX, codeY);
        }

        //再把存放有所有隨機字符的 StringBuffer 對應的字符串放入到 HttpSession 中
        request.getSession().setAttribute(CHECK_CODE_KEY, randomCode.toString());

        //禁止圖像緩存
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        //將圖像輸出到輸出流中
        ServletOutputStream sos = null;
        sos = response.getOutputStream();
        ImageIO.write(buffImg, "jpeg", sos);
        sos.close();
    }
}

表單處理Servlet

package yang.mybatis.servlet.checkCode;

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 java.io.IOException;

/**
 * Created by yangshijing on 2017/11/23 0023.
 */
public class CheckCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        String  check_code_key = (String)session.getAttribute("CHECK_CODE_KEY");
        String checkCode = request.getParameter("checkCode");
        //不區分大小寫
        if(check_code_key != null && !check_code_key.trim().equals("")){
            check_code_key = check_code_key.toLowerCase();
        }
        if (checkCode != null && !checkCode.trim().equals("")){
            checkCode = checkCode.toLowerCase();
        }
        //驗證碼為NULL或者兩者不等,重定向到信息提示頁面
        if(check_code_key == null || checkCode == null && !check_code_key.equals(checkCode)){
            request.getSession().setAttribute("MessageIfo","驗證不一致");
            response.sendRedirect(request.getContextPath()+"/jsp/checkCode/index.jsp");
            return;
        }
        //如果兩個驗證碼一致,處理該表單請求,並移除sesssion域中的屬性值
        session.removeAttribute("CHECK_CODE_KEY");
        response.sendRedirect(request.getContextPath()+"/jsp/token/success.jsp");
    }
}

簡單的Session案例 —— 一次性驗證碼