Cookie中的sessionid与JSONP原理

一、首先说明一下cookie中的sessionid的作用。

1、cookie只是一些文本内容,多是键值对的形式,是请求头中的一部分

2、http是无连接的

知道这两点,就可以很容易的理解sessionid的作用的。

session是保存在服务器端的,与客户端的一次会话。session中用于保存会话的一些内容,可以理解为服务器给一个用户开辟出来的一段内存空间用于保存这次会话的一些内容。

问题在于http是无连接的,所以在http请求结束之后,第二次请求过来时,服务器端是不会知道这次的请求是谁发送的,以及上一次通信的session是什么。这些都是无从得知的,要想知道这次通信,对应的哪个session,就需要cookie来标记了。在cookie中,只要有一次通信,基本上就会有sessionid存在(取决于服务器,应用服务器都会放置sessionid,如tomcat放在cookie中的sessionid叫做jsessionid),在第二次请求时,服务器从cookie中获取sessionid参数,在自己现有的session中寻找该id,如果存在则用此session作为这次通信的session,如果不存在,则重新创建一个。session是会过期的,原因也在这里,服务器是不会知道客户端(浏览器)是否还会进行第二次请求,而且cookie是可以手动清空的,如果一直为其保留session,该session可能永远不会用到,这样下来服务器的内存肯定会承受不了,所以session是一定要有过期这个概念的。

同时,由于一些浏览器,不支持cookie,这个时候sessionid放在哪里呢?放在url中,因为Session默认是需要Cookie支持的,但有些客户浏览器是关闭Cookie的,而jsessionid是存储在Cookie中的,如果禁用Cookie的话,也就是说服务器那边得不到jsessionid,这样也就没法根据jsessionid获得对应的session了,获得不了session就得不到session中存储的数据了。这个时候就需要在URL中指定服务器上的session标识,也就是类似于“jsessionid=5F4771183629C9834F8382E23BE13C4C” 这种格式。

用一个方法(忘了方法的名字)处理URL串就可以得到这个东西,这个方法会判断你的浏览器是否开启了Cookie,如果他认为应该加他就会加上去。
摘抄:所谓session你可以这样理解:当你与服务端进行会话时,比如说登陆成功后,服务端会为你开壁一块内存区间,用以存放你这次会话的一些内容,比如说用户名之类的。那么就需要一个东西来标志这个内存区间是你的而不是别人的,这个东西就是session id(jsessionid只是tomcat中对session id的叫法,在其它容器里面,不一定就是叫jsessionid了。),而这个内存区间你可以理解为session。
然后,服务器会将这个session id发回给你的浏览器,放入你的浏览器的cookies中(这个cookies是内存cookies,跟一般的不一样,它会随着浏览器的关闭而消失)。
之后,只有你浏览器没有关闭,你每向服务器发请求,服务器就会从你发送过来的cookies中拿出这个session id,然后根据这个session id到相应的内存中取你之前存放的数据。
但是,如果你退出登陆了,服务器会清掉属于你的内存区域,所以你再登的话,会产生一个新的session了。
不好意思,我可能说得不太清楚,但这方面的知识网上有不少,你可以了解下session的原理。
session是有一定作用域的,而且是有时间限制的。
jsessionid是服务器那边生成的,因为cookie是服务器那边送到客户端的信息。不管能不能修改jsessionid,都不应该修改,如果你修改了,这就失去了jessionid的自身意义了,你修改的话,你让服务器那边如何找到对应的session?找不到的话,你存放在那个session中的数据不是取不到了吗?
登陆然后退出,我认为会重新生成一个jsessionid。因为退出的话,application作用域的数据都会丢失,更何况这个比它作用域还小的session?既然session都消失了,这个jsessionid有什么用?存入后url格式为:wapbrowse.jsp;jsessionid=5AC6268DD8D4D5D1FDF5D41E9F2FD960?curAlbumID=9
 
二、JS跨域与JSONP
由于JS同源策略的影响,XmlHttpRequest(即Ajax请求对象)的请求是不能跨域的:
URL说明是否允许通信
http://www.a.com/a.js 
http://www.a.com/b.js
同一域名下 允许
http://www.a.com/lab/a.js 
http://www.a.com/script/b.js
同一域名下不同文件夹 允许
http://www.a.com:8000/a.js 
http://www.a.com/b.js
同一域名,不同端口 不允许
http://www.a.com/a.js 
https://www.a.com/b.js
同一域名,不同协议 不允许
http://www.a.com/a.js 
http://70.32.92.74/b.js
域名和域名对应ip 不允许
http://www.a.com/a.js 
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js 
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js 
http://www.a.com/b.js
不同域名 不允许
但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。即通过<script src="http://url" type="text/javascript">标签引入js文件。
比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data.php,那么a.html中的代码就可以这样:
服务器端则需要返回js代码,而不能只返回json对象,js代码为dosomething(jsondata),这样到前台来,就相当于直接执行了前台的方法dosomething,远程的json数据也就传过来的。
这个是php服务器端的特殊处理,只用在原json对象变为callback(json对象)即可。

所以通过http://example.com/data.php?callback=dosomething得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

下面为其他示例:

服务器端:

        protected void Page_Load(object sender, EventArgs e)
        {
            string result = "callback({\"name\":\"zhangsan\",\"date\":\"2012-12-03\"})";

            Response.Clear();
            Response.Write(result);
            Response.End();
        }

客户端:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">

        var result = null;
        window.onload = function () {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "http://192.168.0.101/ExampleBusinessApplication.Web/web2.aspx";

            var head = document.getElementsByTagName("head")[0];
            head.insertBefore(script, head.firstChild);

        };

        function callback(data) {
            result = data;
        }

        function b_click() {
            alert(result.name);
        }
    </script>
</head>
<body>
    <input type="button" value="click me!" onclick="b_click();" />
</body>
</html>

 同时通过jQuery可以简单的实现这个功能:

通过jquery的jsonp的方式.使用此方式,对服务器端有要求.

服务器端如下:

        protected void Page_Load(object sender, EventArgs e)
        {
            string callback = Request.QueryString["jsoncallback"];

            string result = callback + "({\"name\":\"zhangsan\",\"date\":\"2012-12-03\"})";

            Response.Clear();
            Response.Write(result);
            Response.End();
        }


客户端:

$.ajax({ 
                async: false, 
                url: "http://192.168.0.5/Web/web1.aspx", 
                type: "GET", 
                dataType: 'jsonp', 
                //jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncallback的值对应的对象. 
                jsonp: 'jsoncallback', 
                //要传递的参数,没有传参时,也一定要写上 
                  data: null, 
                timeout: 5000, 
                //返回Json类型 
                  contentType: "application/json;utf-8", 
                //服务器段返回的对象包含name,data属性. 
                success: function (result) { 
                    alert(result.date); 
                }, 
                error: function (jqXHR, textStatus, errorThrown) { 
                    alert(textStatus); 
                } 
            });

实际上,在我们执行这段js时,js向服务器发出了这样一个请求:

http://192.168.0.5/Web/web1.aspx?jsoncallback=jsonp1354505244726&_=1354505244742 

而服务器也相应的返回了如下对象:

jsonp1354506338864({"name":"zhangsan","date":"2012-12-03"})
此时就实现了跨域范文数据的要求.

简单方法:

原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

 其他跨域方法有:http://www.cnblogs.com/2050/p/3191744.html

posted @ 2015-06-24 23:13  光闪  阅读(8034)  评论(0编辑  收藏  举报