cookies的使用

来源:互联网 发布:sql cast 编辑:程序博客网 时间:2024/04/29 07:31
1、什么是cookie

Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。

不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。

设置了过期时间,浏览器就会把cookie保存到硬盘上关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。


2、cookie的四个属性

max-age---指定Ccookie的生存周期(以秒为单位),默认情况下,Cookie的值只在浏览器的会话期间存在,当用户退出浏览器这些值就消失了。

     cookie.setMaxAge(0);//不记录cookie
     cookie.setMaxAge(-1);//会话级cookie,关闭浏览器失效(session-JSESSIONID就是这种会话级)
     cookie.setMaxAge(60*60);//过期时间为1小时

path---------设置访问的路径,指定与Cookie关联在一起的网页.默认情况下,cookie会和创建它的网页以及与这个网页处于同一个目录下的网页和处于该                   目录下的子目录关联。(即是可以访问的路径,只有在指定的目录下,才可以访问cookie中存的值)。
domain-----设置访问域。举个例子:位于a.example.com的服务器要读取b.example.com设置的cookie.这里就要引入domain属性,假定由位于a.example.com的页面创建的cookie把自己的path属性设置为"/",把domain属性设置为".example.com",那么所有位于"a.example.com"的网页和所有位于"b.example.com"的网页以及所有位于example.com域的其他服务器上的网页都能够访问这个cookie.如果没有设置cookie的domain值,该属性的默认值就是创建cookie的网页所在服务器的主机名。
注意:不能将一个cookie的域设置成服务器所在的域之外的域.
***cookie,domain设置成顶级域名,浏览器是不存储的;
***cookie不能跨二级域名设置;

seure------安全,指定在网络上如何传输cookie的值 ,这个属性的值或者是“secure”,或者为空。缺省情况下,该属性为空,也就是使用不安全的HTTP连接传递数据。如果一个 cookie 标记为secure,那么,它与WEB服务器之间就通过HTTPS或者其它安全协议传递数据。不过,设置了secure属性不代表其他人不能看到你机器本地保存的cookie。换句话说,把cookie设置为secure,只保证cookie与WEB服务器之间的数据传输过程加密,而保存在本地的 cookie文件并不加密。如果想让本地cookie也加密,得自己加密数据。


3、java Cookie操作
1.创建Cookie
// new一个Cookie对象,键值对为参数  
Cookie cookie = new Cookie("key", "cookie的value值");  
如果cookie的值中含有中文时,需要对cookie进行编码,不然会产生乱码,使用
URLEncoder.encode("cookie的value值","utf-8");
// 设置Cookie最大生存时间,以秒为单位,默认关闭浏览器Cookie消失  
cookie.setMaxAge(24*60*60);  // 一天  
// 将Cookie添加到Response中,使之生效  
response.addCookie(cookie);  //addCookie后,如果已经存在相同名字的cookie,则最新的覆盖旧的cookie   
2.读取cookie
读取Cookie只能从request中获取全部Cookie,然后循环迭代。
// 从request中获取Cookie,拿到的是一个Cookie数组  
Cookie[] cookies = request.getCookies();  
// 然后迭代之  
for (Cookie cookie : cookies) {
    cookie.getName();
    cookie.getValue();
}  
3.删除cookie
删除Cookie的话,只需要将Cookie的生存期设为0即可
Cookie[] cookies = request.getCookies();  
if (cookies != null && cookies.length > 0) {  
    for (Cookie cookie : cookies) {  
        String name = cookie.getName();  
        // 找到需要删除的Cookie  
        if("需要删除的cookie key name".equals(cookie.getName())){
            // 设置生存期为0  
            cookie.setMaxAge(0);  
            // 设回Response中生效  
            response.addCookie(cookie);  
        }  
    }  
}  
4、cookie的setPath方法使用
正常的cookie只能在一个应用中共享,即一个cookie只能由创建它的应用获得。
1.可在同一应用服务器内共享方法:设置cookie.setPath("/"); 
本机tomcat/webapp下面有两个应用:webapp_a和webapp_b, 
1)原来在webapp_a下面设置的cookie,在webapp_b下面获取不到,path默认是产生cookie的应用的路径。
2)若在webapp_a下面设置cookie的时候,增加一条cookie.setPath("/");或者cookie.setPath("/webapp_b/");
   就可以在webapp_b下面获取到webapp_a设置的cookie了。
