案例:登录中输入验证码(Session及JSP技术应用)

article/2025/8/28 11:33:55

案例:登录中输入验证码(会话技术)

1.案例需求:1.访问带有验证码的登录页面login.jsp2.用户输入用户名,密码以及验证码如果用户和密码输入有误,跳转登录页面。提示:用户或密码错误如果验证码输入有误,跳转登录页面,提示:验证码有误如果全部输入正确,跳转到success.jsp页面,显示:用户名,欢迎您
2.案例分析:1.设置request的编码2.获取请求参数3.获取session中的验证码此处会出现验证码反复重用的可能因为图片资源会被浏览器缓存,所以不会再次向服务器请求生成新验证码所以当用户再次输入相同的验证码,直接会拿session中的对比解决方案:获取到session中的程序生成的验证码后,立即删除4.封装表单中的请求数据到Bean5.判断程序生成的验证码和用户输入的是否一致一致:判断用户名密码是否一致一致:存储User数据到session重定向到sucess.jsp不一致:1.给提示信息2.转发到登录页面不一致:1.给用户提示信息2.转发到登录页面

案例分析图解:
在这里插入图片描述

3.涉及的知识点:checkCode验证码生成案例相关知识StringBuilder对象及其append(char c):添加字符数据 -->该方法有多种重载HttpSession对象及其getSession():获取对象方法setAttribute(String s, Object obj):设置共享数据getAttribute(String s):获取共享的数据removeAttribute(String s):删除共享的数据Request对象及其setCharacterEncoding():设置请求数据的字符集请求参数通用方法:如 getParameter() getParameterMap()getContextPath():获取项目的虚拟目录setAttribute():设置request域的共享数据getRequestDispatcher():转发Response对象及其sendRedirect():重定向方法注意:session数据共享可以用于一次会话中的多次请求之间,所以可用在重定向中request数据共享只可以用于一次请求中,所以可以用于转发中

login.jsp(登录时的动态资源):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录页</title>
</head><script>window.onload = function() {document.getElementById("img").onclick = function() {this.src= "/day16/checkCodeServlet?time=" + new Date().getTime();};}
</script><style>div {color: red;}
</style>
<body>
<form action="/day16/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="checkcode"></td></tr><tr><td colspan="2"><img src="/day16/checkCodeServlet" id="img" alt=""></td></tr><tr><td colspan="2"><input type="submit" value="登录"></td></tr></table><div><%= request.getAttribute("user_error") == null ? "" : request.getAttribute("user_error")%></div><div><%= request.getAttribute("checkcode_error") == null ? "" : request.getAttribute("checkcode_error")%></div>
</form>
</body>
</html>

success.jsp(登录成功的动态资源):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>成功登录</title>
</head>
<body><h1>欢迎您回来,<%= request.getSession().getAttribute("user")%></h1>
</body>
</html>

LoginServlet(登录业务逻辑的动态资源):

package 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 {// 设置request编码request.setCharacterEncoding("utf-8");// 获取请求参数String username = request.getParameter("username");String password = request.getParameter("password");String checkcode = request.getParameter("checkcode");// 获取程序中生成的验证码字符串HttpSession session = request.getSession();String generatedCheckCode = (String) session.getAttribute("generatedCheckCode");// 保证验证码只可以使用一次session.removeAttribute("generatedCheckCode");// 判断验证码if (generatedCheckCode != null && generatedCheckCode.equalsIgnoreCase(checkcode)) {// 判断用户名和密码,假设已经让userDAO从数据库中获取到了相关数据if ("zhangsan".equals(username) && "123".equals(password)) {// 共享session中的数据(假设此处的值是从数据库获取的)session.setAttribute("user", "zhangsan");// 重定向到success页面String contextPath = request.getContextPath();response.sendRedirect(contextPath + "/success.jsp");} else {// 给提示信息并且转发回login.jsp// 转发为一次请求,所以可直接用request域对象共享数据request.setAttribute("user_error", "用户名或密码不正确");// 转发不需要用getContextPath()加虚拟目录request.getRequestDispatcher("login.jsp").forward(request, response);}} else {// 给提示信息并且转发回login.jsp// 转发为一次请求,所以可直接用request域对象共享数据request.setAttribute("checkcode_error", "验证码不正确");// 转发不需要用getContextPath()加虚拟目录request.getRequestDispatcher("login.jsp").forward(request, response);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);
}
}

CheckCodeServlet(验证码生成的动态资源):

