Android 使用自帶的HttpClient進行https請求出現403的解決過程記錄

出現的過程

    最近在用程序模擬一個web站的https登陸,而後進行一些後續操做的小玩意。先使用java程序寫測試代碼,測試經過移植到android。 java

    java基於httpclient-4.3.1.jar開發。 android

    android端使用自帶的HttpClient。(sdk版本14) git

    代碼移植到android環境,https請求出現403(請求被拒絕),Google N久找不到答案 - -。可是java一次又一次都能成功! web

處理方法

    最終換jar!使用commons-httpclient-3.1.jar!業務邏輯不變,程序測試經過! apache

    我!很!憂!傷!(java端能夠,android端不行。) 瀏覽器

    (jar是從http://git.oschina.net/atearsan/android-app/tree/master/libs裏下的- -,我懶,直接用osc那邊的)
cookie


一樣是403,其餘的一些可能狀況

    我這個狀況可能特殊,Google時也發現了其餘的一些狀況,順便記錄下。
app

    1. 缺乏header參數. 常見的以下: tcp

        

post.addHeader("Referer", xx);
post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63");
post.addHeader("Host", xx);



    2. 缺乏cookie信息.

        這個就須要分析實際的請求了。能夠藉助一些工具分析(http/https/tcp)請求連接,常見的工具備: 工具

            Fiddler

            Wireshark

            還有直接瀏覽器調式也行,可是可能不夠用,請求過程不夠清晰


java端和android端部分關鍵代碼

    不知道貼出來是否有實際用處,先貼出來吧。

    java端:

    

public void login() {
		try {
			List<NameValuePair> loginParams = new ArrayList<NameValuePair>();
			loginParams.add(new BasicNameValuePair("appuri", appuri));
			loginParams.add(new BasicNameValuePair("useruri", useruri));
			loginParams.add(new BasicNameValuePair("service", service));
			loginParams.add(new BasicNameValuePair("sid", null));
			loginParams.add(new BasicNameValuePair("uname", name));
			loginParams.add(new BasicNameValuePair("action", action));
			loginParams.add(new BasicNameValuePair("pwd", password));

			HttpPost post = new HttpPost(loginURL);
			post.addHeader("Referer", referer);
			post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63");
			post.addHeader("Host", "xxxxxxxxx");
			post.setEntity(new UrlEncodedFormEntity(loginParams, HTTP.UTF_8));

			// 發送登陸請求
			HttpResponse response = httpClient.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) {
				post.releaseConnection();
				
				// 獲取重定向地址
				String location = getLocation(response);
				if (!"".equals(location)) {
					String signURL = getSignURL(location);
					if(!"".equals(signURL)) {
						signIn(signURL);
					} else {
						System.out.println("signURL爲空");
					}
				} else {
					System.out.println("location爲空");
				}
			} else {
				System.out.println("登陸出錯了");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}



    android端的實現:

public void login() {
		try {
			/*
			List<NameValuePair> loginParams = new ArrayList<NameValuePair>();
			loginParams.add(new BasicNameValuePair("appuri", appuri));
			loginParams.add(new BasicNameValuePair("useruri", useruri));
			loginParams.add(new BasicNameValuePair("service", service));
			loginParams.add(new BasicNameValuePair("sid", ""));
			loginParams.add(new BasicNameValuePair("uname", name));
			loginParams.add(new BasicNameValuePair("action", action));
			loginParams.add(new BasicNameValuePair("pwd", password));

			HttpPost post = new HttpPost(loginURL);
			post.addHeader("Referer", referer);
			post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63");
			post.addHeader("Host", "xxx");
			post.setEntity(new UrlEncodedFormEntity(loginParams, HTTP.UTF_8));

			HttpResponse response = httpClient.execute(post);
			*/
			HttpClient cc = new HttpClient();
			PostMethod pm = new PostMethod(loginURL);
			org.apache.commons.httpclient.NameValuePair[] parametersBody = {
					new org.apache.commons.httpclient.NameValuePair("appuri", appuri),
					new org.apache.commons.httpclient.NameValuePair("useruri", useruri),
					new org.apache.commons.httpclient.NameValuePair("service", service),
					new org.apache.commons.httpclient.NameValuePair("sid", ""),
					new org.apache.commons.httpclient.NameValuePair("uname", name),
					new org.apache.commons.httpclient.NameValuePair("action", action),
					new org.apache.commons.httpclient.NameValuePair("pwd", password)	
			};
			pm.setRequestBody(parametersBody);
			pm.setRequestHeader("Referer", referer);
			pm.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			pm.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63");
			pm.setRequestHeader("Host", "xxx");
			
//			int statusCode = response.getStatusLine().getStatusCode();
			int statusCode = cc.executeMethod(pm);	// 登陸請求
			if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
				
				String location = getLocation(pm);	// 獲取重定向地址
//				String location = getLocation(response);
				if (!TUtil.EMPTY.equals(location)) {
					String signURL = getSignURL(location);
					if(!TUtil.EMPTY.equals(signURL)) {
						signIn(signURL);
					} else {
						String log = "獲取簽到地址失敗";
						super.notification(TUtil.TYPE_CM_E_CODE, log);
					}
				} else {
					String log = "獲取重定向地址失敗";
					super.notification(TUtil.TYPE_CM_E_CODE, log);
				}
			} else {
				String log = "登陸失敗.狀態碼:"+statusCode;
				super.notification(TUtil.TYPE_CM_E_CODE, log);
			}
		} catch (Exception e) {
			Log.e(e);
			
			String log = "登陸異常:"+e.getMessage();
			super.notification(TUtil.TYPE_CM_E_CODE, log);
		}
	}



    // java端和android代碼對比結果:

    // 代碼真的沒啥差別,android端被註釋的那些就是使用自帶的HttpClient,可是恰恰登陸請求一直是403.

    // 換成基於commons-httpclient-3.1.jar的HttpClient,沒問題了!

    // 

    // 我還有個問題就是:android sdk 14 自帶的apche HttpClient是什麼年代的版本...??? java端4.3沒問題- -

相關文章
相關標籤/搜索