简介
Http协议是无状态的协议,但是很多情况下web应用都需要跟踪用户的状态,比如网购平台需要知道请求发送方的登录状态等等。因此需要一种机制来实现无状态的Http协议下的有状态传输。
这种机制就叫做Cookie机制。
Cookie 在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在 RAM 中发挥作用 (此种 Cookies 称作 Session Cookies),一旦用户从该网站或服务器退出,Cookie 可存储在用户本地的硬盘上,此种Cookies称作Persistent Cookies。
通常情况下,当用户结束浏览器会话时,系统将终止所有的 Cookie。当 Web 服务器创建了Cookies 后,只要在其有效期内,当用户访问同一个 Web 服务器时,浏览器首先要检查本地的Cookies,并将其原样发送给 Web 服务器。这种状态信息称作“Persistent Client State HTTP Cookie” ,简称为 Cookies。
格式
Cookie实际上是一段文本信息。
服务端向客户端发送cookie在响应头部上的名字叫做Set-Cookie,其包含的内容有:
name 必需,规定cookie值的名称
value 必需,规定cookie值的值
以上是cookie值
expire 可选,规定cookie的有效期
path 可选,规定cookie的服务器路径(即哪些路径内生效)
domain 可选,规定cookie的域名
secure 可选,规定是否通过安全的Https连接进行传输
以上是cookie的属性
其中需要注意的是,属性是不需要返回给服务器的。即如果需要带上cookie返回给服务器已达到保持会话等作用,只需要将cookie值返回即可。
而Cookie属性,是给浏览器用来对cookie进行一系列判断操作的依据,比如说失效时间判断等。
Set-Cookie : customer=xxxxxxx; path=/xx/xx; domain=ccc.ccc; expires=Wednesday, 19-OCT-05 23:12:40 GMT; [secure]
Java 封装
在Java web请求发送工具中添加cookie支持,可以实现工具的会话保持功能,下面是封装的cookie类:
import java.util.HashMap;
import java.util.Map;
/**
* Cookie实体类
*
* @author Xuyh
*
*/
public class Cookie {
public final static String COOKIE_ATTRIBUTE_NAME_EXPIRE = "expire";
public final static String COOKIE_ATTRIBUTE_NAME_PATH = "path";
public final static String COOKIE_ATTRIBUTE_NAME_DOMAIN = "domain";
public final static String COOKIE_ATTRIBUTE_NAME_SECURE = "secure";
public final static String COOKIE_ATTRIBUTE_NAME_HTTPONLY = "HttpOnly";
public final static String COOKIE_ATTRIBUTE_NAME_HTTPONLY_LOWERCASE = "httponly";
/**
* cookie的有效值
*/
private Map<String, String> cookieValue = new HashMap<String, String>();
/**
* cookie的有效期
*/
private String expire = "";
/**
* cookie生效的服务器路径
*/
private String path = "";
/**
* cookie的域名
*/
private String domain = "";
/**
* 是否通过安全的HTTPS连接来传输cookie
*/
private boolean secure = false;
private boolean HttpOnly = false;
/**
* 从服务器获得的Set-Cookie字串解析成Cookie对象
*
* @param set_cookie
* @return Cookie对象
*/
public static Cookie newCookieInstance(String set_cookie) {
Cookie cookie = new Cookie();
String[] params = set_cookie.split("; ");
for (String param : params) {
if (param.toLowerCase().contains(COOKIE_ATTRIBUTE_NAME_PATH)) {
cookie.setPath(param.substring(param.indexOf("=") + 1));
} else if (param.toLowerCase().contains(COOKIE_ATTRIBUTE_NAME_DOMAIN)) {
cookie.setDomain(param.substring(param.indexOf("=") + 1));
} else if (param.toLowerCase().contains(COOKIE_ATTRIBUTE_NAME_EXPIRE)) {
cookie.setExpire(param.substring(param.indexOf("=") + 1));
} else if (param.toLowerCase().contains(COOKIE_ATTRIBUTE_NAME_SECURE)) {
cookie.setSecure(true);
} else if (param.toLowerCase().contains(COOKIE_ATTRIBUTE_NAME_HTTPONLY_LOWERCASE)) {
cookie.setHttpOnly(true);
} else {
String[] nameAndValue = param.split("=");
cookie.addCookieValue(nameAndValue[0], nameAndValue[1]);
}
}
return cookie;
}
/**
* 获取服务器发送客户端的set-cookie字串
*
* @return
*/
public String convertCookieToCookieSetString() {
String Set_Cookie = "";
String cookieValueString = "";
for (String name : this.cookieValue.keySet()) {
cookieValueString += ("; " + name + "=" + this.cookieValue.get(name));
}
cookieValueString = cookieValueString.substring(2);
Set_Cookie += cookieValueString;
if (this.path != null && !this.path.equals("")) {
Set_Cookie += ("; " + COOKIE_ATTRIBUTE_NAME_PATH + "=" + this.path);
}
if (this.domain != null && !this.domain.equals("")) {
Set_Cookie += ("; " + COOKIE_ATTRIBUTE_NAME_DOMAIN + "=" + this.domain);
}
if (this.expire != null && !this.expire.equals("")) {
Set_Cookie += (";" + COOKIE_ATTRIBUTE_NAME_EXPIRE + "=" + this.expire);
}
if (this.secure) {
Set_Cookie += ("; " + COOKIE_ATTRIBUTE_NAME_SECURE);
}
if (this.HttpOnly) {
Set_Cookie += ("; " + COOKIE_ATTRIBUTE_NAME_HTTPONLY);
}
return Set_Cookie;
}
/**
* 添加cookie值
*
* @param name
* @param value
*/
public void addCookieValue(String name, String value) {
this.cookieValue.put(name, value);
}
/**
* 获取cookie值的字串
*
* @return
*/
public String convertCookieToCookieValueString() {
String cookieValueString = "";
for (String name : this.cookieValue.keySet()) {
cookieValueString += ("; " + name + "=" + this.cookieValue.get(name));
}
cookieValueString = cookieValueString.substring(2);
return cookieValueString;
}
public Map<String, String> getCookieValue() {
return cookieValue;
}
public void setCookieValue(Map<String, String> cookieValue) {
this.cookieValue = cookieValue;
}
public String getExpire() {
return expire;
}
public void setExpire(String expire) {
this.expire = expire;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public boolean isSecure() {
return secure;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
public boolean isHttpOnly() {
return HttpOnly;
}
public void setHttpOnly(boolean httpOnly) {
HttpOnly = httpOnly;
}
}
定义好cookie的封装类之后,可以通过以下代码来获取服务器响应的cookie:
Cookie cookie;
URL url = new URL(actionURL);
httpURLConnection = (HttpURLConnection) url.openConnection();
String set_cookie = connection.getHeaderField("Set-Cookie");
cookie = Cookie.newCookieInstance(set_cookie);
以及通过以下代码来发送cookie给服务端:
URL url = new URL(actionURL);
httpURLConnection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("cookie", cookie.convertCookieToCookieValueString());