3)此处的参数,是相对于应用服务器存放应用的文件夹的根目录而言的(比如tomcat下面的webapp),因此cookie.setPath("/")之后,
   可以在webapp文件夹下的所有应用共享cookie,而cookie.setPath("/webapp_b/");
   是指webapp_a应用设置的cookie只能在webapp_b应用下的获得,即便是产生这个cookie的webapp_a应用也不可以,(因为webapp_a应用下没有/webapp_b/的目录)
4)设置cookie.setPath("/webapp_b/jsp")或者cookie.setPath("/webapp_b/jsp/")的时候,只有在webapp_b/jsp下面可以获得cookie,
   在webapp_b下面但是在jsp文件夹外的都不能获得cookie。
5)设置cookie.setPath("/webapp_b");,是指在webapp_b下面才可以使用cookie,这样就不可以在产生cookie的应用webapp_a下面获取cookie了

6)有多条cookie.setPath("XXX");语句的时候,起作用的以最后一条为准。

5、cookie.setDomain方法设计跨域共享
A机所在的域:home.langchao.com,A有应用webapp_a
B机所在的域:jszx.com,B有应用webapp_b 
1)在webapp_a下面设置cookie的时候,增加cookie.setDomain(".jszx.com");,这样在webapp_b下面就可以取到cookie。但是在webapp_a应用下不能访问
2)输入url访问webapp_b的时候,必须输入域名才能解析。
   比如说在A机器输入:http://lc-bsp.jszx.com:8080/webapp;B机器可以获取webapp_a在客户端设置的cookie;
   而B机器访问本机的应用,输入:http://localhost:8080/webapp;B机器则不可以获得cookie。
3)设置了cookie.setDomain(".jszx.com");,还可以在默认的home.langchao.com下面共享

====================================================================================================

当即设置了path,又设置了domain的时候,浏览器会根据domain将cookie显示在浏览器中,但是:

(1)当domain相同,path不同的时候,如果输入的路径不在path范围内,则获取不到cookie;

(2)当domain相同的时候,path为/时,则都可以获取到cookie

=====================================================================================================

补充

1.Cookie组成
 cookie是由名称、内容、作用路径、作用域、协议、生存周期组成,另外还有个HttpOnly属性,HttpOnly属性很重要,如果在cookie中设置了HttpOnly属性,那么通过js脚本(document.cookie)将无法读取到cookie信息,这样能一定程度上的防止XSS攻击,

 Tomcat服务器设置的JSESSIONID就是HttpOnly的。


 javax.servlet.http.Cookie类
该类可以设置cookie的名称、内容、作用路径、作用域、协议、生存周期,but不能设置HttpOnly属性,不知道这么做是出于什么考虑,如果非要设置HttpOnly的cookie,我们可以通过响应头来处理:
response.setHeader("Set-Cookie", "cookiename=value;Path=/;Domain=domainvalue;Max-Age=seconds;HttpOnly");  

2.Cookie作用域

测试Cookie的作用域需要弄几个域名,修改C:\Windows\System32\drivers\etc\hosts文件,将本机ip映射出四个域名,如下:
127.0.0.1 web1.ghsau.com  
127.0.0.1 web2.ghsau.com  

127.0.0.1 web1.com  
127.0.0.1 web2.com  

前两个是2级域名(ghsau.com)相同,3级域名(web1、web2)不同,后两个是2级域名不同。然后我们再写两个jsp,一个用于设置Cookie,另一个用于显示Cookie。
SetCookie.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
<%  
    Cookie cookie = new Cookie("test_key", "test_value");  
    cookie.setPath("/");  
//  cookie.setDomain(".ghsau.com");  
    response.addCookie(cookie);  
%> 

ShowCookie.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
<%  
    // 输出cookies,过滤掉JSESSIONID  
    Cookie[] cookies = request.getCookies();  
    if(cookies != null)  
        for(Cookie cookie : cookies) {  
            if(cookie.getName().equals("JSESSIONID"))    continue;  
            out.println(cookie.getName() + "-" + cookie.getValue());  
        }  
