Cookie的使用,及防止消息重放处理

离职-面试(各种公司,各种人,各种问)。

没日没夜的加班,各种来回的修改(对个人基本没有提升了),突然一个外部管理(不是自己的领导,自己的领导水平还是不错的),自以为是的冲我一阵咆哮,由于个人嘴笨我心里XXX去你MD老子不干了,提离职走人,歇了12天(没有感觉到快乐,平平淡淡的),找工作三天接到第一个offer,然后又歇了3天,入职第一天,看到程序熊猫眼,还有咋咋呼呼地所谓的领导,走人吧,然后是苦逼的面试之路。。。。。


吐槽完了,然后开始正文



cookie:
(小甜饼,外国程序猿还是很有情调的)
服务器存储到客户机器上的信息

作用:
1.用于记录用户历史登录网站的情况(自动识别)
2.网站可以利用cookies跟踪统计用户访问该网站的习惯,比如什么时间访问,访问了哪些页面,在每个网页的停留时间等(利用cookie跟踪用户行为)
(利用这些信息,一方面是可以为用户提供个性化的服务)
3.记录用户登录信息(很容易泄密)

生存周期:
1.Cookie可以保持登录信息到用户下次与服务器的会话
2.Cookie在生成时就会被指定一个Expire值,这就是Cookie的生存周期,在这个周期内Cookie有效,超出周期Cookie就会被清除。
有些页面将Cookie的生存周期设置为“0”或负值,这样在关闭浏览器时,就马上清除Cookie,不会记录用户信息

Cookie的隐患
1.网络臭虫
Cookies在某种程度上说已经严重危及用户的隐私和安全。
其中的一种方法是:一些公司的高层人员为了某种目的(譬如市场调研)
而访问了从未去过的网站(通过搜索引擎查到的),而这些网站包含了一种叫做网页臭虫的图片,
该图片透明,且只有一个像素大小(以便隐藏),
它们的作用是将所有访问过此页面的计算机写入cookie。
而后,电子商务网站将读取这些cookie信息,
并寻找写入这些cookie的网站,
随即发送包含了针对这个网站的相关产品广告的垃圾邮件给这些高级人员

2.个人认为cookie可以造成关键词的泄漏(盗用关键词,引导到别的网站)
:根据cookie找到网站,抓取关键词 进行统计分析

3.脚本攻击
尽管cookie没有病毒那么危险,但它仍包含了一些敏感信息:用户名,计算机名,
使用的浏览器和曾经访问的网站。用户不希望这些内容泄漏出去,尤其是当其中还包含有私人信息的时候。

这并非危言耸听,一种名为跨站点脚本攻击(Cross site scripting)可以达到此目的。
通常跨站点脚本攻击往往利用网站漏洞在网站页面中植入脚本代码或网站页面引用第三方法脚本代码,
均存在跨站点脚本攻击的可能,在受到跨站点脚本攻击时,脚本指令将会读取当前站点的所有 Cookie 内容(已不存在 Cookie 作用域限制),
然后通过某种方式将 Cookie 内容提交到指定的服务器(如:AJAX)。一旦 Cookie 落入攻击者手中,它将会重现其价值。

建议开发人员在向客户端 Cookie 输出敏感的内容时(譬如:该内容能识别用户身份):
1)设置该 Cookie 不能被脚本读取,这样在一定程度上解决上述问题。
  2)对 Cookie 内容进行加密,在加密前嵌入时间戳,保证每次加密后的密文都不一样(并且可以防止消息重放)。
  3)客户端请求时,每次或定时更新 Cookie 内容(即:基于第2小条,重新加密)
  4)每次向 Cookie 写入时间戳,数据库需要记录最后一次时间戳(防止 Cookie 篡改,或重放攻击)。
  5)客户端提交 Cookie 时,先解密然后校验时间戳,时间戳若小于数据数据库中记录,即意味发生攻击。
基于上述建议,即使 Cookie 被窃取,却因 Cookie 被随机更新,且内容无规律性,攻击者无法加以利用。另外利用了时间戳另一大好处就是防止 Cookie 篡改或重放。

