JavaWeb實(shí)現(xiàn)登錄驗(yàn)證碼

在登錄界面中使用圖片驗(yàn)證碼, 對(duì)于現(xiàn)在的web應(yīng)用到處可見(jiàn).

話不多說(shuō), 開(kāi)始寫(xiě)代碼了!
首先, 新建一個(gè)JSP, 表示登錄界面:
login3.jsp文件:

<%--
  User: menglanyingfei
  Date: 2018/1/12
  Time: 16:16
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>登錄界面</title>
</head>
<body>
<%

    // 獲取瀏覽器發(fā)送過(guò)來(lái)的cookie, 獲取用戶(hù)信息
    Cookie[] cookies = request.getCookies();
    String username = "";
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if ("username".equals(cookie.getName())) {
                username = cookie.getValue();
            }
        }
    }
%>
<font color="red">${requestScope.message}</font>
<form action="/day_1_12/LoginServlet3" method="post">
    用戶(hù)名:<input type="text" name="username" value="<%= username%>"><font color="red">${requestScope.error}</font>
    <br>
    密碼:<input type="password" name="password">
    <br>
    驗(yàn)證碼:<input type="text" name="image">
    <img src="/day_1_12/VerifyCodeServlet">
    <input type="button" value="看不清? 換一張." id="btn"><font color="red">${requestScope.imageMess}</font>
    <br>
    <input type="submit" value="登錄">
</form>
<script type="text/javascript">

    document.getElementById("btn").onclick = function () {
        // 獲取img元素
        // 為了讓瀏覽器發(fā)送請(qǐng)求到servlet, 所以一定要改變src
        document.getElementsByTagName("img")[0].src =
            "/day_1_12/VerifyCodeServlet?time=" + new Date().getTime();
    };
</script>

</body>
</html>

界面就是這樣, 當(dāng)然, 你肯定現(xiàn)在出來(lái)不了這個(gè)效果! 沒(méi)事, 接著往下看吧!


登錄界面.png

然后, 新建一個(gè)Servlet:
VerifyCodeServlet.java文件, 因?yàn)檫@里配置了@WebServlet注解, 所以無(wú)需在web.xml中配置!

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * 用來(lái)生成圖片驗(yàn)證碼
 * Created by menglanyingfei on 2018/1/12.
 */
@WebServlet(name = "VerifyCodeServlet", value = "/VerifyCodeServlet")
public class VerifyCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //創(chuàng)建對(duì)象
        VerifyCode vc = new VerifyCode();
        //獲取圖片對(duì)象
        BufferedImage bi = vc.getImage();
        //獲得圖片的文本內(nèi)容
        String text = vc.getText();
        // 將系統(tǒng)生成的文本內(nèi)容保存到session中
        request.getSession().setAttribute("text", text);
        //向?yàn)g覽器輸出圖片
        vc.output(bi, response.getOutputStream());

    }
}

在同一包下, 新建一個(gè)Java文件VerifyCode.java(具體的代碼意思, 可以看注釋, 已經(jīng)寫(xiě)得非常清楚了!):

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

public class VerifyCode {
    private int w = 70;
    private int h = 35;
    private Random r = new Random();
    // {"宋體", "華文楷體", "黑體", "華文新魏", "華文隸書(shū)", "微軟雅黑", "楷體_GB2312"}
    private String[] fontNames  = {"宋體", "華文楷體", "黑體", "微軟雅黑", "楷體_GB2312"};
    // 可選字符
    private String codes  = "0123456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
    // 背景色
    private Color bgColor  = new Color(255, 255, 255);
    // 驗(yàn)證碼上的文本
    private String text ;
    
    // 生成隨機(jī)的顏色
    private Color randomColor () {
        int red = r.nextInt(150);
        int green = r.nextInt(150);
        int blue = r.nextInt(150);
        return new Color(red, green, blue);
    }
    
    // 生成隨機(jī)的字體
    private Font randomFont () {
        int index = r.nextInt(fontNames.length);
        String fontName = fontNames[index];//生成隨機(jī)的字體名稱(chēng)
        int style = r.nextInt(4);//生成隨機(jī)的樣式, 0(無(wú)樣式), 1(粗體), 2(斜體), 3(粗體+斜體)
        int size = r.nextInt(5) + 24; //生成隨機(jī)字號(hào), 24 ~ 28
        return new Font(fontName, style, size);
    }
    
