HttpSession简介及Session验证码的实现
1. HttpSession 的生命周期
1)什么时候创建HttpSession对象
①对于JSP:是否浏览器访问服务器的任何一个JSP,服务器都会立即创建一个HttpSession对象呢?
不一定
Ø 若当前的JSP访问的第一个资源,且page指定的session属性值为false,则不创建
Ø 若不是第一个,但是其他页面已经创建一个HttpSession对象,也不会就创建新的,用以前的
②对于Servlet:若Servlet是客户端访问的第一个WEB应用资源,则指有调用了request。getSession()或request.getSession(true)才会创建HttpSession对象
2)page中的Session=-“false”到底表时什么意思?
Ø 当前JSP页面禁用Session隐含变量!但可以使用其他的显示的HttpSession对象
Ø Servlet中可以通过以下 API 获取 Session 对象
request.getSession(flag):
若 flag 为 true, 则一定会返回一个HttpSession 对象, 如果已经有和当前 JSP 页面关联的 HttpSession对象, 直接返回; 如果没有, 则创建一个新的返回.
flag 为 false: 若有关联的, 则返回; 若没有, 则返回 null
request.getSession():相当于 request.getSession(true);
3). 创建一个 Session 对象: 若 page 指定的 session 设置为 false 或在 Servlet 中可以通过以下 API 获取 Session 对象.
request.getSession(flag):若 flag 为 true, 则一定会返回一个HttpSession 对象, 如果已经有和当前 JSP 页面关联的 HttpSession
对象, 直接返回; 如果没有, 则创建一个新的返回.flag 为 false: 若有关联的, 则返回; 若没有, 则返回 null
request.getSession():相当于 request.getSession(true);
HttpSession session = request.getSession(); out.print(session.getId()); session.invalidate(); | 每次不一样 |
4). Session 对象的销毁:
①. 直接调用 HttpSession 的 invalidate()
②.HttpSession 超过过期时间.
> 返回最大时效:getMaxInactiveInterval() 单位是秒
> 设置最大时效:setMaxInactiveInterval(int interval)
可以在 web.xml 文件中配置 Session 的最大时效, 单位是分钟.
<session-config> <session-timeout>30</session-timeout> </session-config> |
③. 卸载当前 WEB 应用.
注意: 关闭浏览器不会销毁 Session!
重新登录和注销方法实现 |
Login.jsp |
<% Object username = session.getAttribute("username"); if(username==null){ username=""; } %> <form action="hello.jsp" method="post"> username:<input type="text" name="username" value="<%=username%>"/> <input type="submit" value="Submit"/> </form> |
Hello.jsp |
Hello:<%=request.getParameter("username") %>
<%--重新登录有两种方式 <a hr ef="Zhuxiao.jsp?username=<%=request.getParameter("username") %>">重新登录</a> --%> <!-- session 可以跨页面--> <% session.setAttribute("username", request.getParameter("username")); %> <a href="login.jsp">重新登录</a> <a href="logout.jsp">注销</a> |
Logout.jsp |
Bye:<%=session.getAttribute("username") %> <br><br>
<a href="login.jsp">重新登录</a> <% session.invalidate(); %> |
注:页面组织cookie时的重新登录方法——URL重写 |
<a href=response.encodeURL("login.jsp")>重新登录</a> |
或者 <a href=response.encodeRedirectURL("login.jsp")>重新登录</a> |
2. / 什么时候代表站点的根目录, 什么时候代表当前 WEB 应用的根目录
1)当前WEB应用的根路径:http://localhost:8080/contextPath
若/ 交由Servlet容器来处理
其中的ContextPath可由request或application的getContextPath方法来获取
Ø 请求转发request.getRequestDispatcher(“/path/b.jsp”).forward(request,response);
Ø Web.xml中的<selrvlet-mapping>
Ø 各种定制标签中的/
2)WEB站点的根路径:http://localhost:8080/
交由浏览器来处理
Ø 超链接<a href=”/TestServlet”>TO B Page</a>
Ø 表单中的action:<form action=”/login.jsp”>
Ø 请求重定向:response.sendRedirect(“/a.jsp”)
3. 表单的重复提交
1). 重复提交的情况:
①. 在表单提交到一个 Servlet, 而 Servlet 又通过请求转发的方式响应一个JSP(HTML) 页面,
此时地址栏还保留着 Serlvet 的那个路径, 在响应页面点击 "刷新"
②. 在响应页面没有到达时重复点击 "提交按钮".
③. 点击 "返回", 再点击 "提交"
2). 不是重复提交的情况: 点击 "返回", "刷新" 原表单页面, 再 "提交"。
3). 如何避免表单的重复提交: 在表单中做一个标记, 提交到 Servlet 时, 检查标记是否存在且是否和预定义的标记一致, 若一致, 则受理请求,并销毁标记, 若不一致或没有标记, 则直接响应提示信息: "重复提交"
①. 仅提供一个隐藏域: <inputtype="hidden" name="token" value="atguigu"/>. 行不通: 没有方法清除固定的请求参数.
②. 把标记放在 request 中. 行不通, 因为表单页面刷新后, request已经被销毁, 再提交表单是一个新的 request.
③. 把标记放在 session 中. 可以!
> 在原表单页面, 生成一个随机值 token
> 在原表单页面, 把 token 值放入session 属性中
> 在原表单页面, 把 token 值放入到隐藏域中.
> 在目标的 Servlet 中: 获取 session 和隐藏域中的 token 值
> 比较两个值是否一致: 若一致, 受理请求, 且把 session 域中的 token 属性清除
> 若不一致, 则直接响应提示页面: "重复提交"
4. 使用 HttpSession 实现验证码
1). 基本原理: 和表单重复提交一致:
> 在原表单页面, 生成一个验证码的图片, 生成图片的同时, 需要把该图片中的字符串放入到 session 中.
> 在原表单页面, 定义一个文本域, 用于输入验证码.
> 在目标的 Servlet 中: 获取 session 和表单域中的验证码的值
> 比较两个值是否一致: 若一致, 受理请求, 且把 session 域中的验证码属性清除
> 若不一致, 则直接通过重定向的方式返回原表单页面, 并提示用户 "验证码错误"