4.Cookie 窃取:搜集用户cookie并发给攻击者的黑客。攻击者将利用cookie信息通过合法手段进入用户帐户。
5.Cookie 篡改:利用安全机制,攻击者加入代码从而改写 Cookie 内容,以便持续攻击


Cookie的用途:

Cookie 的用途之一是存储用户在特定网站上的密码和 ID
各家公司利用 cookie 的一般用途包括:在线定货系统、网站个人化和网站跟踪。

Cookie可以导致不能匿名查看一些信息


Cookie基本解析:
cookie通常以user@domain格式命名 例如:user是你的本地用户名,domain是所访问的网站的域名,

Cookie中的内容大多数经过了加密处理,因此在我们看来只是一些毫无意义的字母数字组合,
只有服务器的CGI处理程序才知道它们真正的含义。通过一些软件我们可以查看到更多的内容,
使用Cookie Pal软件查看到的Cookie信息,如图2所示。它为我们提供了Server、Expires、Name、value等选项的内容。
其中,Server是存储Cookie的网站,Expires记录了Cookie的时间和生命期,Name和value字段则是具体的数据。


Cookie的传递流程

适用对象:中级读者
当在浏览器地址栏中键入了Amazon的URL,浏览器会向Amazon发送一个读取网页的请求,并将结果在显示器上显示。
这时该网页在你的电脑上寻找Amazon网站设置的Cookie文件,如果找到,浏览器会把Cookie文件中的数据连同前面输入的URL一同发送到Amazon服务器
。服务器收到Cookie数据,就会在他的数据库中检索你的ID,你的购物记录、个人喜好等信息,并记录下新的内容,增加到数据库和Cookie文件中去。
如果没有检测到Cookie或者你的Cookie信息与数据库中的信息不符合,则说明你是第一次浏览该网站,服务器的CGI程序将为你创建新的ID信息,并保存到数据库中。
Cookie是利用了网页代码中的HTTP头信息进行传递的,浏览器的每一次网页请求,都可以伴随Cookie传递,
例如,浏览器的打开或刷新网页操作。服务器将Cookie添加到网页的HTTP头信息中,伴随网页数据传回到你的浏览器,
浏览器会根据你电脑中的Cookie设置选择是否保存这些数据。如果浏览器不允许Cookie保存,则关掉浏览器后,
这些数据就消失。Cookie在电脑上保存的时间是不一样的,这些都是由服务器的设置不同决定的。
Cookie有一个Expires(有效期)属性,这个属性决定了Cookie的保存时间,
服务器可以通过设定Expires字段的数值,来改变Cookie的保存时间。
如果不设置该属性,那么Cookie只在浏览网页期间有效,关闭浏览器,这些Cookie自动消失,绝大多数网站属于这种情况。
通常情况下,Cookie包含Server、Expires、Name、value这几个字段,
其中对服务器有用的只是Name和value字段,Expires等字段的内容仅仅是为了告诉浏览器如何处理这些Cookies。

Cookie的编程实现
多数网页编程语言都提供了对Cookie的支持。
如javascript、VBScript、Delphi、ASP、SQL、PHP、C#等。
在这些面向对象的编程语言中,对Cookie的编程利用基本上是相似的,大体过程为:先创建一个Cookie对象(Object),
然后利用控制函数对Cookie进行赋值、读取、写入等操作。那么如何通过代码来获取其他用户Cookie中的敏感信息,下面进行简单的介绍


该方法主要有两步,首先要定位你需要收集Cookie的网站,并对其进行分析,并构造URL;
然后编制收集Cookie的PHP代码,并将其放到你可以控制的网站上,当不知情者单击了你构造的URL后可以执行该PHP代码。下面我们看具体的实现过程。


