我是靠谱客的博主 清秀云朵,最近开发中收集的这篇文章主要介绍Cookie详解与跨域问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原文地址:Cookie详解与跨域问题

Http是无状态的协议,客户端每次对服务端的http请求都是独立的,不受该客户端其它的请求的影响。

为了把Http这个无状态协议变的与上下文有关系,我们引入了会话(Session)的概念,具有相同会话ID的请求使之变成了有状态。

介绍一下cookie:
 
1.cookie是一个存储在客户端的字符串属性,可以用它对当前网页的cookie进行读,写,增.删等操作;javascript能够用document对象的cookie属性对cookie进行操作;
 
2.cookie的四个可选属性:
 

  • 2.1 cookie的生存期属性:expires;默认情况下,cookie只在浏览器会话期存在.退出浏览器就丢失;可以用expires设置时间;退出浏览器后就不会丢失并存为客户端浏览器的cookie文件;过了时间后cookie失效,还会自动删除cookie文件.

 

  • 2.2 path属性:默认情况下,在同一个目录下文件可以调用;

例如:http://hanj.com/c1/1.html设置的cookie可以被http://hanj.com/c1/2.html调用.但不能被http://hanj.com/c2/目录下的文件调用;
但如把path属性设成"/";则在http://hanj.com/下的所有文件都可调用此cookie.
 

  • 2.3 domain属性:例如设成".hanj.com"则在.hanj.com下的所有服务器下的文件都可以调用cookie.

 

  • 2.4 安全属性:默认情况下为false;用http协议不安全传输;true:用https等协议安全传输.

 
3.cookie的局限性:浏览器最多保存300个cookie;为单个web服务器的最多只能保存20个cookie;每个cookie不能超过4000个字节.


服务端可以给请求setSession的信息,信息保存在服务端内存,同时在response时将session内容推送给客户端浏览器,浏览器为了保存SessionID等信息,又有了Cookie这玩意,Cookie本质是一块存储少量数据的存储空间,可以存到内存也可以写入磁盘。每次浏览器向一个域名发送http请求时会去查找该域名的Cookie信息拼接到Http的header中送到Server端。

谈到域名,可以简单的理解为我们访问的地址(请注意不是真正映射成的IP地址),而Cookie具有不跨域性质,只会将属于该域名的Cookie信息添加到Header中传到Server端。

下面我们写个Demo来试下Cookie的跨域

先设置下本机的host,添加两个域名peer1和peer2。

用管理员权限打开C:WINDOWSsystem32driversetchosts

添加两行:

127.0.0.1       peer1

127.0.0.1       peer2

 

测试代码放在了 git 上:https://github.com/yejingtao/forblog/tree/master/cookie-domain
核心代码如下:

    @Value("${cookie.value}")
    String cookieValue;
    
    @RequestMapping("/setCookie")
    public String home(HttpServletResponse response,HttpServletRequest request) {
        Cookie cookie = new Cookie("testName", cookieValue);
        response.addCookie(cookie);
        return "Success";
    }
    
    @RequestMapping("/getCookie")
    public String home(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        Cookie[] cookies = request.getCookies();
        if(cookies!=null) {
            for(Cookie cookie : cookies) {
                sb.append(cookie.getName());
                sb.append(",");
                sb.append(cookie.getValue());
                sb.append(";");
            }
        }
        return sb.length()==0?"Empty":sb.toString();
    }


测试前先看下我本机的cookie有哪些内容,需要对peer1和peer2这两个域名做下清理:

以Chrome浏览器为例:

设置--高级—内容设置—cookie—查看所有cookie和网站数据,保证不要有peer1和peer2的cookie数据。

浏览器请求http://peer1:8087/setCookie,会发现cookie里多了peer1

打开箭头可以看到详细的cookie信息,cookie的属性有我们代码中显式设置的,也有隐式默认的:


此时我们请求peer1的getCookie是可以获取到cookie值的,请求peer2的getCookie是获取不到cookie内容的,所以验证了cookie是不能跨域的,而这个域是浏览器请求的域名,哪怕他们最终的服务端是一起的也不可以跨越。

上图中cookie值里有个域名peer1,这个不是我们代码中显式设置的,浏览器默认帮我们根据域名设置的,那么如果我显式设置一个跟域名对不上的domain会如何呢?

给setCookie代码增加一行:

    @RequestMapping("/setCookie")
    public String home(HttpServletResponse response,HttpServletRequest request) {
        Cookie cookie = new Cookie("testName", cookieValue);
        cookie.setDomain("peer2");
        response.addCookie(cookie);        
        return "Success";
    }


清理浏览器cookie、重启服务后访问peer1的setCookie

奇怪的是无论是peer1的getCookie还是peer2的getCookie都获取不到cookie内容,而且设置里面也确实没有。难道是浏览器自己的安全机制发现我set的Domain与域名不匹配所以认为这是个无效的cookie就没有保存?调用下peer2的setCookie就可以验证这一猜想,测试结果是肯定的。

Cookie是不安全的,浏览器、脚本类语言、甚至直接访问cookie保存文本的地址都可以获取到Cookie信息,所以尽量不要讲敏感内容保存在cookie中,即便是密码之类的可以进行加密,但是别人可以不需要解密直接使用你cookie中的内容进行欺骗。所以在服务端对cookie使用时,尽量设置超时时间,客户端尽量cookie不使用时(例如浏览器关闭)及时清空。

Cookie是客户端保存的内容,Session是服务端保存的内容,Session对于单个客户来说是安全的,而Cookie是客户共享的。所以可以推断得出从安全角度讲能用Session的情况尽量不要用Cookie,特别是现在Redis等共享缓存组件的使用使服务端存储Session的能力大大加强。

最后回到本文最开始的那张图,我们将代码再修改下验证下第一张图。

代码修改如下:

     @RequestMapping("/setCookie")
    public String home(HttpServletResponse response,HttpServletRequest request) {
        request.getSession().setAttribute("sessionID", "haha");
        return "Success";
    }

请求后浏览器会保留一个cookie来存取sessionID

最后

以上就是清秀云朵为你收集整理的Cookie详解与跨域问题的全部内容,希望文章能够帮你解决Cookie详解与跨域问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部