    // 畫(huà)干擾線
    private void drawLine (BufferedImage image) {
        int num  = 3;//一共畫(huà)3條
        Graphics2D g2 = (Graphics2D)image.getGraphics();
        for(int i = 0; i < num; i++) {//生成兩個(gè)點(diǎn)的坐標(biāo)赘那,即4個(gè)值
            int x1 = r.nextInt(w);
            int y1 = r.nextInt(h);
            int x2 = r.nextInt(w);
            int y2 = r.nextInt(h); 
            g2.setStroke(new BasicStroke(1.5F)); 
            g2.setColor(Color.BLUE); //干擾線是藍(lán)色
            g2.drawLine(x1, y1, x2, y2);//畫(huà)線
        }
    }
    
    // 隨機(jī)生成一個(gè)字符
    private char randomChar () {
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }
    
    // 創(chuàng)建BufferedImage
    private BufferedImage createImage () {
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
        Graphics2D g2 = (Graphics2D)image.getGraphics(); 
        g2.setColor(this.bgColor);
        g2.fillRect(0, 0, w, h);
        return image;
    }
    
    // 調(diào)用這個(gè)方法得到驗(yàn)證碼
    public BufferedImage getImage () {
        BufferedImage image = createImage();//創(chuàng)建圖片緩沖區(qū) 
        Graphics2D g2 = (Graphics2D)image.getGraphics();//得到繪制環(huán)境
        StringBuilder sb = new StringBuilder();//用來(lái)裝載生成的驗(yàn)證碼文本
        // 向圖片中畫(huà)4個(gè)字符
        for(int i = 0; i < 4; i++)  {//循環(huán)四次,每次生成一個(gè)字符
            String s = randomChar() + "";//隨機(jī)生成一個(gè)字母 
            sb.append(s); //把字母添加到sb中
            float x = i * 1.0F * w / 4; //設(shè)置當(dāng)前字符的x軸坐標(biāo)
            g2.setFont(randomFont()); //設(shè)置隨機(jī)字體
            g2.setColor(randomColor()); //設(shè)置隨機(jī)顏色
            g2.drawString(s, x, h-5); //畫(huà)圖
        }
        this.text = sb.toString(); //把生成的字符串賦給了this.text
        drawLine(image); //添加干擾線
        return image;       
    }
    
    // 返回驗(yàn)證碼圖片上的文本
    public String getText () {
        return text;
    }
    
    // 保存圖片到指定的輸出流
    public static void output (BufferedImage image, OutputStream out) 
                throws IOException {
        ImageIO.write(image, "JPEG", out);
    }
}


處理登錄邏輯的Servlet(LoginServlet3.java):

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by menglanyingfei on 2018/1/12.
 */
