第六阶段-验证码登陆与订单系统
登陆:显示用户名
需求,对于已经成功登陆过的用户信息,当用户访问其他页面时应当针对性提供用户信息。
解决思路:如果用户成功登陆,就在UserServlet
把登陆时成功获取的用户Dao保存至session
中,故应当在login
方法中写如下代码:
if (loginUser == null) {
// 把错误信息,和回显的表单项信息,保存到Request域中
request.setAttribute("msg", "用户或密码错误!");
request.setAttribute("username", username);
// 跳回登录页面
request.getRequestDispatcher("/pages/user/login.jsp").forward(request, response);
} else {
// 登录 成功
⭐️// 将用户数登陆信息保存至session中
request.getSession().setAttribute("user",loginUser);
//跳到成功页面login_success.html
request.getRequestDispatcher("/pages/user/login_success.jsp").forward(request, response);
}
然后在其他页面中例如login_success
增加
<span>欢迎<span class="um_span">${sessionScope.user.username}</span>欢迎光临尚硅谷书城</span>
以及在首页中需要针对session
中是否包含用户信息来选择性的展示页面
<%-- 如果用户还没有登陆 显示包含注册和登陆的菜单 --%>
<c:if test="${empty sessionScope.user}">
<a href="pages/user/login.jsp">登录</a> |
<a href="pages/user/regist.jsp">注册</a>
</c:if>
<%-- 如果用户成功登陆 显示包含注销的菜单 --%>
<c:if test="${not empty sessionScope.user}">
<span>欢迎<span class="um_span">${sessionScope.user.username}</span>进入尚硅谷书城</span>
<a href="pages/cart/cart.jsp">购物车</a>
<a href="pages/order/order.jsp">我的订单</a>
<a href="userServlet?action=logout">注销</a>
</c:if>
<a href="pages/manager/manager.jsp">后台管理</a>
<a href="index.jsp">返回</a>
未登陆时的主页
成功登陆时的主页
登出:注销用户
在上一部分提到,用户是否成功登陆的关键就是当前Session中是否有user
的信息,因此当用户点击注销后,访问userServlet
中的logout
方法,该方法删除session
中的user
信息,在将请求转发至主页index.jsp
即可。
protected void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// 销毁session中的用户登陆信息
request.getSession().invalidate();
// 重定向至首页(注意路径问题)
response.sendRedirect(request.getContextPath());
}
注意:这里使用的是响应重定向,告诉先前的请求直接去访问index.jsp
**这里附上一个请求转发与响应重定向的区别的博客
表单重复提交之验证码
后面两种情况的解决方法——验证码
验证码利用session技术解决表单重复提交问题
谷歌验证码
使用步骤如下
Step1:导入jar包:captcha-2.3.2.jar
Step2:在web.xml中配置用于生成验证码的Servlet程序,代码如下所示。这里最好写成.jpg
的样式,这样看起来更像图片
<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>/kaptcha.jpg</url-pattern>
</servlet-mapping>
Step3:在表单中使用img标签去显示验证码并使用
<form action="http://localhost:8080/tmp/registServlet" method="get">
用户名:<input type="text" name="username" > <br>
验证码:<input type="text" style="width: 60px;" name="code">
<img src="http://localhost:8080/tmp/kaptcha.jpg" alt="" style="width: 100px; height: 28px;"> <br>
<input type="submit" value="登录">
</form>
效果图:
Step4:在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取Session中的验证码
String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
// 删除 Session中的验证码
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
String code = req.getParameter("code");
// 获取用户名
String username = req.getParameter("username");
if (token != null && token.equalsIgnoreCase(code)) {
System.out.println("保存到数据库:" + username);
resp.sendRedirect(req.getContextPath() + "/ok.jsp");
} else {
System.out.println("请不要重复提交表单");
}
}
验证码的切换——刷新验证码
需要给验证码绑定好单击事件
$(function () {
// 给验证码的图片,绑定单击事件
$("#code_img").click(function () {
// 在事件响应的function函数中有一个this对象。这个this对象,是当前正在响应事件的dom对象
// src属性表示验证码img标签的 图片路径。它可读,可写
// alert(this.src);
this.src = "${basePath}kaptcha.jpg?d=" + new Date();
});
上述代码中,由于个别浏览器会对相同请求地址自动生成缓存信息,因此需要加上时间戳避免缓存产生
<label>验证码:</label>
<input class="itxt" type="text" name="code" style="width: 80px;" id="code"/>
<img id="code_img" alt="未找到验证码" src="kaptcha.jpg" style="float: right; margin-right: 40px;width: 110px;height: 30px">
关于客户端与服务器验证码地址缓存的说明:
出现的问题一:当没有用idea连接数据库时,可能会出现无法访问数据库的情况
出现的问题二:项目的out.artifacts中一直保持着旧的的编译内容
解决方案:删除对应的artifacts,然后在idea中重新构建Artifacts