android實現(xiàn)session保持簡要概述及實現(xiàn)
更新時間:2013年03月04日 15:58:29 作者:
其實sesion在瀏覽器和web服務(wù)器直接是通過一個叫做name為sessionid的cookie來傳遞的,所以只要在每次數(shù)據(jù)請求時保持sessionid是同一個不變就可以用到web的session了,感興趣的你可以參考下本文或許對你有所幫助
在最近寫的一個Android中需要請求web服務(wù)器中的數(shù)據(jù),有一個登錄Activity,登錄后會到MainActivity,這中間登錄和MainActivity都需要請求php的jsonapi,所以要在網(wǎng)絡(luò)請求中保持session的,研究了好半天才搞定。其實sesion在瀏覽器和web服務(wù)器直接是通過一個叫做name為sessionid的cookie來傳遞的,所以只要在每次數(shù)據(jù)請求時保持sessionid是同一個不變就可以用到web的session了,做法是第一次數(shù)據(jù)請求時就獲取sessionid的值并保存在一個靜態(tài)變量中,然后在第二次請求數(shù)據(jù)的時候要將這個sessionid一并放在Cookie中發(fā)給服務(wù)器,服務(wù)器則是通過這個sessionid來識別究竟是那個客戶端在請求數(shù)據(jù)的,在php中這個sessionid的名字叫做PHPSESSID。下面貼下代碼
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
public class MyHttpClient implements InetConfig {
private DefaultHttpClient httpClient;
private HttpPost httpPost;
private HttpEntity httpEntity;
private HttpResponse httpResponse;
public static String PHPSESSID = null;
public LVHttpClient() {
}
public String executeRequest(String path, List<NameValuePair> params) {
String ret = "none";
try {
this.httpPost = new HttpPost(BASEPATH + path);
httpEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
httpPost.setEntity(httpEntity);
//第一次一般是還未被賦值,若有值則將SessionId發(fā)給服務(wù)器
if(null != PHPSESSID){
httpPost.setHeader("Cookie", "PHPSESSID=" + PHPSESSID);
}
httpClient = new DefaultHttpClient();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = httpResponse.getEntity();
ret = EntityUtils.toString(entity);
CookieStore mCookieStore = httpClient.getCookieStore();
List<Cookie> cookies = mCookieStore.getCookies();
for (int i = 0; i < cookies.size(); i++) {
//這里是讀取Cookie['PHPSESSID']的值存在靜態(tài)變量中,保證每次都是同一個值
if ("PHPSESSID".equals(cookies.get(i).getName())) {
PHPSESSID = cookies.get(i).getValue();
break;
}
}
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return ret;
}
}
其實web的原理都是一樣的,基于http協(xié)議的,那么如果網(wǎng)站不是php做的話,那個叫做Sessionid的Cookie可能叫做別的了,就不是PHPSESSID了,而是叫做別的名字了,這個可能要具體情況去查了。
其實不只是Android程序,其他任何程序需要這么用的時候只需要在http協(xié)議請求header里頭加上發(fā)送相應(yīng)的SessionId就可以了。剛剛這種方法是可以幫助理解sessionid的,其實還有一種方法如果更通用的話,就可以將剛剛所有的Cookie每次都發(fā)回到服務(wù)器端,也就可以解決session保持的問題了,只是這樣可能會稍微大些網(wǎng)絡(luò)流量開銷而已。
這里看到一個SessionId的本質(zhì),順便mark一下。
SessionID的本質(zhì)
一、客戶端用cookie保存了sessionID
客戶端用cookie保存了sessionID,當(dāng)我們請求服務(wù)器的時候,會把這個sessionID一起發(fā)給服務(wù)器,服務(wù)器會到內(nèi)存中搜索對應(yīng)的sessionID,如果找到了對應(yīng)的 sessionID,說明我們處于登錄狀態(tài),有相應(yīng)的權(quán)限;如果沒有找到對應(yīng)的sessionID,這說明:要么是我們把瀏覽器關(guān)掉了(后面會說明為什 么),要么session超時了(沒有請求服務(wù)器超過20分鐘),session被服務(wù)器清除了,則服務(wù)器會給你分配一個新的sessionID。你得重 新登錄并把這個新的sessionID保存在cookie中。
在沒有把瀏覽器關(guān)掉的時候(這個時候假如已經(jīng)把sessionID保存在cookie中了)這個sessionID會一直保存在瀏覽器中,每次請求的時候都會把這個sessionID提交到服務(wù)器,所以服務(wù)器認(rèn)為我們是登錄的;當(dāng)然,如果太長時間沒有請求服務(wù)器,服務(wù)器會認(rèn)為我們已經(jīng)所以把瀏覽器關(guān)掉了,這個時候服務(wù)器會把該sessionID從內(nèi)存中清除掉,這個時候如果我們再去請求服務(wù)器,sessionID已經(jīng)不存在了,所以服務(wù)器并沒有在內(nèi)存中找到對應(yīng)的 sessionID,所以會再產(chǎn)生一個新的sessionID,這個時候一般我們又要再登錄一次。
二、客戶端沒有用cookie保存sessionID
這 個時候如果我們請求服務(wù)器,因為沒有提交sessionID上來,服務(wù)器會認(rèn)為你是一個全新的請求,服務(wù)器會給你分配一個新的sessionID,這就是 為什么我們每次打開一個新的瀏覽器的時候(無論之前我們有沒有登錄過)都會產(chǎn)生一個新的sessionID(或者是會讓我們重新登錄)。
當(dāng)我們一旦把瀏覽器關(guān)掉后,再打開瀏覽器再請求該頁面,它會讓我們登錄,這是為什么?我們明明已經(jīng)登錄了,而且還沒有超時,sessionID肯定還在服 務(wù)器上的,為什么現(xiàn)在我們又要再一次登錄呢?這是因為我們關(guān)掉瀏覽再請求的時候,我們提交的信息沒有把剛才的sessionID一起提交到服務(wù)器,所以服務(wù)器不知道我們是同一個人,所以這時服務(wù)器又為我們分配一個新的sessionID,打個比方:瀏覽器就好像一個要去銀行開戶的人,而服務(wù)器就好比銀行, 這個要去銀行開戶的人這個時候顯然沒有帳號(sessionID),所以到銀行后,銀行工作人員問有沒有帳號,他說沒有,這個時候銀行就會為他開通一個帳 號。所以可以這么說,每次打開一個新的瀏覽器去請求的一個頁面的時候,服務(wù)器都會認(rèn)為,這是一個新的請求,他為你分配一個新的sessionID。
復(fù)制代碼 代碼如下:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
public class MyHttpClient implements InetConfig {
private DefaultHttpClient httpClient;
private HttpPost httpPost;
private HttpEntity httpEntity;
private HttpResponse httpResponse;
public static String PHPSESSID = null;
public LVHttpClient() {
}
public String executeRequest(String path, List<NameValuePair> params) {
String ret = "none";
try {
this.httpPost = new HttpPost(BASEPATH + path);
httpEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
httpPost.setEntity(httpEntity);
//第一次一般是還未被賦值,若有值則將SessionId發(fā)給服務(wù)器
if(null != PHPSESSID){
httpPost.setHeader("Cookie", "PHPSESSID=" + PHPSESSID);
}
httpClient = new DefaultHttpClient();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = httpResponse.getEntity();
ret = EntityUtils.toString(entity);
CookieStore mCookieStore = httpClient.getCookieStore();
List<Cookie> cookies = mCookieStore.getCookies();
for (int i = 0; i < cookies.size(); i++) {
//這里是讀取Cookie['PHPSESSID']的值存在靜態(tài)變量中,保證每次都是同一個值
if ("PHPSESSID".equals(cookies.get(i).getName())) {
PHPSESSID = cookies.get(i).getValue();
break;
}
}
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return ret;
}
}
其實web的原理都是一樣的,基于http協(xié)議的,那么如果網(wǎng)站不是php做的話,那個叫做Sessionid的Cookie可能叫做別的了,就不是PHPSESSID了,而是叫做別的名字了,這個可能要具體情況去查了。
其實不只是Android程序,其他任何程序需要這么用的時候只需要在http協(xié)議請求header里頭加上發(fā)送相應(yīng)的SessionId就可以了。剛剛這種方法是可以幫助理解sessionid的,其實還有一種方法如果更通用的話,就可以將剛剛所有的Cookie每次都發(fā)回到服務(wù)器端,也就可以解決session保持的問題了,只是這樣可能會稍微大些網(wǎng)絡(luò)流量開銷而已。
這里看到一個SessionId的本質(zhì),順便mark一下。
SessionID的本質(zhì)
一、客戶端用cookie保存了sessionID
客戶端用cookie保存了sessionID,當(dāng)我們請求服務(wù)器的時候,會把這個sessionID一起發(fā)給服務(wù)器,服務(wù)器會到內(nèi)存中搜索對應(yīng)的sessionID,如果找到了對應(yīng)的 sessionID,說明我們處于登錄狀態(tài),有相應(yīng)的權(quán)限;如果沒有找到對應(yīng)的sessionID,這說明:要么是我們把瀏覽器關(guān)掉了(后面會說明為什 么),要么session超時了(沒有請求服務(wù)器超過20分鐘),session被服務(wù)器清除了,則服務(wù)器會給你分配一個新的sessionID。你得重 新登錄并把這個新的sessionID保存在cookie中。
在沒有把瀏覽器關(guān)掉的時候(這個時候假如已經(jīng)把sessionID保存在cookie中了)這個sessionID會一直保存在瀏覽器中,每次請求的時候都會把這個sessionID提交到服務(wù)器,所以服務(wù)器認(rèn)為我們是登錄的;當(dāng)然,如果太長時間沒有請求服務(wù)器,服務(wù)器會認(rèn)為我們已經(jīng)所以把瀏覽器關(guān)掉了,這個時候服務(wù)器會把該sessionID從內(nèi)存中清除掉,這個時候如果我們再去請求服務(wù)器,sessionID已經(jīng)不存在了,所以服務(wù)器并沒有在內(nèi)存中找到對應(yīng)的 sessionID,所以會再產(chǎn)生一個新的sessionID,這個時候一般我們又要再登錄一次。
二、客戶端沒有用cookie保存sessionID
這 個時候如果我們請求服務(wù)器,因為沒有提交sessionID上來,服務(wù)器會認(rèn)為你是一個全新的請求,服務(wù)器會給你分配一個新的sessionID,這就是 為什么我們每次打開一個新的瀏覽器的時候(無論之前我們有沒有登錄過)都會產(chǎn)生一個新的sessionID(或者是會讓我們重新登錄)。
當(dāng)我們一旦把瀏覽器關(guān)掉后,再打開瀏覽器再請求該頁面,它會讓我們登錄,這是為什么?我們明明已經(jīng)登錄了,而且還沒有超時,sessionID肯定還在服 務(wù)器上的,為什么現(xiàn)在我們又要再一次登錄呢?這是因為我們關(guān)掉瀏覽再請求的時候,我們提交的信息沒有把剛才的sessionID一起提交到服務(wù)器,所以服務(wù)器不知道我們是同一個人,所以這時服務(wù)器又為我們分配一個新的sessionID,打個比方:瀏覽器就好像一個要去銀行開戶的人,而服務(wù)器就好比銀行, 這個要去銀行開戶的人這個時候顯然沒有帳號(sessionID),所以到銀行后,銀行工作人員問有沒有帳號,他說沒有,這個時候銀行就會為他開通一個帳 號。所以可以這么說,每次打開一個新的瀏覽器去請求的一個頁面的時候,服務(wù)器都會認(rèn)為,這是一個新的請求,他為你分配一個新的sessionID。
相關(guān)文章
RecyclerView中監(jiān)聽EditText變化的BUG的解決方法
本篇文章主要介紹了RecyclerView中監(jiān)聽EditText變化的BUG的解決方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11Android 側(cè)邊滑動關(guān)閉Activity的示例代碼
這篇文章主要介紹了Android 側(cè)邊滑動關(guān)閉Activity的方法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05Android定制RadioButton樣式三種實現(xiàn)方法
三種方法實現(xiàn)Android定制RadioButton樣式:使用XML文件進(jìn)行定義/在JAVA代碼中定義等等,感興趣的朋友可以參考下,希望可以幫助到你2013-02-02Android實現(xiàn)回彈ScrollView的原理
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)回彈ScrollView的原理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Presenting?Streams?in?Flutter小技巧
這篇文章主要為大家介紹了Presenting?Streams?in?Flutter小技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android Activity啟動模式之singleTask實例詳解
這篇文章主要介紹了Android Activity啟動模式之singleTask,結(jié)合實例形式較為詳細(xì)的分析了singleTask模式的功能、使用方法與相關(guān)注意事項,需要的朋友可以參考下2016-01-01Android入門之onTouchEvent觸碰事件的示例詳解
今天給大家?guī)淼氖荰ouchListener與OnTouchEvent的比較,以及多點觸碰的知識點!?文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-12-12