Java Web 学习笔记之四:Cookie介绍及使用

Java Web 学习笔记之四:Cookie介绍及使用

简介

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,其包含的内容有:

1
2
3
4
5
6
7
8
9
10
11
name             必需,规定cookie值的名称
value 必需,规定cookie值的值

以上是cookie值

expire 可选,规定cookie的有效期
path 可选,规定cookie的服务器路径(即哪些路径内生效)
domain 可选,规定cookie的域名
secure 可选,规定是否通过安全的Https连接进行传输

以上是cookie的属性

其中需要注意的是,属性是不需要返回给服务器的。
即如果需要带上cookie返回给服务器已达到保持会话等作用,只需要将cookie值返回即可。

而Cookie属性,是给浏览器用来对cookie进行一系列判断操作的依据,比如说失效时间判断等。

Cookie由 web 服务端响应头部的 Set-Cookie 定义,由 键-值 对组成,其格式为:

1
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类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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的封装类之后,可以通过:

1
2
3
4
5
Cookie cookie;
URL url = new URL(actionURL);
httpURLConnection = (HttpURLConnection) url.openConnection();
String set_cookie = connection.getHeaderField("Set-Cookie");
cookie = Cookie.newCookieInstance(set_cookie);

来获取服务器响应的cookie。

以及通过:

1
2
3
URL url = new URL(actionURL);
httpURLConnection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("cookie", cookie.convertCookieToCookieValueString());

来发送cookie给服务端。