Java网络开发(Tomcat)—— 登陆 和 注册功能 的实现 从html 到 jsp 迭代升级 session保存登陆信息

news2024/11/25 2:20:27

目录

  • 引出
  • 登陆功能---从html到jsp
    • 1.登陆--用post请求
    • 2.用html文件的form表单登陆
      • (1)index.html页面
      • (2)login.html登陆的页面
      • (3)LoginServlet.java处理输入信息的代码
      • (4)登陆成功:
    • 3.如果失败在原页面显示信息----用jsp文件登陆
      • (1)login.jsp页面
      • (2)LoginServlet.java处理登陆业务---共享msg
  • 注册功能---注册验证码
    • 4.注册逻辑 和 注册成功后跳转到登陆页面
    • 5.如何防止用户恶意注册----用验证码限制
      • (1)前端显示验证码
      • (2)后端判断验证是否正确
      • (3)完整代码
  • 登陆成功和退出登陆
    • 6.登陆成功和退出登陆---保存session和删除session
      • (1)前端页面,comIndex.jsp
      • (2)进行登陆,保存session
      • (3)退出系统servlet,LogoutServlet.jsp
  • 总结

引出

1.验证用户名密码正确的思路;
2.从html文件到jsp文件的登陆进化—静态到动态;
3.用验证码的方式防止不断注册;
4.注册成功后再跳转到登陆页面—重定向;
4.如何保存登陆的用户信息----session;


登陆功能—从html到jsp

1.登陆–用post请求

两种登陆方法:

1.浏览器上,输入用户名&密码进行登陆,比如浏览器 -----B/S架构(Brower Server)
2.在软件上,输入用户名&密码登陆,比如QQ ----- C/S架构

思路:
1.通过username 和 password 查询对象出来,如果对象有,登陆成功,否则失败;
2.通过username 和 password 查询数量,如果数量为1,登陆成功,否则失败;

3.【推荐】SpringSecurity 推荐的方式:用username 查一个对象出来;
(1)查不到,登陆失败(没有注册过,数据库没有这个用户名);
(2)查到了,用户名正确,用查询出来的这一条记录和前端发送过来的密码对比:
​ 如果正确,登陆成功,否则,登陆失败;

dao层的接口和实现:
接口要有:(1)新增一个数据到数据库;(2)根据用户名查询一条记录出来;

dao层的接口:

package com.tianju.dao;

import com.tianju.entity.ComUser;

/**
 * 公司用户的Dao类
 */
public interface IComUserDao {
    /**
     * 新增一个公司用户
     * @param comUser 新增用户
     * @return 影响行数
     */
    Integer add(ComUser comUser);

    /**
     * 根据用户名查一条记录出来
     * @param username 查询的用户名
     * @return 查询出的用户
     */
    ComUser queryByUsername(String username);

}

dao接口的实现:

package com.tianju.dao.impl;

import com.tianju.dao.IComUserDao;
import com.tianju.entity.ComUser;
import com.tianju.util.DBUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.List;

public class ComUserDaoImpl implements IComUserDao {
    private JdbcTemplate db = DBUtils.getJdbcTemplate();
    public RowMapper<ComUser> rowMapper = new BeanPropertyRowMapper<>(ComUser.class);
    @Override
    public Integer add(ComUser comUser) {
        String sql = "INSERT INTO com_user(id,username,password,sex,birthday)" +
                "values (null,?,?,?,?)";
        return db.update(sql,comUser.getUsername(),comUser.getPassword(),comUser.getSex(),comUser.getBirthday());
    }

    @Override
    public ComUser queryByUsername(String username) {
        String sql = "SELECT * FROM com_user WHERE username=?";
        List<ComUser> find = db.query(sql, rowMapper,username);
        if (find.size()>0){
            return find.get(0);
        }
        return null;
    }
}

2.用html文件的form表单登陆

在这里插入图片描述

