day08-功能实现07

家居网购项目实现07

以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git

16.功能15-会员显示登录名

16.1需求分析/图解

image-20221223173332112 image-20221223173351764 image-20221223173640884
  1. 会员登录成功
  2. login_ok.jsp显示欢迎信息
  3. 返回首页,显示登录相关菜单,如果有登录过,显示如上信息
  4. 如果用户没有登录过,网站首页就显示 登录/注册 超链接

16.2思路分析

16.3代码实现

dao和service层不变,在之前实现的MemberServlet中,修改login方法:

如果用户登录成功,创建session,在session中设置member信息,请求转发到登录成功页面login_ok.jsp,在该页面中显示用户信息。

MemberServlet.login():

/**
 * 处理会员登录业务
 *
 * @param request
 * @param response
 * @throws ServletException
 * @throws IOException
 */
public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.接收用户名和密码
    //如果前端输入的是null,后台接收的数据为空串""
    String username = request.getParameter("username");
    String password = request.getParameter("password");

    //构建一个member对象
    Member member = new Member(null, username, password, null);

    //2.调用MemberServiceImpl的login方法
    if (memberService.login(member) == null) {//数据库中没有该用户,返回登录页面
        //登录失败,将错误信息和登录会员名放入request域中
        request.setAttribute("errInfo", "登录失败,用户名或者密码错误");
        request.setAttribute("username", username);
        //注意路径
        request.getRequestDispatcher("/views/member/login.jsp")
                .forward(request, response);
    } else {//登录成功
        //创建session,将jsessionid作为cookie返回给浏览器
        HttpSession session = request.getSession();
        session.setMaxInactiveInterval(1800);//设置生命周期为30分钟
        //将得到的member对象放入session域对象中
        session.setAttribute("member", member);
        //跳转到登录成功页面
        request.getRequestDispatcher("/views/member/login_ok.jsp")
                .forward(request, response);
    }
}

在前端jsp页面中,如果没有在session域对象中获取到member对象,就显示登录注册链接,否则显示登录用户信息(这里先不实现过滤)

views/customer/index.jsp

<!-- Single Wedge Start -->
<%--根据用户登录的状态显示不同菜单--%>
<%--如果未登录--%>
<c:if test="${empty sessionScope.member}">
    <div class="header-bottom-set dropdown">
        <a href="views/member/login.jsp">登录|注册</a>
    </div>
</c:if>
<%--如果已登录--%>
<c:if test="${not empty sessionScope.member}">
    <div class="header-bottom-set dropdown">
        <a> 欢迎:${sessionScope.member.username}</a>
    </div>
    <div class="header-bottom-set dropdown">
        <a href="#">订单管理</a>
    </div>
    <div class="header-bottom-set dropdown">
        <a href="#">安全退出</a>
    </div>
</c:if>
<!-- Single Wedge End -->

login_ok.jsp同理

16.4完成测试

未登录访问首页:

image-20221223194603497

登录后访问首页:

image-20221223194724345 image-20221223194736146 image-20221223194819075

17.功能16-注销登录

17.1需求分析/图解

image-20221223195300743
  1. 顾客登陆成功后
  2. login_ok.jsp中点击安全退出,注销登录
  3. 返回首index.jsp,也可以点击安全退出,注销登录

17.2思路分析

17.3代码实现

dao,service层不变

在MemberServlet中实现logout方法

/**
 * 处理用户注销登录的请求
 *
 * @param req
 * @param resp
 * @throws ServletException
 * @throws IOException
 */
protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //销毁当前用户的session
    req.getSession().invalidate();
    //重定向到index.jsp,目的是刷新首页
    //req.getContextPath()=>/项目名  -默认访问index.jsp
    resp.sendRedirect(req.getContextPath());
}

注意修改安全退出超链接的参数action=logout

image-20221223201050749

17.4完成测试

18.功能17-注册验证码

18.1需求分析/图解

表单重复提交情况:

  1. 提交完表单,服务器使用请求转发进行页面跳转。用户刷新(F5),会发起最后一次的请求,造成表单重复提交问题。解决方案是使用重定向
  2. 用户正常提交,由于网络延迟等原因,未收到服务器响应,如果这时用户重复点击提交,也会造成表单重复提交问题。解决方案:使用验证码
  3. 用户正常提交,服务器没有延迟,但是提交完之后,用户回退浏览器重新提交,也会造成表单重复提交。解决方案:验证码
  4. 恶意注册,使用可以批量发送http的工具,比如Postman,Jemeter等,解决方案:仍是使用验证码防护

18.2思路分析

18.3代码实现

