出现的过程
最近在用程序模拟一个web站的https登录,然后进行一些后续操作的小玩意。先使用java程序写测试代码,测试通过移植到android。
java基于httpclient-4.3.1.jar开发。
android端使用自带的HttpClient。(sdk版本14)
代码移植到android环境,https请求出现403(请求被拒绝),Google N久找不到答案 - -。但是java一次又一次都能成功!
处理方法
最终换jar!使用commons-httpclient-3.1.jar!业务逻辑不变,程序测试通过!
我!很!忧!伤!(java端可以,android端不行。)
(jar是从http://git.oschina.net/atearsan/android-app/tree/master/libs里下的- -,我懒,直接用osc那边的)
同样是403,其他的一些可能情况
我这个情况可能特殊,Google时也发现了其他的一些情况,顺便记录下。
1. 缺少header参数. 常见的如下:
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);
这个就需要分析实际的请求了。可以借助一些工具分析(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);
}
}
// 代码真的没啥差异,android端被注释的那些就是使用自带的HttpClient,但是偏偏登录请求一直是403.
// 换成基于commons-httpclient-3.1.jar的HttpClient,没问题了!
//
// 我还有个问题就是:android sdk 14 自带的apche HttpClient是什么年代的版本...??? java端4.3没问题- -
来源:oschina
链接:https://my.oschina.net/u/94055/blog/205517