Cookie的安全问题
Cookie欺骗
Cookie记录着用户的帐户ID、密码之类的信息,如果在网上传递,通常使用的是MD5方法加密。
这样经过加密处理后的信息,即使被网络上一些别有用心的人截获,也看不懂,
因为他看到的只是一些无意义的字母和数字。然而,遇到的问题是,截获Cookie的人不需要知道这些字符串的含义,
他们只要把别人的Cookie向服务器提交,并且能够通过验证,他们就可以冒充受害人的身份,登陆网站。
这种方法叫做Cookie欺骗。Cookie欺骗实现的前提条件是服务器的验证程序存在漏洞,并且冒充者要获得被冒充的人的Cookie信息。
网站的验证程序要排除所有非法登录是非常困难的,例如,编写验证程序使用的语言可能存在漏洞。而且要获得别人Cookie是很容易的
,用支持Cookie的语言编写一小段代码就可以实现(具体方法见三),只要把这段代码放到网络里,那么所有人的Cookie都能够被收集。
如果一个论坛允许HTML代码或者允许使用Flash标签就可以利用这些技术收集Cookie的代码放到论坛里,然后给帖子取一个吸引人的主题,
写上有趣的内容,很快就可以收集到大量的Cookie。在论坛上,有许多人的密码就被这种方法盗去的。至于如何防范,还没有特效药,
我们也只能使用通常的防护方法,不要在论坛里使用重要的密码,也不要使用IE自动保存密码的功能,以及尽量不登陆不了解底细的网站。

Cookie是面向对象的

这里还有一点要说明的,比如你的站点有几个不同的目录,
那么如果只用不带路径的Cookie的话,在一个目录下的页面里设的Cookie在另一个目录的页面里是看不到的,也就是说,Cookie是面向路径的。
际上,即使没有指定路径,WEB 服务器会自动传递当前的路径给浏览器的,指定路径会强制服务器使用设置的路径。
解决这个问题的办法是在调用SetCookie时加上路径和域名,域名的格式可以是SetCookie函数里表示value的部分,在传递时会自动被encode,也就是说,
如果value的值是“test value”在传递时就变成了“test%20value”,跟URL的方法一样。当然,对于程序来说这是透明的,
因为在PHP接收Cookie的值时会自动将其decode。

JavaScript Cookies
jsp中使用cookie完成状态管理:





这就造成用户在A网站搜索了一个关键字,用户继续访问B网站,
由于B网站也使用了同一家的第三方广告代码,这个代码可以从Cookie中获取用户在A网站的搜索行为,
进而展示更精准的推广广告。比如搜索“糖尿病”等关键词,再访问其联盟网站,页面会立刻出现糖尿病治疗广告。
如果并未事先告之,经用户同意,此做法有对隐私构成侵犯的嫌疑。这个还处在灰色地带。

超级Cookies
英国伦敦的一名软件开发者已发现了一串代码,能在浏览器的隐私模式中执行普通会话,这将导致隐私模式的失效。



java中Cookie的使用


1.建立一个无生命周期的cookie,即随着浏览器的关闭即消失的cookie,
HttpServletRequest request 
HttpServletResponse response
Cookie cookie = new Cookie("cookiename","cookievalue");
response.addCookie(cookie);

2.建立一个有生命周期的cookie,可以设置他的生命周期
cookie = new Cookie("cookiename","cookievalue");

cookie.setMaxAge(3600);

//设置路径,这个路径即该工程下都可以访问该cookie 如果不设置路径,那么只有设置该cookie路径及其子路径可以访问

cookie.setPath("/");
response.addCookie(cookie);

3.如何读取cookie,读取cookie代码如下
Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
for(Cookie cookie : cookies){
    cookie.getName();// get the cookie name
    cookie.getValue(); // get the cookie value
}

4.Cookie基本封装
,比如增加一个cookie,我们关注的是cookie的name,value,生命周期,所以进行封装一个函数,当然还要传入一个response对象,addCookie()代码如下
/**
* 设置cookie
* @param response
* @param name  cookie名字
* @param value cookie值
* @param maxAge cookie生命周期  以秒为单位
*/
public static void addCookie(HttpServletResponse response,String name,String value,int maxAge){
    Cookie cookie = new Cookie(name,value);
    cookie.setPath("/");
    if(maxAge>0)  cookie.setMaxAge(maxAge);
    response.addCookie(cookie);
}

5.读取Cookie封装
/**
* 根据名字获取cookie
* @param request
* @param name cookie名字
* @return
*/
public static Cookie getCookieByName(HttpServletRequest request,String name){
    Map<String,Cookie> cookieMap = ReadCookieMap(request);
    if(cookieMap.containsKey(name)){
        Cookie cookie = (Cookie)cookieMap.get(name);
        return cookie;
    }else{
        return null;
    }  
}