(1)index.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<img src="img/register.jpg" width="200px"><br>
<a href="/day01/html/login.html" target="_blank">登陆</a><br>
<a href="html/register.html" target="_blank">注册</a><br>
<a href="html/idcard.html" target="_blank">身份证归属地</a><br>
<a href="/day01/html/loginNew.html">新版登陆页面</a><br>
<a href="/day01/bookTypes/list">显示图书类型的表格--前端在java中拼出来</a><br>
<a href="/day01/bookList/jsp">显示图书类型的表格--用jsp</a>


</body>
</html>

在这里插入图片描述

(2)login.html登陆的页面

其中密码输入的input框的type设置成 password

密码 :<input type="password" name="password"><br>

在这里插入图片描述

action 要用绝对路径 :/项目名/链接

1)有 / 为绝对路径,从ip/端口/day01/开始拼接 ,会从localhost:8080位置开始拼接路径
2)无 / 为相对路径,浏览器会删除最后一级目录,然后把相对目录地址拼接上去

如果是绝对路径,会从localhost:8080位置开始拼接路径

浏览器路径为:localhost:8080/day01/a
<a href="/b">跳转</a>
跳转后路径为:localhost:8080/b

如果是相对路径,浏览器会删除最后一级目录,然后把相对目录地址拼接上去

浏览器路径为:localhost:8080/day01/a
<a href="b">跳转</a>
跳转后路径为:localhost:8080/day01/b

get和post
查询用get:链接里显示输入的值;写到请求头中
登陆用post:链接里不会显示输入的值;写到请求体中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆的页面</title>
</head>
<body>
    <form action="/day01/loginUserNew" method="post">
        <h1>新版登陆页面</h1>
        <img src="../img/register.jpg" width="200px"><br>
        用户名:<input type="text" name="username"><br>&nbsp;&nbsp;码:<input type="password" name="password"><br>
        <input type="submit" value="登陆">
        <input type="reset" value="重置">
    </form>
    <a href="../index.html">返回主界面</a>

</body>
</html>

在这里插入图片描述

(3)LoginServlet.java处理输入信息的代码

业务流程:

1)输入不为空;

2)验证用户名和密码;

2)登陆成功;

/**
 * 用户登陆的服务,注意不能用log
 * 1.username + password 查询对象出来,对象有,登陆成功,否则失败;
 * 2.查询数量出来,1成功,否则失败;
 * 3.【建议】springSecurity 推荐,用username 查一个对象;
 *     3.1 查不到,登陆失败(没有注册过,数据库无这个用户名);
 *     3.2 查到了,用户名正确,就用这一条记录的密码和前端发送的密码对比;
 *         如果正确,登陆成功,不登录失败;
 */

@WebServlet("/loginUserNew")
public class LoginServlet extends HttpServlet {
    private IUserService  userService = new UserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决编码的问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 获取前端传来的用户名
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            resp.getWriter().write("<h1>必填项为空</h1>");
            return;
        }

        // 登陆错误,重新输入
        User user = userService.findByUsername(username);
        if (user==null || !password.equals(user.getPassword())){
            resp.getWriter().write("<h1>用户名|密码错误</h1>");
            return;
        }
        String out = "<h1>用户名"+user.getUsername() +"/"+ user.getNickname() +"登陆成功"+"</h1>";
        resp.getWriter().write(out);

    }
}

在这里插入图片描述

(4)登陆成功:

在这里插入图片描述

3.如果失败在原页面显示信息----用jsp文件登陆

(1)login.jsp页面

用一个span框,获取共享的msg信息

    <span style="color: darkred">${msg}</span><br>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登陆页面e</title>
</head>
<body>
<form action="/day06/comUser/login" method="post">
    用户名:<input type="text" name="username"><br>
    密&nbsp;&nbsp;码:<input type="password" name="password"><br>
    <span style="color: darkred">${msg}</span><br>
    <input type="submit" value="登陆">

</form>

</body>
</html>

(2)LoginServlet.java处理登陆业务—共享msg

