JavaWeb项目实战一(Servlet+Jsp登录功能优化)

643 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

登录功能优化

注销功能实现

新建 servlet 实现注销功能

image-20220423090002679

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 移除用户的Constants.USER_SESSION
        req.getSession().removeAttribute(Constants.USER_SESSION);
        resp.sendRedirect(req.getContextPath() + "/login.jsp"); // 返回登录界面
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

然后在 web.xml 中注册 servlet

<!--  注册注销servlet  -->
    <servlet>
        <servlet-name>LogoutServlet</servlet-name>
        <servlet-class>com.ocean.servlet.user.LogoutServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LogoutServlet</servlet-name>
        <url-pattern>/jsp/logout.do</url-pattern>
    </servlet-mapping>

前端代码访问 /jsp/logout.do 路由即可

<li><a href="${pageContext.request.contextPath }/jsp/logout.do">退出系统</a></li>

此时存在一个问题,没有对后台做权限验证,即存在后台未授权访问

http://localhost:8080/smbms/jsp/frame.jsp

登录拦截优化

新建一个 Filter

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
​
    }
​
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
​
        // 过滤器,从session中获取用户
        User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
​
        if (user == null) {
            // 表示用户已经被移除或者注销,没有查到session
            response.sendRedirect(request.getContextPath() + "/login.jsp");
            // 如果不加 getContextPath 访问 http://localhost:8080/smbms/jsp/frame.jsp 会跳转到 http://localhost:8080/smbms/jsp/login.jsp
            // 加了 getContextPath 会跳转到 http://localhost:8080/smbms,所以一定要在 login.jsp 前边加斜杠
        } else {
            chain.doFilter(req, resp);
        }
    }
​
    public void destroy() {
​
    }
}

然后在 web.xml 中注册过滤器

<!--用户登录鉴权过滤器-->
    <filter>
        <filter-name>SysFilter</filter-name>
        <filter-class>com.ocean.filter.SysFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SysFilter</filter-name>
        <url-pattern>/jsp/*</url-pattern>
        <!--  匹配路由      -->
    </filter-mapping>

注意这里 Filter 一定要在 xml 文档中注册,这是内存马的一个很重要的点

Filter、FilterChain、FilterConfig 介绍

密码修改

image-20220423104217893

从底层往上层写代码

1.写 dao 接口

image-20220423104334147

2.写 updatePwd 接口实现类

    public int updatePwd(Connection connection, int id, String password) throws SQLException {
​
        PreparedStatement preparedStatement = null;
        int excute = 0;
        if (connection != null) {
            String sql = "update smbms_user set userPassword = ? where id= ?";
            // 查询参数数组
            Object params[] = {password, id};
            excute = BaseDao.excute(connection, preparedStatement, sql, params);
            BaseDao.closeResource(connection, null, null);
​
        }
        return excute;
    }

3.写 userService

image-20220423104716166

写实现类

    public boolean updatePwd(int id, String password) {
        boolean flag = false;
        Connection connection = null;
​
        connection = BaseDao.getConnection();
        try {
            if (userDao.updatePwd(connection, id, password) > 0) {
                flag = true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResource(connection, null, null);
        }
        return flag;
    }

4.写 servlet

image-20220423163615823

public class UserServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 实现servlet复用
        String method = req.getParameter("method");
        if (method.equals("savepwd") && method != null) {
            this.updatePwd(req, resp);
        }
        // 如果想要加其他的在这里写else判断即可
    }
​
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
​
    public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
        // 从session中取出用户
        Object attribute = req.getSession().getAttribute(Constants.USER_SESSION);
        // 从前端取出密码
        String newpassword = req.getParameter("newpassword");
​
        boolean flag = false;
​
        if (attribute != null && !StringUtils.isNullOrEmpty(newpassword)) {
            UserServiceImpl userService = new UserServiceImpl();
            // 调用userService中的修改密码功能
            flag = userService.updatePwd(((User) attribute).getId(), newpassword);
​
            if (flag) {
                // 修改成功
                req.setAttribute("message", "密码修改成功,请重新登录");
                req.getSession().removeAttribute(Constants.USER_SESSION);
            } else {
                req.setAttribute("message", "密码修改失败");
            }
        } else {
            req.setAttribute("message", "新密码有问题");
        }
​
        try {
            req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
        } catch (ServletException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

前端代码

image-20220423163714112

注意这里的 action 要和 web.xml 中注册的一致,hidden 属性 input 字段为 servlet 后端复用判断前提

web.xml 中注册 servlet 路由

image-20220423163853247

session 过期时间

在 web.xml 中设置

<!--默认session过期时间30分钟-->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

\