Javaweb 会话跟踪学习记录(1)—Cookie
1.无状态的 HTTP 协议
- HTTP 协议 ( 超文本传输协议 )是一种无状态协议;
- HTTP 协议采用“连接—请求—应答—关闭连接”模式;
- 对于交互式的 Web 应用,保持状态是非常重要的。一个有状态的协议可以用来帮助在多个请求和响应之间实现复杂的业务逻辑 。
2.会话跟踪技术
- 会话跟踪技术是一种在客户端与服务器间保持 HTTP 状态的解决方案。从开发角度考虑,是使上一次请求所传递的数据能够维持状态到下一次请求,并且辨认出是否相同的客户端所发送出来的。
- 会话跟踪技术的解决方案主要分为以下几种:
(1)Cookie
(2)Session
(3)URL重写技术
(4)隐藏表单域技术
3.Cookie 技术
- Cookie 技术是一种在客户端保持会话跟踪的解决方案
- Cookie 是指某些网站为了辨别用户身份而储存在用户终端上的文本信息( 通常经过加密 )。
- Cookie 在用户第一次访问服务器时,由服务器通过响应头的方式发送给客户端浏览器;当用户再次向服务器发送请求时会附带上这些文本信息 。
4.与Cookie 相关的响应报文信息
服务器对第一次客户端请求所响应的含有"Set—Cookie" 响应头的响应报文
客户端再次请求时附带的含有"Cookie"请求头的报文信息
5.Cookie的作用
- 通过 Cookie,服务器在接收到来自客户端浏览器的请求时,能够通过分析请求头的内容而得到客户端特有的信息,从而动态生成与该客户端相对应的内容。
- 如,在很多登陆页面中可以看到“记住我”类似的选项,勾选后,下次再访问该网站时就会自动记住用户名和密码。另外,一些网站根据用户的使用喜好,进行个性化的风格设置、广告投放等,这些功能都可以通过存储在客户端的 Cookie 实现。
6.Cookie对象的创建
Cookie 对象 通过 javax.servlet.http.Cookie 类的构造方法来创建
示例:Cookie unameCookie = new Cookie("username","CSDN");
其中,Cookie 类的构造方法需要两个参数 :
- 第一个String 类型的参数用于指定Cookie 的属性名;
- 第二个String 类型的参数用于指定属性值。
7.Cookie 对象的响应
HttpServletResponse 对象通过 addCookie () 方法,将 Cookie 对象响应给客户端浏览器,存储在客户端机器上 。
示例:response.addCookie(unameCookie);
其中,参数为一个Cookie。
8.获取并遍历客户端 Cookie
存储在客户端的 Cookie,通过 HttpServletRequest 对象 的getCookies() 方法获取, 该方法返回所访问网站的所有 Cookie的对象数组,遍历该数组可以获得各个 Cookie 对象。
示例:
Cookie[] cookies = request.getCookies();
if(cookies != null)
for(Cookie c : cookies){
out.println("属性名:" + c.getName());
out.println("属性值" + c.getValue());
}
9.Cookie 的存活时间
- Cookie 有一定的存活时间,不会在客户端一直保存 。
- 默认情况下,Cookie 保存在浏览器内存中,在浏览器关闭时失效,这种 Cookie 也称为临时 Cookie ( 或会话 Cookie )
- 若要使Cookie 较长时间的保存在磁盘上,可以通过 Cookie 对象的setMaxAge() 方法设置其存活时间 ,保存在磁盘上的 Cookie 也称为持久Cookie 。
- Cookie 对象可以通过 setMaxAge () 方法设置其存活时间 , 时间以秒为单位 :
(1)时间若为正整数,表示其存活的秒数;
(2)时间若为负数 , 表示其为临时Cookie;
(3)时间若为0,表示通知浏览器删除相应的 Cookie 。
示例:设置存活 时间为1 周的持久CookieunameCookie.setMaxAge (7*24*60*60); // 参数以秒为基本单位
10.演示
创建writeCookie.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
//创建cookie
Cookie cookie = new Cookie("cookey", "cookieValue");
//cookie.setPath("/classDemo04/jsp/");
//cookie.setPath("/");
//保存cookie
cookie.setMaxAge(20);
response.addCookie(cookie);
%>
<a href="readCookie.jsp">读取cookie</a>
</body>
</html>
创建readCookie.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String value = null;
//读取cookie列表
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cook : cookies) {
if ("cookey".equals(cook.getName())) {
value = cook.getValue();
}
}
if (value != null) {
out.print(value);
} else {
out.print("没有指定的cookie");
}
} else {
out.print("第一次访问,无cookie对象");
}
%>
</body>
</html>
运行readCookie
运行writeCookie
Cookie技术的应用:
创建CookieExampleServlet
package com;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class CookieExampleServlet
*/
@WebServlet("/CookieExampleServlet")
public class CookieExampleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CookieExampleServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd==HH:mm:ss");
String nowTime = sdf.format(date);
String lastVisitTime = "";
int visitCount = 0;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("lastVisitTime".equals(cookie.getName())) {
lastVisitTime = cookie.getValue();
}
if ("visitCount".equals(cookie.getName())) {
visitCount = Integer.parseInt(cookie.getValue());
}
}
}
// 非第一次访问
if (!"".equals(lastVisitTime) && visitCount != 0) {
out.print("您上次访问的时间为:" + lastVisitTime + "<br/>");
out.print("您是第" + (visitCount + 1) + "次访问");
} else {
out.print("您是第1次访问");
}
// 创建并保存相应记录cookie
Cookie lastVisitTimeCook = new Cookie("lastVisitTime", nowTime);
Cookie visitCountCook = new Cookie("visitCount", String.valueOf(visitCount + 1));
response.addCookie(lastVisitTimeCook);
response.addCookie(visitCountCook);
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
运行
页面保存登陆账号密码小功能:
创建LoginServlet
package com;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String cookName = "";
String cookPassword = "";
String isSave = "";
int count = 0;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("userName".equals(cookie.getName())) {
cookName = cookie.getValue();
count++;
}
if ("userPassword".equals(cookie.getName())) {
cookPassword = cookie.getValue();
count++;
}
}
}
if (count == 2) {
isSave = "checked";
}
out.print("<html>");
out.print("<head><title>登录</title></head>");
out.print("<body>");
out.print("<center>");
out.print("<form action = 'SaveCookieServlet' method = 'post'>");
out.print("用户名:<input type='text' name='userName' value='" + cookName + "'/><br/>");
out.print("密码:<input type='text' name='userPassword' value='" + cookPassword + "'/><br/>");
out.print("保存用户名和密码:<input type='checkbox' name='save' value='yes' " + isSave + "/><br/>");
out.print("<input type='submit' value='提交'/>");
out.print("</form>");
out.print("</center>");
out.print("</body>");
out.print("</html>");
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
创建SaveCookieServlet
package com;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class SaveCookieServlet
*/
@WebServlet("/SaveCookieServlet")
public class SaveCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public SaveCookieServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String userName = request.getParameter("userName");
String userPassword = request.getParameter("userPassword");
String isSave = request.getParameter("save");
Cookie cookName = new Cookie("userName", userName);
Cookie cookPassword = new Cookie("userPassword", userPassword);
if (isSave != null && isSave.equals("yes")) {
cookName.setMaxAge(60);
cookPassword.setMaxAge(60);
} else {
cookName.setMaxAge(0);
cookPassword.setMaxAge(0);
}
response.addCookie(cookPassword);
response.addCookie(cookName);
PrintWriter out = response.getWriter();
out.print("欢迎," + userName);
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
运行
重新运行LoginServlet
账号密码自动填充
11.Cookie 的缺点
Cookie 的缺点主要集中在其安全性和隐私保护上 , 主要包括以下几种 :
- Cookie 可能被禁用,当用户非常注重个人隐私保护时,很可能会禁用浏览器的Cookie 功能 ;
- Cookie 是与浏览器相关的,这意味着即使访问的是同一个页面,不同浏览器之间所保存的 Cookie 也是不能互相访问的 ;
- Cookie 可能被删除,因为每个 Cookie 都是硬盘上的一个文件,因此很有可能被用户删除 ;
- Cookie 的大小和个数受限,单个 Cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 Cookie ;
- Cookie 安全性不够高,所有的 Cookie 都是以纯文本的形式记录于文件中,因此如果要保存用户名密码等信息时,最好事先经过加密处理。