dao层和service层不变

  1. 引入kaptcha-2.3.2.jar,在web.xml中配置KaptchaServlet

    (KaptchaServlet已经在jar包中写好了,只需要配置即可)

    image-20221224165823841

    KaptchaServlet源码:

    image-20221224174933107
    <servlet>
        <servlet-name>KaptchaServlet</servlet-name>
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>KaptchaServlet</servlet-name>
        <url-pattern>/kaptchaServlet</url-pattern>
    </servlet-mapping>
    
  2. 修改login.jsp的注册表单,生成正确的验证码图片,点击图片可以生成新的验证码图片

    <!--注册表单-->
    <form action="memberServlet" method="post">
    <input type="hidden" name="action" value="register"/>
    <input type="text" id="username" name="username"
           value="${requestScope.username}" placeholder="Username"/>
    <input type="password" id="password" name="password" placeholder="输入密码"/>
    <input type="password" id="repwd" name="repassword" placeholder="确认密码"/>
    <input name="email" id="email" placeholder="电子邮件" value="${requestScope.email}"
           type="email"/>
    <input type="text" name="code" style="width: 50%" id="code" placeholder="验证码"/>   
        <img id="codeImg" alt="" src="kaptchaServlet" style="width: 120px;height: 50px">
    <div class="button-box">
        <button type="submit" id="sub-btn"><span>会员注册</span></button>
    </div>
    </form>
    

    在function中给验证码图片,绑定单击事件

    //给验证码图片绑定单击事件,可以获取新的验证码
    $("#codeImg").click(function () {
        //在url没有变化的时候,图片不会发出新的请求(因为图片已经被缓存了)
        //为了防止不刷新,可以携带一个变化的参数
        this.src="<%=request.getContextPath()%>/kaptchaServlet?d="+new Date();
    })
    
  3. 前端校验代码: login.jsp增加注册表单的校验-验证码提交时不为空

    //点击绑定事件
    $("#sub-btn").click(function () {
        //编写正则表达式进行验证
        //1. 验证用户名
       		 ...
        
        //2. 验证密码
       		...
    
        //3.两次密码要相同
        	...
    
        //4. 邮箱格式验证
        	...
    
        //5.验证码不能为空
        var codeText=$("#code").val();
        //去掉验证码前后空格
        var codeText = $.trim(codeText);
        if (codeText==null||codeText==""){
            //提示
            $("span.errorMsg").text("验证码不能为空");
            return false;
        }
        
        //如果上面的信息格式都正确,就可以提交表单信息了
        $("span.errorMsg").text("验证通过...");
        return true;
    })
    
  4. 后端校验代码-修改MemberServlet.register(),增加在服务器端的校验代码

    /**
     * 处理会员注册业务
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //接收用户注册信息--参数名要以前端页面的变量名为准
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        //获取用户提交的验证码
        String code = request.getParameter("code");
        //从session中获取正确的验证码文本
        String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
        //立即删除session的验证码,防止该验证码被重复使用
        request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
        //将提交的验证码和正确的验证码文本进行对比
        //如果token不为空,并且和用户提交的验证码一致,就继续执行业务
        if (token != null && token.equalsIgnoreCase(code)) {
    
            //如果返回false,说明该用户信息可以注册
            if (!memberService.isExistsUsername(username)) {
                //构建一个member对象
                Member member = new Member(null, username, password, email);
                if (memberService.registerMember(member)) {
                    //如果注册成功,请求转发到register_ok.html
                    request.getRequestDispatcher("/views/member/register_ok.html")
                            .forward(request, response);
                } else {
                    //注册失败,请求转发到register_fail.html
                    request.getRequestDispatcher("/views/member/register_fail.html")
                            .forward(request, response);
                }
            } else {//否则不能进行注册
                //请求转发到login.html
                //后面可以加入提示信息
                request.getRequestDispatcher("/views/member/login.jsp")
                        .forward(request, response);
            }
        } else {//验证码不正确
            request.setAttribute("errInfo", "验证码不正确");
            //回显注册信息
            request.setAttribute("username",username);
            request.setAttribute("email",email);
            request.getRequestDispatcher("/views/member/login.jsp")
                    .forward(request, response);
        }
    }
    
  5. 修改了一些前端代码

18.4完成测试

提交空验证码,前端返回提示信息

image-20221224173528383

提交错误验证码,后端返回提示信息,并回显注册用户名和邮件

image-20221224183939315

输入合法数据,注册成功

image-20221224184245629 image-20221224184322246
posted @ 2022-12-23 21:20  一刀一个小西瓜  阅读(83)  评论(0编辑  收藏  举报