@WebServlet(name = "LoginServlet3", value = "/LoginServlet3")
public class LoginServlet3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 編碼
        request.setCharacterEncoding("utf-8");
        // 獲取請(qǐng)求參數(shù)
        /*
            拿到頁(yè)面?zhèn)鬟^(guò)來(lái)的手動(dòng)輸入的驗(yàn)證碼, 該驗(yàn)證碼要和生成圖片上的
            文本驗(yàn)證碼比較, 如果相同, 驗(yàn)證碼輸入成功!
         */
        String imageText = request.getParameter("image");
        // 圖片的驗(yàn)證碼
        String text = (String) request.getSession().getAttribute("text");

        if (!text.equalsIgnoreCase(imageText)) {
            request.setAttribute("imageMess", "驗(yàn)證碼輸入錯(cuò)誤!");
            request.getRequestDispatcher("/jsp/login3.jsp").forward(request, response);
        }
        // 獲取用戶(hù)名和密碼
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if ("haha".equals(username) && "123".equals(password)) {
            // 將用戶(hù)信息保存到session中
            request.getSession().setAttribute("username", username);

            // 使用cookie實(shí)現(xiàn)回寫(xiě)用戶(hù)名
            Cookie cookie = new Cookie("username", username);
            cookie.setMaxAge(60 * 60);
            // 通過(guò)響應(yīng)頭發(fā)送cookie
            response.addCookie(cookie);
            // 重定向登錄成功界面
            response.sendRedirect(request.getContextPath() + "/jsp/success2.jsp");
        } else {
            request.setAttribute("error", "用戶(hù)名或密碼錯(cuò)誤!");
            request.getRequestDispatcher("/jsp/login3.jsp").forward(request, response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

登錄成功后的界面:(success2.jsp)

<%--
  User: menglanyingfei
  Date: 2018/1/12
  Time: 16:44
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>成功登錄</title>
</head>
<body>
<%
    // 獲取用戶(hù)信息
    String username = (String) session.getAttribute("username");

    if (username == null) {
        // 保存錯(cuò)誤信息到request中, 然后轉(zhuǎn)發(fā)到login3.jsp中, 提醒登錄
        request.setAttribute("message", "請(qǐng)登錄!");

        // 轉(zhuǎn)發(fā)到登錄頁(yè)面
        request.getRequestDispatcher("/jsp/login3.jsp").forward(request, response);
    }
%>
<h2>歡迎登錄:${sessionScope.username}!!!</h2>
</body>
</html>

最后, 演示登錄:
因?yàn)? 用戶(hù)名haha和密碼123已經(jīng)寫(xiě)死在代碼里了!


登錄.png

成功.png

完整代碼地址

https://github.com/menglanyingfei/Java/tree/master/JavaWebTrain/day_1_12

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末负甸,一起剝皮案震驚了整個(gè)濱河市峡谊,隨后出現(xiàn)的幾起案子蛹头,更是在濱河造成了極大的恐慌视译,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浸须,死亡現(xiàn)場(chǎng)離奇詭異吧秕,居然都是意外死亡琉闪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)砸彬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颠毙,“玉大人,你說(shuō)我怎么就攤上這事砂碉≈郏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵增蹭,是天一觀的道長(zhǎng)滴某。 經(jīng)常有香客問(wèn)我,道長(zhǎng)滋迈,這世上最難降的妖魔是什么霎奢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮饼灿,結(jié)果婚禮上幕侠,老公的妹妹穿的比我還像新娘。我一直安慰自己碍彭,他們只是感情好晤硕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著庇忌,像睡著了一般舞箍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上皆疹,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天创译,我揣著相機(jī)與錄音,去河邊找鬼墙基。 笑死软族,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的残制。 我是一名探鬼主播立砸,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼初茶!你這毒婦竟也來(lái)了颗祝?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恼布,失蹤者是張志新(化名)和其女友劉穎螺戳,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體折汞,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倔幼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了爽待。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片损同。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鸟款,靈堂內(nèi)的尸體忽然破棺而出膏燃,到底是詐尸還是另有隱情,我是刑警寧澤何什,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布组哩,位于F島的核電站,受9級(jí)特大地震影響处渣,放射性物質(zhì)發(fā)生泄漏伶贰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一霍比、第九天 我趴在偏房一處隱蔽的房頂上張望幕袱。 院中可真熱鬧,春花似錦悠瞬、人聲如沸们豌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)望迎。三九已至,卻和暖如春凌外,著一層夾襖步出監(jiān)牢的瞬間辩尊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工康辑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摄欲,地道東北人轿亮。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像胸墙,于是被迫代替她去往敵國(guó)和親我注。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,811評(píng)論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法迟隅,類(lèi)相關(guān)的語(yǔ)法但骨,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法智袭,異常的語(yǔ)法奔缠,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,639評(píng)論 18 399
  • 人在草木間,茶語(yǔ)人生 我的家鄉(xiāng)不產(chǎn)茶吼野,對(duì)茶很陌生校哎。小時(shí)候只知道有茯茶,喝起來(lái)覺(jué)得平淡無(wú)味箫锤。等到品出茶味來(lái)贬蛙,源于青年...
    瑨瑀軒馬永紅閱讀 550評(píng)論 3 3
  • 工作壓力大,天天熬夜谚攒,黑眼圈眼袋都出來(lái)了阳准。快來(lái)讓眼膜幫你去除黑眼圈馏臭,眼袋野蝇。什么牌子的眼膜比較好呢?為大家整理了眼膜...
    Angelxie閱讀 1,053評(píng)論 0 0