请求转发,内部转发,jsp本质也是servlet

        if (comUser==null || !comUser.getPassword().equals(SecureUtil.md5(password))){
            req.setAttribute("msg", "用户名 | 密码错误");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

完整代码:

/**
 * 用户登陆的servlet
 */
@WebServlet("/comUser/login")
public class LoginServlet extends HttpServlet {
    private IComUserService comUserService = new ComUserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 编码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 输入不为空
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            // 输入为空
            req.setAttribute("msg", "输入为空,请检查");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

        // 进行验证
        ComUser comUser = comUserService.queryByUsername(username);
        if (comUser==null || !comUser.getPassword().equals(SecureUtil.md5(password))){
            req.setAttribute("msg", "用户名 | 密码错误");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }
        // 跳转到操作页面
        resp.sendRedirect(req.getContextPath()+"/compMess/comIndex.jsp");
        
    }
}

在这里插入图片描述

注册功能—注册验证码

4.注册逻辑 和 注册成功后跳转到登陆页面

用验证码的方式防止恶意注册;

注册成功重定向到登陆页面:

		// 5.注册成功跳转到登陆页面
        resp.sendRedirect(req.getContextPath()+"/comUser/login.jsp");

5.如何防止用户恶意注册----用验证码限制

(1)前端显示验证码

验证码的图片请求servlet

    验证码:<input type="text" name="imgCode"><img src="/day06/register/image/get">

<%--    如果要让验证码在点击时自动更新--%>
    验证码:<input type="text" name="imgCode">
    <img src="/day06/register/image/get" οnclick="this.src='/day06/register/image/get?'+new Date().getMilliseconds()">

servlet处理请求:

(1)把验证码—4位数字存到session中;

(2)把验证码的图片放到响应中,发送给前端jsp,进行展示;

@WebServlet("/register/image/get")
public class ImageServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 随机生成验证码
        String randomStr = ImageCodeUtils.getRandomStr(4);

        // 验证码存到session空间中
        HttpSession session = req.getSession();
        session.setAttribute("yzm", randomStr);

        // 根据验证码在缓存中生成一张图片
        BufferedImage bufferedImage = ImageCodeUtils.createImageCode(100, 36, randomStr);

        // 把缓存中的图片以png的格式,放到响应的输出流中
        ImageIO.write(bufferedImage, "png", resp.getOutputStream());

    }
}

注意这里有个错误:共享的时候不能是session,查了好久这个bug

在这里插入图片描述

一个卡了一会儿的bug

在这里插入图片描述

生成的图片分析:

在这里插入图片描述

(2)后端判断验证是否正确

在图片的servlet中,把图片的验证码4位数字存到session空间中;

        // 验证码存到session空间中
        HttpSession session = req.getSession();
        session.setAttribute("yzm", randomStr);

在注册的register的servlet中,获取session,从session中获取验证码数字,进行判断

  • 忽略大小写
        // +++++判断验证码是否正确
        HttpSession session = req.getSession();
        // 从session中获取验证码
        String yzm = (String)session.getAttribute("yzm");
        // 忽略大小写 .equalsIgnoreCase
        if (!yzm.equalsIgnoreCase(imgCode)){
            req.setAttribute("msg", "验证码不正确");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }

验证码对比流程:

在这里插入图片描述

(3)完整代码

处理注册业务的RegisterServlet.java文件


@WebServlet("/comUser/register")
public class RegisterServlet extends HttpServlet {
    private IComUserService comUserService = new ComUserServiceImpl();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决编码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 用户注册的业务逻辑
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String rePassword = req.getParameter("rePassword");
        String sex = req.getParameter("gender");
        String birthday = req.getParameter("birthday");
        System.out.println(username+password+rePassword+sex+birthday);
        // +++加入+验证码输入
        String imgCode = req.getParameter("imgCode");

