什么是Session, 什么是Cookie?
Session是由應用服務器維持的一個服務器端的存儲空間,用戶在連接服務器時,會由服務器生成一個唯一的SessionID,用該SessionID為標識符來存取服務器端的Session存儲空間。而SessionID這一數據則是保存到客戶端,用Cookie保存的,用戶提交頁面時,會將這一SessionID提交到服務器端,來存取Session數據。這一過程,是不用開發人員干預的。所以一旦客戶端禁用Cookie,那么Session也會失效。Cookie是客戶端的存儲空間,由瀏覽器來維持。
Url重寫
服務器也可以通過URL重寫的方式來傳遞SessionID的值,因此不是完全依賴Cookie。如果客戶端Cookie禁用,則服務器可以自動通過重寫URL的方式來保存Session的值,並且這個過程對程序員透明。可以試一下,即使不寫Cookie,在使用request.getCookies();取出的Cookie數組的長度也是1,而這個Cookie的名字就是JSESSIONID,還有一個很長的二進制的字符串,是SessionID的值。實質上 URL 重寫是通過向 URL 連接添加參數,並把 session ID 作為值包含在連接中。然而,為使這生效,你需要為你的 servlet 響應部分的每個連接添加 session ID.
同源下http cookie的協議
在同源時,不管是ajax請求還是普通的get post請求,瀏覽器訪問時都是會帶着本域下所有的cookie一起訪問服務端。服務端在響應時又會通過http header中的set cookie返回給瀏覽器。瀏覽器把cookie再寫入該域名下的cookie存儲空間。如此來循環
跨域下http cookie的協議
當跨域時,瀏覽器端請求服務端都不會帶着cookie的信息。在使用ajax請求時,如果不進行特殊的處理還會有同源錯誤產生,更不用說帶着cookie了。 服務端返回的cookie,瀏覽器也不會寫入其對應的域名下的存儲空間。那么怎么解決這個問題,xmlhttprequest 2 給出了解決方案。
方案:
需要在 ajax請求參數中帶上 withCredentials ,值為true。如果是 jquery方式,則是這樣設置:
$.ajax({ url: a_cross_domain_url, // 將XHR對象的withCredentials設為true xhrFields:{ withCredentials:true }});
針對這樣一般的瀏覽器(IE11以下版本不支持,還有個別垃圾瀏覽器不支持,這點請注意)就會允許跨域資源共享。
同時服務器端還需要設置 Access-Control-Allow-Credentials 為true。
如下面是 java 的設置方式:
response().setHeader("Access-Control-Allow-Credentials", "true");
response().setHeader("Access-Control-Allow-Origin", "fromeDomain.com");
注意,這里fromeDomain.com 不能設置為 * 來允許全部,如果在 Credentials 是true 的情況下。因為瀏覽器會報錯如下:
A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://xxxxxxxxxx' is therefore not allowed access
所以只能乖乖的設置成客戶端頁面的 域名。
有一點需要注意,設置了widthCredentials為true的請求中會包含遠程域的所有cookie,但這些cookie仍然遵循同源策略,所以你是訪問不了這些cookie的。
是當提交一個請求到異域時,后台嘗試在響應中綁定cookie信息,以告知瀏覽器去保存這個cookie,但是默認情況下,瀏覽器是不會去為你創建cookie的,具體現象就是你發現在響應中已經有set-cookie的響應頭了並且有值,而且瀏覽器也會有信息顯示已接收到cookie了,但是就是在cookie中找不到。沒錯,該現象就是因為你是跨域提交的創建cookie的請求。那么如果我們非要瀏覽器去創建這個cookie怎么辦呢?這里就要使用到一個xmlHttpRequest對象的屬性xhrFields,官方文檔的解釋如下: A map of fieldName-fieldValue pairs to set on the native XHR object. For example, you can use it to setwithCredentials to true for cross-domain requests if needed.
設置了withCredentials:true 之后可以解決一個發送,一個設置的問題
1、允許創建來自不同域的cookie信息;2、每次的跨域請求都允許帶上該cookie信息
另外:ajax在異域請求的時候有時會發送option請求
1.第一步 服務端設置響應頭
header('Access-Control-Allow-Origin:*'); //支持全域名訪問,不安全,部署后需要固定限制為客戶端網址
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支持的http 動作
header('Access-Control-Allow-Headers:x-requested-with,content-type'); //響應頭 請按照自己需求添加。
2.第二部 了解IE chrome 等瀏覽器 對於 跨域請求並要求設置Headers自定義參數的時候的 "預請求" 就是如果遇到 跨域並設置headers的請求,所有請求需要兩步完成!
A 第一步:發送預請求 OPTIONS 請求。此時 服務器端需要對於OPTIONS請求作出響應 一般使用202響應即可 不用返回任何內容信息。(能看到這份手稿的人,本人不相信你后台處理不了一個options請求)
B 第二步:服務器accepted 第一步請求后 瀏覽器自動執行第二步 發送真正的請求。此時 大多數人 會發現請求成功了,但是 有那么幾個人會發現 請求成功了但是沒有任何信息返回 why?因為你自定義的請求頭在服務器響應中不存在!
查看console輸出 會發現一個問題:
“Access-Control-Allow-Headers 列表中不存在請求標頭 XXXXXX”【IE】,
request header field xxxxxx is not allowed by Access-Control-Allow-Header【chrome】
這是因為 你的XXXX請求頭 沒有在服務器端被允許哦~
遇到這個問題 只有通過修改服務器端來完成,舉例:需要設置 requesttype這么一個自定義頭,那么 你需要在 服務端里面 將header('Access-Control-Allow-Headers:x-requested-with,content-type,requesttype'); 同學們自行體會吧 這種語法就是根據“,”分割 自己需要設置什么頭,必須要在 服務端請求的響應頭里面設置好,不然客戶端永遠永遠提交不上去!