day08-功能实现07
家居网购项目实现07
以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git
16.功能15-会员显示登录名
16.1需求分析/图解
- 会员登录成功
- login_ok.jsp显示欢迎信息
- 返回首页,显示登录相关菜单,如果有登录过,显示如上信息
- 如果用户没有登录过,网站首页就显示 登录/注册 超链接
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完成测试
未登录访问首页:
登录后访问首页:
17.功能16-注销登录
17.1需求分析/图解
- 顾客登陆成功后
- login_ok.jsp中点击安全退出,注销登录
- 返回首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
17.4完成测试
18.功能17-注册验证码
18.1需求分析/图解
表单重复提交情况:
- 提交完表单,服务器使用请求转发进行页面跳转。用户刷新(F5),会发起最后一次的请求,造成表单重复提交问题。解决方案是使用重定向
- 用户正常提交,由于网络延迟等原因,未收到服务器响应,如果这时用户重复点击提交,也会造成表单重复提交问题。解决方案:使用验证码
- 用户正常提交,服务器没有延迟,但是提交完之后,用户回退浏览器重新提交,也会造成表单重复提交。解决方案:验证码
- 恶意注册,使用可以批量发送http的工具,比如Postman,Jemeter等,解决方案:仍是使用验证码防护
18.2思路分析
18.3代码实现
dao层和service层不变
-
引入kaptcha-2.3.2.jar,在web.xml中配置KaptchaServlet
(KaptchaServlet已经在jar包中写好了,只需要配置即可)
KaptchaServlet源码:
<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>
-
修改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(); })
-
前端校验代码: 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; })
-
后端校验代码-修改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); } }
-
修改了一些前端代码
18.4完成测试
提交空验证码,前端返回提示信息
提交错误验证码,后端返回提示信息,并回显注册用户名和邮件
输入合法数据,注册成功