        // 1.输入不为空;
        if (StringUtils.isBlank(username)
        || StringUtils.isBlank(password)
        || StringUtils.isBlank(rePassword)
        || StringUtils.isBlank(sex)
        || StringUtils.isBlank(birthday)
        || StringUtils.isBlank(imgCode)){
            // 如果为空,显示一条信息;转发给jsp
            req.setAttribute("msg", "输入为空,请检查");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }

        // +++++判断验证码是否正确
        HttpSession session = req.getSession();
        // 从session中获取验证码
        String yzm = (String)session.getAttribute("yzm");
        // 忽略大小写 .equalsIgnoreCase
        if (!yzm.equalsIgnoreCase(imgCode)){
            req.setAttribute("msg", "验证码不正确");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }


        // 2.用户名不重复;
        ComUser comUserDb = comUserService.queryByUsername(username);
        if (comUserDb!=null){
            // 用户名重复
            req.setAttribute("msg", "用户名重复,请重新输入");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }

        // 3.两次密码输入一致;
        if (!password.equals(rePassword)){
            // 两次密码不一致
            req.setAttribute("msg", "两次密码输入不一致,请检查");
            req.getRequestDispatcher("/comUser/register.jsp").forward(req, resp);
            return;
        }


        // 进行密码加密存储
        ComUser comUser = new ComUser();
        comUser.setPassword(SecureUtil.md5(password));
        comUser.setUsername(username);
        try {
            comUser.setBirthday(sdf.parse(birthday));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        comUser.setSex(sex);

        System.out.println(comUser);


        // 4.保存信息到数据库
        comUserService.add(comUser);

        // 5.注册成功跳转到登陆页面
        resp.sendRedirect(req.getContextPath()+"/comUser/login.jsp");

    }
}

生成验证码的ImageServlet.java文件:

/**
 * 验证码的servlet
 * 随机生成验证码,验证码存到session空间中;
 * 把验证码图片以png的格式,放到响应的输出流中;
 */
@WebServlet("/register/image/get")
public class ImageServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 随机生成验证码
        String randomStr = ImageCodeUtils.getRandomStr(4);

        // 验证码存到session空间中
        HttpSession session = req.getSession();
        session.setAttribute("yzm", randomStr);

        // 根据验证码在缓存中生成一张图片
        BufferedImage bufferedImage = ImageCodeUtils.createImageCode(100, 36, randomStr);

        // 把缓存中的图片以png的格式,放到响应的输出流中
        ImageIO.write(bufferedImage, "png", resp.getOutputStream());

    }
}

ImageCodeUtils.java --生成验证码图片的工具类

package com.tianju.util;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 生成图片验证码
 */
public class ImageCodeUtils {