package 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 javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int width = 100;int height = 50;// 1.创建内存中的图片对象BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 生成随机数对象Random random = new Random();// 2.美化图片// 获取画笔对象Graphics graphics = bufferedImage.getGraphics();// 设置色彩graphics.setColor(Color.PINK);// 填充正方形graphics.fillRect(0, 0, width, height);// 设置色彩graphics.setColor(Color.BLUE);// 画边框graphics.drawRect(0, 0, width-1, height-1);StringBuilder sb = new StringBuilder();// 写字String code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for (int i = 1; i <= 4; i++) {int index = random.nextInt(code.length());char c = code.charAt(index);sb.append(c);graphics.drawString(String.valueOf(c), width/5*i, height/2);}// 新增代码,作用是共享程序生产的验证码字符串String generatedCheckCode = sb.toString();HttpSession session = req.getSession();session.setAttribute("generatedCheckCode", generatedCheckCode);// 写干扰线for (int i = 0; i < 10; i++) {int x1 = random.nextInt(width);int x2 = random.nextInt(width);int y1 = random.nextInt(height);int y2 = random.nextInt(height);graphics.drawLine(x1, y1, x2, y2);}// 3.将图片输出到页面ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());}@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);
}
}

http://chatgpt.dhexx.cn/article/mIEsnhRj.shtml

相关文章

《线性代数及其应用 第四版》习题1.4

18. 行化简的结果显示&#xff0c;矩阵B化简后的简化阶梯型只有三行包含主元位置&#xff1a; 根据1.4的定理4&#xff0c;由于B不是每行都有主元位置&#xff0c;因此B的列向量的线性组合不能表示所有R4中的向量。要注意B的列向量也不能张成R3&#xff0c;因为B的列向量位于R4…

同济大学 线性代数 第六版 pdf_线性代数(第六版)【课后习题答案】

来源 线性代数&#xff08;第六版&#xff09; -【课后习题答案】​daanbar.com 网盘下载&#xff1a;https://pan.baidu.com/s/14LN2FrLtxZzKAqtd1ZFoZQ 提取码&#xff1a;375d 同济大学数学系 编 高等教育出版社 第1章 行列式第2章 矩阵及其运算第3章 矩阵的初等变换与线性…

安徽大学线性代数第二章习题册(详细解答)

第二章第一题中4A-3B中间的0换成4&#xff08;感谢通信孔晨皓同学的建议&#xff09; 第五题第二小问2A-EB(EA&#xff09;换成2A-E&#xff08;EA&#xff09;B&#xff0c;不影响后面&#xff0c;因为可以交换&#xff0c;但是错误引导&#xff08;感谢信安赖铭峰同学的建议…

经济数学—线性代数第二版课后习题解析 吴传生 编|高等教育出版社 大学课后习题答案

来源&#xff1a;答案吧 http://www.daanbar.com/book-info/2624.html 经济数学—线性代数第二版课后习题解析 吴传生 编 高等教育出版社 第1章&#xff1a;线性方程组的消元法和矩阵的初等变换 第2章&#xff1a;行列式克拉默法则 第3章&#xff1a;矩阵的运算 第4章&am…

安徽大学(线性代数第一章详细答案)

附录1 #pragma warning(disable:4996) #include <cstdio> #include <cmath>#define MAXN 100 #define zero(x) (fabs(x)<1e-10)struct mat{int n, m;double data[MAXN][MAXN]; }; double det(const mat &a){int i, j, k, sign 0;double b[MAXN][MAXN], re…

工程数学线性代数 同济大学版 第六版 课后习题答案 高等数学 大学数学 线性代数 课后题答案与解析 考试复习提纲

大学 高等数学 大学线性代数 第六版 同济大学版 工程数学线性代数 课后习题答案 大学高等数学 大学线性代数 第六版 同济大学版 课后习题答案工程数学线性代数 同济大学数学系编 高等教育出版社出版 注意:答案在文章最下方 前言 第1章 行列式 课后习题答案 1 二阶与三阶行列…

经济应用数学基础二 线性代数 (第四版) 赵树嫄 编 中国人大版 课后习题答案

更多答案:http://www.daanbar.com/book-info/122.html 经济应用数学基础二 线性代数 &#xff08;第四版&#xff09; 赵树嫄 编 中国人大版 第1章 行列式第2章 矩阵第3章 线性方程组第4章 矩阵的特征值第5章 二次型 第1章 行列式

安徽大学线性代数习题册第四章详细答案

在这里向所有访客道个歉&#xff0c;因为我们的原因延迟了这么久才发