%>
将这两个jsp放到应用后,部署到服务器中,启动服务器,我们就可以通过域名来访问了。

测试一,首先访问http://web1.ghsau.com:8080/WebSSOAuth/SetCookie.jsp,设置cookie后,再访问http://web1.ghsau.com:8080/WebSSOAuth/ShowCookie.jsp,页面输出test_key=test_value,这时我们访问http://web2.ghsau.com:8080/WebSSOAuth/ShowCookie.jsp,发现页面什么都没有输出,这时我们得出结论,cookie默认情况下作用域为当前域名

测试二,将SetCookie.jsp第五行注释打开,按照上面的顺序依次访问,我们发现http://web2.ghsau.com:8080/WebSSOAuth/ShowCookie.jsp中输出了http://web1.ghsau.com:8080/WebSSOAuth/SetCookie.jsp中设置的cookie,这时我们得出结论,cookie作用域为父级域名时,所有子级域名都可以得到该cookie,这也是实现跨子域SSO的关键。这时有些朋友可能会想到那我把cookie作用域设置到顶级域名(.com、.net)上,是不是用该顶级域名的网站就都能获取该cookie了?这样设置的cookie,浏览器是不存储的,无效的cookie。

测试三,修改SetCookie.jsp第五行代码为cookie.setDomain(".web2.com"),首先访问http://web1.com:8080/WebSSOAuth/SetCookie.jsp,设置cookie后,这时我们访问http://web2.com:8080/WebSSOAuth/ShowCookie.jsp,发现页面什么都没有输出,这时我们得出结论,cookie不能跨二级域名设置

3.Cookie安全性
cookie中的数据通常会包含用户的隐私数据,首先要保证数据的保密性,其次要保证数据不能被伪造或者篡改,基于这两点,我们通常需要对cookie内容进行加密,加密方式一般使用对称加密(单密钥,如DES)或非对称加密(一对密钥,如RSA),密钥需要保存在服务器端一个安全的地方,这样,别人不知道密钥时,无法对数据进行解密,也无法伪造或篡改数据。另外,像上文提到的,重要的cookie数据需要设置成HttpOnly的,避免跨站脚本获取你的cookie,保证了cookie在浏览器端的安全性。

还有我们可以设置cookie只作用于安全的协议(https),JavaEE中可以通过Cookie类的setSecure(boolean flag)来设置,设置后,该cookie只会在https下发送,而不会在http下发送,保证了cookie在服务器端的安全性,


cookie访问的过程:

http方式:以访问http://www.webryan.net/index.php为例

Step1.客户端发起http请求到Server
Host: www.webryan.net
(这里是省去了User-Agent,Accept等字段)
Content-type: text/html
Set-Cookie: name=value
Set-Cookie: name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT
(content of page)
Host: www.webryan.net
Cookie: name=value; name2=value2
Accept: */*
JavaScript或类似的寄宿在浏览器中的脚本语言也可以设置Cookie。在JavaScript里,可以通过document.cookie对象实现。例如:
document.cookie = “key=newvalue”;

GET /index.php HTTP/1.1

Step2. 服务器返回http response,其中可以包含Cookie设置

HTTP/1.1 200 OK

Step3. 后续访问webryan.net的相关页面

GET /spec.html HTTP/1.1

需要修改cookie的值的话,只需要Set-Cookie: name=newvalue即可,浏览器会用新的值将旧的替换掉。

脚本方式种植 Cookie:




总结:

cookie的设置及发送:

客户端发送一个http请求到服务器端 

服务器端发送一个http响应到客户端,其中包含Set-Cookie头部 

客户端发送一个http请求到服务器端,其中包含Cookie头部 

服务器端发送一个http响应到客户端

在客户端的第二次请求中包含的Cookie头部中,提供给了服务器端可以用来唯一标识客户端身份的信息。这时,服务器端也就可以判断客户端是否启用了cookies。

cookie可以在页面设置,也可以在Java程序中设置




0 0