    //根据传入的位数,生成随机字符
    public static String getRandomStr(int length)
    {
        String s = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

//        Random random = new Random(System.currentTimeMillis());
        Random random = new Random();

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int i1 = random.nextInt(s.length());
            sb.append(s.charAt(i1));
        }
        return sb.toString();
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        for (int i = 0; i < 100; i++) {
            Thread.sleep(10);
            String randomStr = getRandomStr(4);
            System.out.println(randomStr);
        }
//        //BuffereImage 图片缓冲流
//        BufferedImage bufferedImage = createImageCode(100, 34, "ABCD");//生成图片的缓冲流
//        //把缓冲流,写到某个输出流
//        ImageIO.write(bufferedImage,"jpg",new FileOutputStream("/Users/edz/Desktop/11.jpg"));
    }

    public static BufferedImage createImageCode(int width, int height, String code) {
        int codeSize = code.length();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Random rand = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Color[] colors = new Color[5];
        Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
                Color.ORANGE, Color.PINK, Color.YELLOW };
        float[] fractions = new float[colors.length];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
            fractions[i] = rand.nextFloat();
        }
        Arrays.sort(fractions);

        g2.setColor(Color.GRAY);// 设置边框色
        g2.fillRect(0, 0, width, height);

        Color c = getRandColor(200, 250);
        g2.setColor(c);// 设置背景色
        g2.fillRect(0, 2, width, height - 4);

        // 绘制干扰线
        Random random = new Random();
        g2.setColor(getRandColor(160, 200));// 设置线条的颜色
        for (int i = 0; i < 20; i++) {
            int x = random.nextInt(width - 1);
            int y = random.nextInt(height - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        // 添加噪点
        float yawpRate = 0.05f;// 噪声率
        int area = (int) (yawpRate * width * height);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int rgb = getRandomIntColor();
            image.setRGB(x, y, rgb);
        }

        shear(g2, width, height, c);// 使图片扭曲

        g2.setColor(getRandColor(100, 160));
        int fontSize = height - 4;
        Font font = new Font("Algerian", Font.ITALIC, fontSize);
        g2.setFont(font);
        char[] chars = code.toCharArray();
        for (int i = 0; i < codeSize; i++) {
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
                    (width / codeSize) * i + fontSize / 2, height / 2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((width - 10) / codeSize) * i + 5, height / 2 + fontSize / 2 - 10);
        }

        g2.dispose();
        return image;
    }

    private static Color getRandColor(int fc, int bc) {
        Random random = ThreadLocalRandom.current();

        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static int getRandomIntColor() {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb) {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb() {
        Random random = ThreadLocalRandom.current();
        int[] rgb = new int[3];
        for (int i = 0; i < 3; i++) {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    private static void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private static void shearX(Graphics g, int w1, int h1, Color color) {
        Random random = ThreadLocalRandom.current();
        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) {
            double d = (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * phase) / frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }

    }

    private static void shearY(Graphics g, int w1, int h1, Color color) {
        Random random = ThreadLocalRandom.current();
        int period = random.nextInt(40) + 10; // 50;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) {
            double d = (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * phase) / frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }

        }
    }

}

登陆成功和退出登陆

6.登陆成功和退出登陆—保存session和删除session

登陆成功后,将登陆成功的用户存到session----用于确定当前的操作是谁做的

        // +登陆成功的用户存到session----用于确定当前的操作是谁做的
        req.getSession().setAttribute("user", userDb);

退出登陆后,把保存的session信息删除,并重新回到登陆页

        HttpSession session = req.getSession();
        session.invalidate(); // 清理session
        resp.sendRedirect(req.getContextPath()+"/user/login.jsp");

完整的业务逻辑代码:

在这里插入图片描述

(1)前端页面,comIndex.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆成功的index页面</title>
</head>
<body>
<a href="/day06/company/messList" target="iframe">查询公司所有信息</a>
<a href="/day06/user/logout">退出系统</a>
<iframe width="100%" height="80%" name="iframe"></iframe>

</body>
</html>

(2)进行登陆,保存session

/**
 * 用户登陆的servlet
 */
@WebServlet("/comUser/login")
public class LoginServlet extends HttpServlet {
    private IComUserService comUserService = new ComUserServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 编码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 输入不为空
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            // 输入为空
            req.setAttribute("msg", "输入为空,请检查");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

        // 进行验证
        ComUser comUser = comUserService.queryByUsername(username);
        if (comUser==null || !comUser.getPassword().equals(SecureUtil.md5(password))){
            req.setAttribute("msg", "用户名 | 密码错误");
            req.getRequestDispatcher("/comUser/login.jsp").forward(req, resp);
            return;
        }

        // ++++++登陆成功的用户对象存储到session中=====用户确定后续的操作是谁做的
        req.getSession().setAttribute("user", comUser);

        // 跳转到操作页面---重定向
        resp.sendRedirect(req.getContextPath()+"/compMess/comIndex.jsp");

    }
}

(3)退出系统servlet,LogoutServlet.jsp


/**
 * 退出登陆的servlet,清除session缓存
 */
@WebServlet("/user/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.invalidate(); // 清除session
        // 重定向,回到登陆页面
        resp.sendRedirect(req.getContextPath()+"/index.jsp");
    }
}


总结

