1. 程式人生 > >---使用HttpSession實現驗證碼功能

---使用HttpSession實現驗證碼功能

原理

原理和使用session來防止表單重複提交一樣,只是在提交的時候,將表單中隱藏域替換成接受使用者輸入的內容。

實現

index.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 'index.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> This is my JSP page. <br> <form action="<%=request.getContextPath()%>/checkCodeServlet" method="post"> Username:<input type="text" name="username" /><br> <br> <br>CheckCode: <input type="text" name="CHECK_CODE_PARAM_CODE" /> <!-- 驗證碼Sevlet --> <img alt="" src="<%=request.getContextPath()%>/validateColorServlet"> <font color="RED"> <%=session.getAttribute("message") == null ? "" : session .getAttribute("message")%> <% session.removeAttribute("message"); %> </font><input type="submit" value="submit" /> </form> </body> </html>

ValidateColorServlet.java

package com.aaa.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;

/**
 * 驗證碼Servlet,返回驗證碼圖片,並且把驗證碼的值放入session中
 * 
 * @author tuxianchao
 * 
 */
public class ValidateColorServlet extends HttpServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public static final String CHECK_CODE_KEY = "CHECK_CODE_KEY";

    // 驗證碼圖片的寬度, 高度, 驗證碼的個數
    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);

        // 隨機產生 100 條幹擾線,
        Random random = null;
        random = new Random();
        graphics.setColor(Color.GREEN);
        for (int i = 0; i < 100; 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());

        System.out.println("產生的驗證碼---" + 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();
    }
}

CheckCodeServlet.java

package com.aaa.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CheckCodeServlet extends HttpServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        // 獲取請求引數:CHECK_CODE_PARAM_NAME

        String checkCodeFromForm = request
                .getParameter("CHECK_CODE_PARAM_CODE");

        // 獲取session的CHECK_CODE_KEY
        String checkCodeFromSession = (String) request.getSession()
                .getAttribute("CHECK_CODE_KEY");
        System.out.println("使用者提交的---" + checkCodeFromForm);
        System.out.println("session中的---" + checkCodeFromSession);
        // 驗證
        if (checkCodeFromForm != null
                & checkCodeFromForm.equals(checkCodeFromSession)) {
            // 合法 ,處理請求
            System.out.println("處理請求....");
        } else {
            // 不合法,返回頁面,提示驗證碼錯誤
            request.getSession().setAttribute("message", "驗證碼錯誤");
            response.sendRedirect(request.getContextPath()
                    + "/checkCode/index.jsp");
        }
    }
}

總結

分析:在訪問index.jsp的時候,驗證碼圖片由一個servlet產生,同時將產生的驗證碼放入session中,在提交到servlet的時候,驗證提交過來的驗證碼和session中的驗證碼是否一致,如果一致正確響應請求,如果不一致,重定向到之前頁面,同時提示驗證碼錯誤。