Android 實現 session 保持
最近在開發專案的過程中,遇到 android 與 web 伺服器要在同一 session 下通訊的問題。先來了解一下 session 機制 和 session 的實現方式:
Session機制
Session 機制是一種伺服器端的機制,伺服器使用一種類似於散列表的結構(也可能就是使用散列表)來儲存資訊。
當程式需要為某個客戶端的請求建立一個 session 的時候,伺服器首先檢查這個客戶端的請求裡是否已包含了一個 session 標識 - 稱為 session id,如果已包含一個session id 則說明以前已經為此客戶端建立過 session,伺服器就按照 session id 把這個 session 檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含 session id,則為此客戶端建立一個 session 並且生成一個與此 session 相關聯的 session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字串,這個 session id將被在本次響應中返回給客戶端儲存。
Session的實現方式
1 ) 使用Cookie來實現
伺服器給每個 Session 分配一個唯一的 JSESSIONID,並通過 Cookie 傳送給客戶端。
當客戶端發起新的請求的時候,將在 Cookie 頭中攜帶這個 JSESSIONID。這樣伺服器能夠找到這個客戶端對應的 Session。
2 )使用URL回顯來實現
URL回寫 是指伺服器在傳送給瀏覽器頁面的所有連結中都攜帶 JSESSIONID 的引數,這樣客戶端點選任何一個連結都會把 JSESSIONID 帶給伺服器。如果直接在瀏覽器中輸入 url 來請求資源,Session 是匹配不到的。Tomcat 對 Session 的實現,是一開始同時使用 Cookie 和 URL回寫機制,如果發現客戶端支援 Cookie,就繼續使用 Cookie,停止使用 URL回寫。如果發現 Cookie 被禁用,就一直使用 URL回寫。(jsp 開發處理到 Session 的時候,對頁面中的連結記得使用 response.encodeURL() )。
在解決問題前先了解下 Session 與 Cookie:
Cookie 和 Session都為了用來儲存狀態資訊,都是儲存客戶端狀態的機制,它們都是為了解決 HTTP 無狀態的問題所做的努力。
Session 可以用 Cookie 來實現,也可以用 URL回寫的機制來實現。
Cookie和Session有以下明顯的不同點:
1)Cookie 將狀態儲存在客戶端,Session 將狀態儲存在伺服器端;
2)Cookies 是伺服器在本地機器上儲存的小段文字並隨每一個請求傳送至同一個伺服器。網路伺服器用 HTTP 頭向客戶端傳送 cookies,在客戶端,瀏覽器解析這些 cookies 並將它們儲存為一個本地檔案,它會自動將同一伺服器的任何請求縛上這些 cookies。
3)Session 是針對每一個使用者的,變數的值儲存在伺服器上,用一個 sessionID 來區分是不同使用者 session 變數,這個值是通過使用者的瀏覽器在訪問的時候返回給伺服器,當客戶禁用 cookie 時,這個值也可能設定為由 get 來返回給伺服器;
4)就安全性來說:當你訪問一個使用 session 的站點,同時在自己機器上建立一個 cookie,建議在伺服器端的 SESSION 機制更安全些.因為它不會任意讀取客戶儲存的資訊。
/***************************** 以上為借鑑 < 華 麗 麗 的 分 割 線 > 以下為實踐 *****************************/
最近的 Android 專案,使用的是 XUtils 中的 HttpUtils 來實現網路資料請求,用 post 方式,將 sessionid 儲存在 cookie 中,傳送給伺服器。做法是 第一次資料請求時 將獲取到的 sessionid
的值儲存在一個靜態變數中,然後在第二次請求資料時,將這個 sessionid 放在 Cookie 中傳送給伺服器,伺服器則是通過這個 sessionid 來識別究竟是哪個客戶端在請求資料的, java 中這個 sessionid 的名字叫做 JSESSIONID (在
php 中這個 sessionid 的名字叫做 PHPSESSID)。java 中 sessionid 值的格式:JSESSIONID=AD5F5C9EEB16C71EC3725DBF209F6178,是鍵值對,不是單指值。
在 XUtils 中有一個 configCookieStore 用來設定請求中的 Cookie 物件,引數型別 org.apache.http.client.CookieStore,也就是說在第一次資料請求後,儲存CookieStore型別cookie即可。
下面是建立的一個類,使用 靜態變數 來實現 全域性共享(也可以使用自定義 Application 裡面增加變數):
package com.chitty.easylottery.configs;
import org.apache.http.client.CookieStore;
/**
* Created by Chitty on 2016/4/8.
* E-Mail:[email protected]
*/
public class MyCookieStore {
public static CookieStore cookieStore=null;
public static String SESSIONID = null;
}
在每次網路請求時設定:
final HttpUtils httpRequest = new HttpUtils();
//第一次一般是還未被賦值,若有值則將 SessionId 發給伺服器
if(null != MyCookieStore.SESSIONID){
httpPost.setHeader("Cookie", "JSESSIONID=" + MyCookieStore.SESSIONID);
LogUtils.i("login","== setHeader === SESSIONID ====="+ MyCookieStore.SESSIONID);
}
httpRequest.configCookieStore(MyCookieStore.cookieStore);
在第一次網路請求(一般為登陸操作)成功後(即在 HttpUtils 的 onSuccess()方法中寫 )設定:
DefaultHttpClient dh = (DefaultHttpClient) httpRequest.getHttpClient();
MyCookieStore.cookieStore = dh.getCookieStore();
CookieStore cs = dh.getCookieStore();
List<Cookie> cookies = cs.getCookies();
for (int i = 0; i < cookies.size(); i++) {
if ("JSESSIONID".equals(cookies.get(i).getName())) {
MyCookieStore.SESSIONID = cookies.get(i).getValue();
break;
}
}
即可實現 客戶端 與 服務端 的 session 保持。