1.验证用户名密码正确:通过username查一条信息出来,对比密码;
2.用jsp文件代替html文件实现共享msg的提醒,比如用户名|密码不正确;
3.用验证码的方式防止不断注册,点击图片自动更细;
4.注册成功后再跳转到登陆页面—重定向;
4.用session空间保存登陆成功的用户对象;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/624219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT提示大解析:如何有效定制Prompt并用插件管理

有时候&#xff0c;你可能在编程时遇到难题&#xff0c;需要解决方法。有时候&#xff0c;你在学习新的语言时&#xff0c;想要找到一位悉心的教师。又或者&#xff0c;你可能只是需要一些新的灵感&#xff0c;来润色你的文章。在所有这些情况下&#xff0c;ChatGPT都可以发挥巨…

轻量应用服务器哪款性价比高?

最近云服务器618活动正在火热进行中&#xff0c;选对时间入手自己心仪的云服务器其实可以为你省去一大笔费用&#xff0c;这里先开门见山将三家的云服务器活动粒度做个对比。 腾讯云 懂行的人一看这种配置性价比就会内心无比激动&#xff0c;按照平时的价格根本买不到这么实惠的…

JavaSE基础知识笔记

​1、基础语法 在一个Java源文件中可以声明多个class&#xff0c;但是最多只有一个类可以被声名为public&#xff0c;而且被声名为public的类的类名必须与源文件名相同。 计算机底层都以补码的方式来存储数据&#xff01;目的是为了简化计算机的结构设计&#xff0c;同时提升运…

如何在Moonbeam设置多重签名钱包,加固资产安全

Moonbeam Safe是以太坊上Safe&#xff08;先前名为Gnosis Safe&#xff09;的分叉。Safe于2018年正式推出&#xff0c;并发展成为了以太坊上知名的去中心化托管协议和集体资产管理平台。 Moonbeam Safe可用于创建多重签名Safe钱包&#xff0c;通过配置一个多签&#xff08;mul…

02.Web大前端时代之:HTML5+CSS3入门系列~H5结构元素

Web大前端时代之&#xff1a;HTML5CSS3入门系列&#xff1a;Web大前端时代之&#xff1a;HTML5CSS3入门系列 - 毒逆天 - 博客园 1.结构元素 可以理解为语义话标记&#xff0c;比如&#xff1a;以前这么写<div id"nav"></div> 现在偷懒写&#xff1a;&l…

JavaWeb笔记_SpringBoot原理

JavaWeb笔记_SpringBoot原理 配置优先级Bean管理获取BeanBean作用域第三方Bean SpringBoot原理自动配置原理ComponentScan组件扫描Import导入源码跟踪Conditional自定义starter创建aliyun-oss-spring-boot-starter模块创建aliyun-oss-spring-boot-autoconfigure 来源 配置优先级…

opencv、dlib、paddlehub人脸检测

opencv、dlib、paddlehub检测效果对比。dlib和paddlehub的效果相对好一点。 说明&#xff1a;本文只做人脸检测不识别&#xff0c;找识别的不用看本文。 ## 部署说明 # 1. 安装python或conda # 2. 安装依赖&#xff0c;pip install -r requirements.txt # 3. 192.168.1.41 修…

Docker 基本使用

安装 Linux安装 # 1、查看当前Linux系统版本 Linux系统版本需要>3.0 [rootzjrs_test2_152 ~]# uname -a Linux zjrs_test2_152 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux [rootzjrs_test2_152 ~]# uname -r 3.10.0-957.el…