/**
* 将cookie封装到Map里面
* @param request
* @return
*/
private static Map<String,Cookie> ReadCookieMap(HttpServletRequest request){ 
    Map<String,Cookie> cookieMap = new HashMap<String,Cookie>();
    Cookie[] cookies = request.getCookies();
    if(null!=cookies){
        for(Cookie cookie : cookies){
            cookieMap.put(cookie.getName(), cookie);
        }
    }
    return cookieMap;
}

6.Cookie中的中文处理
创建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
       注意:在Struts中可以使用 ServletActionContext.getResponse()获得respone对象
      
8.删除Cookie
删除Cookie的话,只需要将Cookie的生存期设为0即可
if (cookies != null && cookies.length > 0) { 
    for (Cookie cookie : cookies) { 
        String name = cookie.getName(); 
        // 找到需要删除的Cookie 
        if (name.compareTo("target-key") == 0) { 
            // 设置生存期为0 
            cookie.setMaxAge(0); 
            // 设回Response中生效 
            response.addCookie(cookie); 
        } 
    } 


9. 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下面获取到cas设置的cookie了。  (这一条非常中用,用于统计分析数据用)

3)此处的参数,是相对于应用服务器存放应用的文件夹的根目录而言的(比如tomcat下面的webapp),因此cookie.setPath("/");之后,
可以在webapp文件夹下的所有应用共享cookie,而cookie.setPath("/webapp_b/");
是指cas应用设置的cookie只能在webapp_b应用下的获得,即便是产生这个cookie的webapp_a应用也不可以

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");语句的时候,起作用的以最后一条为准。


10. 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。
2)输入url访问webapp_b的时候,必须输入域名才能解析。比如说在A机器输入:http://lc-bsp.jszx.com:8080/webapp_b,
可以获取webapp_a在客户端设置的cookie,而B机器访问本机的应用,输入:http://localhost:8080/webapp_b则不可以获得cookie。
)设置了cookie.setDomain(".jszx.com");,还可以在默认的home.langchao.com下面共享


提高COOKIE的安全性--相关解决方案

给Cookies加个加密算法。 给Cookies加个时间戳和IP戳,实际就是让Cookies在同个IP下多少时间内失效。
最终使用MD5来MAC签名防止篡改……但这样仍然可以看到明文信息,有一定不安全之处。

我的方案是

cookie==3des(“值,时间,IP戳”);   最终得到的COOKIE是这样的:3BD1B32614A528EA


使用3DES来加密,这样保证客户端没有明文……。


服务端检查的时候,再解密出来值,时间,IP戳,并检查过期时间与IP……不符的需要清空此COOKIE,转向登录页面..


这样解决了几个问题
1.客户端COOKIE无明文,得到不任何有用信息……如果使用MD5签名,客户端势必有明文。
2.无法篡改,一旦篡改后在服务端解密的时候就会出错……防止了暴力破解
3.在网络被截获后,也无法使用,因为有IP戳……且IP是加密的,无法看到明文,所以也无法使用伪造IP的方式
4.之所以在客户端存放IP戳,可以使得其在多台电脑上存放COOKIE,如果放在服务端,则只能一台电脑用COOKIE登录了,影响用户体验,且浪费性能查询数据库……


http://my.oschina.net/kevinair/blog/192829#OSC_h2_1


注意Cookie有两个版本version0 version1
最大区别: version1中添加了Port端口 该 Cookie 在什么端口下可以回传服务端,如果有多个端口,以逗号隔开,如 Port="80,81,8080"



每个域名对cookie数量的限制

浏览器版本 Cookie 数限制 Cookie 总大小限制
IE6 20 个 / 每个域名 4095 个字节
IE7 50 个 / 每个域名 4095 个字节
续表

浏览器版本 Cookie 数限制 Cookie 总大小限制
IE8 50 个 / 每个域名 4095 个字节
IE9 50 个 / 每个域名 4095 个字节
Chrome 50 个 / 每个域名 大于 80000
FireFox 50 个 / 每个域名 4097 个字




猜你喜欢

转载自caizhaohua.iteye.com/blog/2299619