一. 需求
- 訪問帶有驗證碼的登錄頁面 login.jsp。
- 用戶輸入用戶名、密碼、驗證碼。
- 如果用戶名或密碼輸入錯誤,跳轉至登錄頁面,提示:用戶名或密碼錯誤
- 如果驗證碼輸入錯誤,跳轉至登錄頁面,提示:驗證碼錯誤
- 如果全部輸入正確,跳轉至主頁 success.jsp,顯示:用戶名,歡迎您!
二. 分析
三. 開發步驟
VerificationCodeServlet.java,參考:四. response Demo - 4. 驗證碼
package com.hjplz.servlet;
import javax.imageio.ImageIO;
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.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/verificationCodeServlet")
public class VerificationCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100; // 驗證碼圖片的寬度
int height = 50; // 驗證碼圖片的高度
// 1. 創建一個對象,代表在內存中的驗證碼圖片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2. 美化圖片
// 2.1 填充背景色
Graphics g = image.getGraphics(); // 畫筆對象
g.setColor(Color.PINK); // 設置畫筆顏色
g.fillRect(0, 0, width, height);
// 2.2 畫邊框
g.setColor(Color.BLUE);
// 邊框佔 1 像素,所以寬高相應 - 1
g.drawRect(0, 0, width - 1, height - 1);
// 2.3 寫驗證碼
StringBuilder sb = new StringBuilder();
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random ran = new Random();
// 隨機生成四個驗證碼字符
for(int i = 1; i <= 4; i++) {
// 生成隨機角標
int index = ran.nextInt(str.length());
// 獲取隨機字符
char ch = str.charAt(index);
sb.append(ch);
g.drawString(ch + "", width / 5 * i, height / 2);
}
// 將驗證碼存入 Session 中
String code = sb.toString();
request.getSession().setAttribute("code_session", code);
// 2.4 畫干擾線
g.setColor(Color.GREEN);
// 隨機生成 10 條幹擾線
for(int i = 0; i < 10; i++) {
// 隨機生成 4 個座標點
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1, x2, y1, y2);
}
// 3. 將圖片輸出到頁面
ImageIO.write(image, "jpg", response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
LoginServlet.java
package com.hjplz.servlet;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 設置 request 編碼格式
request.setCharacterEncoding("UTF-8");
// 2. 獲取參數
String username = request.getParameter("username");
String password = request.getParameter("password");
String code = request.getParameter("code");
// 3. 獲取生成的驗證碼
String code_session = (String)request.getSession().getAttribute("code_session");
HttpSession session = request.getSession();
// 刪除 session 中存儲的驗證碼
session.removeAttribute("code_session");
// 4. 判斷驗證碼是否正確,忽略大小寫比較
if(code_session == null) { // 用戶已登錄(使用過此驗證碼)
// 轉發到登錄頁面
request.getRequestDispatcher("login.jsp").forward(request, response);
}
else if(code_session.equalsIgnoreCase(code)) { // 驗證碼正確
// 判斷用戶名和密碼是否正確,應該由 UserDao 的 login() 判斷
if("admin".equals(username) && "123".equals(password)) { // 登錄成功
// 在 Session 中存儲用戶信息
session.setAttribute("username", username);
// 重定向到 success.jsp
response.sendRedirect(request.getContextPath() + "/success.jsp");
}
else { // 登錄失敗
// 在 request 中存儲信息
request.setAttribute("login_error", "用戶名或密碼錯誤");
// 轉發到登錄頁面
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
else { // 驗證碼錯誤
// 在 request 中存儲信息
request.setAttribute("code_error", "驗證碼錯誤");
// 轉發到登錄頁面
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</title>
<style>
div {
color: red;
}
</style>
</head>
<body>
<form action="/verification_code/loginServlet" method="post">
<table>
<tr>
<td>用戶名</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>密碼</td>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td>驗證碼</td>
<td><input type="text" name="code"/></td>
</tr>
<tr>
<td colspan="2"><img id="img" src="/verification_code/verificationCodeServlet"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登錄"></td>
</tr>
</table>
</form>
<div><%= request.getAttribute("code_error") == null ? "" : request.getAttribute("code_error")%></div>
<div><%= request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%></div>
</body>
<script>
window.onload = function() {
document.getElementById("img").onclick = function() {
// 添加時間戳防止獲取瀏覽器緩存結果
this.src = "/verification_code/verificationCodeServlet?time=" + new Date().getTime();
}
}
</script>
</html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
<h1><%= request.getSession().getAttribute("username") %>,歡迎您!</h1>
</body>
</html>
四. 項目結構
五. 效果演示
-
登錄頁面 login.jsp
-
登錄成功,重定向至 success.jsp
-
驗證碼錯誤,轉發回 login.jsp
-
用戶名或密碼錯誤,轉發回 login.jsp