Baumer工业相机堡盟工业相机如何使用BGAPI SDK控制相机数据流的开启和关闭(C#)

Baumer工业相机堡盟工业相机如何使用BGAPI SDK控制相机数据流的开启和关闭&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机BGAPI SDK的技术背景Baumer工业相机使用BGAPISDK控制相机数据流的方式1.引用合适的类文件2.使用BGAPISDK控制相机数据流的方式2.使用BGAPISDK控…

AOP--@DeclareParents--引入新功能

目录 引入 解析 示例 引入 Java不是动态语言&#xff1b;一旦类编译完成了&#xff0c;我们就很难再为该类添加新的功能了切面能够为现有的方法增加额外的功能&#xff0c;为什么不能为一个对象增加新的方法呢&#xff1f;实际上&#xff0c;利用被称为引入的AOP概念&#x…

从数据开始,构建值得信赖的生成式AI应用

生成式AI有望从根本上打开新世界机遇的大门&#xff1a;从能够个性化回复的对话式聊天机器人&#xff0c;到各种应用的代码&#xff0c;再到营销传播的定制化内容......生成式AI正在彻底改变企业的运作方式。越来越多的领先企业正在构建可信的生成式AI应用&#xff0c;让它们在…

信息共享、管理协作!工程劳务管理模板让企业内部更加通畅

随着建筑行业的快速发展&#xff0c;工程劳务管理变得越来越复杂&#xff0c;同时企业也需要更加高效地管理劳务人员的信息、工资、考勤等方面。因此&#xff0c;工程劳务管理系统应运而生&#xff0c;帮助企业解决这些问题。作为一款低代码开发平台&#xff0c;百数根据市面上…

面向 MSP 的IT管理

MSP&#xff08;管理服务提供商&#xff09;是通过建立自己的网络运作中心(NOC&#xff0c;Network Operating Center)来实施管理服务的。用户的网络通过WAN与MSP的NOC相连&#xff0c;并使用加密技术保证信息在网络上的传输安全。通过NOC&#xff0c;MSP可以实现远程的管理、实…

LVS负载均衡群集----DR部署

文章目录 一、数据包流向分析二、DR模式的特点三、LVS-DR中的ARP问题四、LVS单网段DR模式部署第一步配置负载调度器第二步设置两台节点服务器第三步设置DR 服务器第四步在本地查看调度服务器 一、数据包流向分析 &#xff08;1&#xff09;客户端发送请求到 Director Server&a…

前后端 java 对接海康威视监控-hls实现h5播放

海康的获取监控预览流的接口当中支持 rtsp、rtmp、hls等协议。 这篇文章主要是说hls协议的。 贴上海康的开发平台地址&#xff0c;其中有对应的API&#xff1a;海康开发平台 1、java层面代码 这里除了main方法之外&#xff0c;有两个方法&#xff0c;分别是&#xff1a; 1&am…

【Python】一文教你如何使用 Requests 库

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

审视自己再出发,在职读研从人民大学与加拿大女王大学金融硕士项目起航

有人说&#xff0c;人生并非一帆风顺。是的&#xff0c;在人生的道路上&#xff0c;总会出现各种各样的麻烦。或者认真学习不见成效&#xff0c;或是努力工作得不到赏识。人生中最困难的事情就是审视自己&#xff0c;当我们意识到自己需要提升时&#xff0c;往往是拥有强大能量…

【Linux】线程分离和线程互斥

终于到线程互斥了~ 文章目录 前言一、线程分离 如何理解线程库和线程ID二、线程互斥总结 前言 在上一篇文章中我们学习了线程控制&#xff0c;比如创建一个线程&#xff0c;取消一个线程以及等待线程&#xff0c;这篇文章我们讲两个非常重要的概念&#xff0c;一个是线…

CDH 之 hive 升级至 hive-3.1.3 完美踩坑过程

一、准备工作 1.1 前言 这是博主在升级过程中遇到的问题记录&#xff0c;大家不一定遇到过&#xff0c;如果不是 CDH 平台的话&#xff0c;单是 hive 服务升级应该是不会有这些问题的&#xff0c;且升级前博主也参考过几篇相关 CDH 升级 hive 服务的博文&#xff0c;前面的升级…

go语言操作以太坊智能合约

操作中要注意版本问题 geth版本、golang版本等 在remix环境中写好合约后&#xff0c;进行编译得到abi文件 简单举例 Hello.sol合约 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;contract Hello {string Msg;function setMsg(string memory _msg) public{Msg_msg…