1. 程式人生 > >http連續請求中Session丟失問題解決方案彙總

http連續請求中Session丟失問題解決方案彙總

先說遇到的問題:同一套介面,iOS端的APP可以正常使用而Android端的APP不能使用(可以登入成功)。

初步除錯發現:Android端的APP登入成功後,後續的訪問取不到登入時儲存在session中的使用者資訊,而iOS是可以取到session中使用者資訊。

下面是筆者解決該問題的過程總結:

先簡單說一下HTTP請求中的Session機制:Session資料儲存在伺服器端,SessionID儲存在客戶端的Cookies中(關閉瀏覽器時過期)。當客戶端向伺服器傳送的HTTP請求時,SessionID通過Cookies被髮送到伺服器,伺服器端根據Cookies中的SessionID獲取獲取此使用者的Session資訊。

回過頭說筆者遇到的問題,Android端的APP登陸後Session丟失的問題,正是因為Android客戶端在呼叫介面的時候,每次請求都是單獨發起的請求,所以沒有共享同一個Session。而iOS端可用,應該是iOS開發人員自己做了處理,因為筆者是做Java開發的,這個就不深入了。

現在的問題就簡化為:如何使同一個客戶端的多次請求都共享伺服器端的同一個Session。上網找資料後發現解決辦法有兩個:

1、每次請求中攜帶SessionID(儲存在Cookies中)

Java模擬傳送請求時加入下面一行程式碼:

conn.setRequestProperty("Cookie", "JSESSIONID=A399BA4C94EBF00534F5F444B07D30A3");

Java傳送post請求示例程式碼:

<span style="white-space:pre">	</span>/**
	 * 向指定 URL 傳送POST方法的請求
	 * 
	 * @param url
	 *            傳送請求的 URL
	 * @param param
	 *            請求引數,請求引數應該是 name1=value1&name2=value2 的形式。
	 * @return 所代表遠端資源的響應結果
	 */
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 開啟和URL之間的連線
			URLConnection conn = realUrl.openConnection();
			// 設定通用的請求屬性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

			// 將Session資訊放入請求攜帶的Cookies中 
			conn.setRequestProperty("Cookie", "JSESSIONID=A399BA4C94EBF00534F5F444B07D30A3");

			// 傳送POST請求必須設定如下兩行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 獲取URLConnection物件對應的輸出流
			out = new PrintWriter(conn.getOutputStream());
			// 傳送請求引數
			out.print(param);
			// flush輸出流的緩衝
			out.flush();
			// 定義BufferedReader輸入流來讀取URL的響應
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("傳送 POST 請求出現異常!" + e);
			e.printStackTrace();
		}
		// 使用finally塊來關閉輸出流、輸入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

2、在請求URL中加入;jsessionid=F8DA665F7A45AFD63F527CA49C3A67C8

注意:這裡並不是作為引數加到URL中,而是在?之前加的

例如:http://localhost:8080/aaa/bbb.jsp;jsessionid=saldjfsdflsaeir234?para=1

以上兩種方法都可以有效解決Session丟失問題,筆者採用的是第一種,第二種也親測可用。

本文的方法都是客戶端修改請求程式碼,還有另一種方法不用客戶端更改請求程式碼,只需要伺服器端做出修改,有興趣的話可以請檢視筆者另一篇博文:Java根據sessionId獲取Session物件