Web项目开发实践,Cookie与Session机制(二)
5.1.3 Cookie的不可跨域名性
很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢?
答案是否定的。Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。
Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。
需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。
%注意:用户登录网站www.google.com之后会发现访问images.google.com时登录信息仍然有效,而普通的Cookie是做不到的。这是因为Google做了特殊处理。本章后面也会对Cookie做类似的处理。
5.1.4 Unicode编码:保存中文
中文与英文字符不同,中文属于Unicode字符,在内存中占4个字符,而英文属于ASCII字符,内存中只占2个字节。Cookie中使用Unicode字符时需要对Unicode字符进行编码,否则会乱码。编码可以使用java.net.URLEncoder类的encode(String str, String encoding)方法,解码使用java.net.URLDecoder类的decode(String str,String encoding)方法,例如:
代码5.3 encoding.jsp
<%@ page language="java"pageEncoding="UTF-8" %>
<jsp:directive.page import="java.net.URLEncoder"/>
<jsp:directive.page import="java.net.URLDecoder"/>
// 使用中文的 Cookie. name 与 value 都使用 UTF-8 编码
Cookie cookie = new Cookie(
URLEncoder.encode("姓名", "UTF-8"),
URLEncoder.encode("刘京华", "UTF-8"));
response.addCookie(cookie); // 发送到客户端
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">
<title>Cookie Encoding</title>
</head>
if(request.getCookies() != null){
for(Cookie cc :request.getCookies()){ // 遍历所有的Cookie
String cookieName= URLDecoder.decode(cc.getName(), "UTF-8");
StringcookieValue = URLDecoder.decode(cc.getValue(), "UTF-8");
out.println(cookieName + "=" + cookieValue + ";<br/>");
else{
out.println("Cookie 已经写入客户端. 请刷新页面. ");
</body>
</html>
程序使用UTF-8编码了Cookie内容,然后再使用UTF-8解码Cookie并显示出来。程序运行效果如图5.3所示。
图5.3 Cookie的UTF-8编码
%提示:Cookie中保存中文只能编码。一般使用UTF-8编码即可。不推荐使用GBK等中文编码,因为浏览器不一定支持,而且JavaScript也不支持GBK编码。
5.1.5 BASE64编码:保存二进制图片
Cookie不仅可以使用ASCII字符与Unicode字符,还可以使用二进制数据。例如在Cookie中使用数字证书,提供安全度。使用二进制数据时也需要进行编码。下面的例子使用BASE64编码在Cookie中保存二进制文件。源代码如下:
代码5.4 base64.jsp
<%@ page language="java"pageEncoding="UTF-8" %>
<jsp:directive.pageimport="sun.misc.BASE64Encoder"/>
<jsp:directive.pageimport="java.io.InputStream"/>
<jsp:directive.pageimport="java.io.File"/>
File file = newFile(this.getServletContext().getRealPath("cookie.
gif"));
byte[] binary = newbyte[(int)file.length()]; // 二进制数组
// 从图片文件读取二进制数据.
InputStream ins =this.getServletContext().getResourceAsStream
(file.getName());
ins.read(binary);
ins.close();
String content =BASE64Encoder.class.newInstance().encode(binary);
// BASE64 编码
Cookie cookie = newCookie("file", content);
// 包含二进制数据的 Cookie
response.addCookie(cookie); // 将 Cookie 发送到客户端
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">
<title>Cookie Encoding</title>
</head>
从 Cookie 中获取到的二进制图片:<imgsrc="base64_decode.jsp" /> <br/>
<textarea id='cookieArea' style='width:100%;height:200px; '></textarea>
<scripttype="text/javascript">cookieArea.value=document.cookie;</script>
</body>
</html>
程序使用的二进制数据来自根目录下的cookie.gif文件。程序先将二进制数据写进客户端Cookie中,然后又将Cookie中的二进制数据还原并显示。输入框中用JavaScript程序显示了客户端Cookie的所有内容。
解码并显示图片的源代码如下:
代码5.5 base64_decode.jsp
<%@ page language="java"pageEncoding="UTF-8" %>
<jsp:directive.page import="sun.misc.BASE64Decoder"/>
<jsp:directive.page trimDirectiveWhitespaces="true"/>
out.clear(); // 清除输出
for(Cookie cookie : request.getCookies()){ // 遍历Cookie
if(cookie.getName().equals("file")){ // 找到名为file的Cookie
byte[] binary =
BASE64Decoder.class.newInstance().decodeBuffer(cookie.
getValue().replace(" ", "")); // 解码BASE64编码的二进制内容
response.setHeader("Content-Type", "image/gif");
// 设置内容类型为 gif 图片
response.setHeader("Content-Disposition", "inline;
filename=cookie.gif");
response.setHeader("Connection", "close");
response.setContentLength(binary.length); // 设置输出内容的长度
response.getOutputStream().write(binary); // 输出到客户端