定义
当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择,都纪录下来。当下次你再光临同一个网站,WEB 服务器会先看看有没有它上次留下的 Cookie 资料,有的话,就会依据 Cookie里的内容来判断使用者,送出特定的网页内容给你。 Cookie 的使用很普遍,许多有提供个人化服务的网站,都是利用 Cookie来辨认使用者,以方便送出使用者量身定做的内容,像是 Web 接口的免费 email 网站,都要用到 Cookie。
具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。
同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。
cookie机制。正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。
cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。
会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式
session机制。session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于SEEESIONID。但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:
<code class="hljs ocaml has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><form name=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"testform"</span> action=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/xxx"</span>>
<input <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">type</span>=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"hidden"</span> name=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"jsessionid"</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">value</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"</span>>
<input <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">type</span>=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"text"</span>>
</form></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
实际上这种技术可以简单的用对action应用URL重写来代替。
cookie 和session 的区别
- cookie数据存放在客户的浏览器上,session数据放在服务器上。
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE。
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
- 所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
Android的cookie和session
当Android应用程序访问WEB服务器的时候,我们为了与服务器保持同一会话,也就是说当前登录用户与服务器的交互是在同一个SessionId下。
当我们登录成功的时候,可以通过HTTP请求获取到Cookie信息,其中包括会话的SessionId,同时也可以自己将SessionId放入Json中返回。Session我们可以用一个静态变量来存放,每次向服务器发送请求的时候将SessionId带过去,服务器会自动检验这个SessionId有没有失效。
客户端第一次向服务器发送Http请求时,由于没有Cookie,在Http请求头中即Header中不包含”Cookie”。此时在服务器返回的相应(HttpResponse)中会多一个字段”Set-Cookie”,此字段的值就是服务器生成的Cookie值,下次再由此客户端程序访问该服务器时,就可以把该Cookie值放入Http请求头中。服务器就会知道是哪个用户再次访问了该服务器。客户端需要保存该Cookie以此用户再次访问服务器时使用。Cookie会有一个失效时间,客户端在Cookie失效后再次访问服务器,服务器会返回一个Cookie失效的状态码(比如403之类的),并在HttpResponse中包含”Set-Cookie”字段,这里面是新的Cookie。客户端需要做的操作是:1.将新Cookie覆盖旧的Cookie。2.跳入用户登录界面,让用户用新的Cookie重新登陆。Cookie 可以保存在SharePreferenced或者Sqlite中。
获取服务器的cookie:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">
List<Cookie> cookies = httpclient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getCookieStore</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getCookies</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span>
if (cookies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isEmpty</span>()) {
Log<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.i</span>(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"-------Cookie NONE---------"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span>
} else {
for (int i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; i < cookies.size(); i ) { </span>
//保存cookie
cookie = cookies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>(i)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span>
Log<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.d</span>(TAG, cookies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>(i)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getName</span>() <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"="</span> cookies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>(i)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getValue</span>() )<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span>
} </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>
添加到我们的POST或者GET请求里面
<code class="hljs vbscript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">DefaultHttpClient httpclient = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DefaultHttpClient();
HttpPost httpPost = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HttpPost(访问地址);
httpPost.setHeader(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Cookie"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"JSESSIONID="</span> + 我们在静态变量里存放的SessionId);
HttpResponse httpResponse = httpclient.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">execute</span>(httpPost);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
WebView中的Cookie同步问题
Cookie从Android最早的版本已经开始支持. 但Cookie在Android2.2以上才WebView才支持headers(Android2.2才加入了webview.load(url,headers)的API).
android.webkit.CookieManager是android cookie的管理类,可以讲客户端信息封装在cookiemanager中,这样系统发送请求时就自动带上这些cookie信息。
在Android手机中,Cookie的相关信息保存在/data/data/package_name/database/webview.db中.
Cookie的获取:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CookieManager cm = CookieManager<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getInstance</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
String Cookiestr = cm<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getCookie</span>(url)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
Cookie的同步:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CookieSyncManager<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.createInstance</span>(this)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
CookieSyncManager<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getInstance</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sync</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
注意,此处代码需在在webview加载URL前设置,并且在调用后,不再设置webview的websetttings属性,否则会导致失效.
清除Cookie:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CookieManager<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getInstance</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.removeSessionCookie</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
CookieManager<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getInstance</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.removeAllCookies</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
如果只是需要删除和特定url关联的cookie,需要先进行移除后同步:
<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 同步一下cookie
*/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">synCookies</span>(Context context, String url) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
cookieManager.removeSessionCookie();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//移除</span>
cookieManager.setCookie(url, cookies);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指定要修改的cookies</span>
CookieSyncManager.getInstance().sync();
}</code>