使用HttpClient进行http请求时,出现403错误,搜到一些解决办法,记录下来。
第一种是http请求:
原文地址:
http://blog.csdn.net/yue_pengcheng/article/details/10820231
Android,使用Apache HttpClient 和 HttpURLConnection 访问服务器接口,被拒绝,返回403 forbidden,然而同样的URL使用浏览器访问是正常的。
(注:本篇问题仅限于Http请求,若是Https请求可先检查SSL设置)
查了下关于403的几种可能性:
403 禁止访问:访问被拒绝
403.1 禁止访问:执行访问被拒绝
403.2 禁止访问:读取访问被拒绝
403.3 禁止访问:写入访问被拒绝
403.4 禁止访问:需要使用 SSL 查看该资源
403.5 禁止访问:需要使用 SSL 128 查看该资源
403.6 禁止访问:客户端的 IP 地址被拒绝
403.7 禁止访问:需要 SSL 客户端证书
403.8 禁止访问:客户端的 DNS 名称被拒绝
403.9 禁止访问:太多客户端试图连接到 Web 服务器
403.10 禁止访问:Web 服务器配置为拒绝执行访问
403.11 禁止访问:密码已更改
403.12 禁止访问:服务器证书映射器拒绝了客户端证书访问
403.13 禁止访问:客户端证书已在 Web 服务器上吊销
403.14 禁止访问:在 Web 服务器上已拒绝目录列表
403.15 禁止访问:Web 服务器已超过客户端访问许可证限制
403.16 禁止访问:客户端证书格式错误或未被 Web 服务器信任
403.17 禁止访问:客户端证书已经到期或者尚未生效
403.18 禁止访问:无法在当前应用程序池中执行请求的URL
403.19 禁止访问:无法在该应用程序池中为客户端执行CGI
403.20 禁止访问:Passport 登录失败
通过一系列操作,排除法将问题锁定在Http头字段的问题上。使用HttpWatch 检测浏览器的头字段设置,发现User-Agent字段可能存在问题。
打印源生的的User-Agent字段是null,尝试设置UA字段,看下IE浏览器User-Agent的格式:
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4)"
HttpUriRequest.setHeader("User-Agent",“Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4)”);
(注:HttpUriRequest类是HttpGet 和 HttpPost的父类)
可以正常访问了。
另外:我们可以使用User-Agent字段做一些统计信息的提交,只要遵从特定格式即可,例如:
“Mozilla/5.0 (Android/4.0.3; HUAWEI U9200; IMEI/111111111111111; IMSI/111111111111)”
可以根据自己的需要添加特定字段。
自此我的问题解决了。
关于403,还存在另外一种可能,Referer 字段,某些网站做了盗链的限制,仅限于本网站链接导入的网址才可以访问,这时我们可以设置Referer字段:
HttpUriRequest.setHeader("Referer","http://,,,");
使用HttpURLConnection访问的同学可以是用
conn.setRequestProperty("Referer", "http://,,,");
value字段可以是访问接口的域名地址。
相比起接口,图片和文件防止盗链的限制更多一些,也可以在下载图片或其他类型文件的请求中添加Referer头字段,问题就解决啦。
第二篇是关于https的请求:
http://my.oschina.net/atearsan/blog/205517
最近在用程序模拟一个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那边的)
我这个情况可能特殊,Google时也发现了其他的一些情况,顺便记录下。
1. 缺少header参数. 常见的如下:
1
2
3
4
|
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端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
public
void
login() {
try
{
List
new
ArrayList
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端的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
public
void
login() {
try
{
/*
List
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没问题- -