HttpClient进行http请求出现403

使用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那边的)


同样是403,其他的一些可能情况

    我这个情况可能特殊,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);



     2. 缺少cookie信息.  

        这个就需要分析实际的请求了。可以借助一些工具分析(http/https/tcp)请求链接,常见的工具有:

            Fiddler

            Wireshark

            还有直接浏览器调式也行,但是可能不够用,请求过程不够清晰


java端和android端部分关键代码

    不知道贴出来是否有实际用处,先贴出来吧。

    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 loginParams = 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 = 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", ""));
             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没问题- -


最后检查才发现:是我的http地址写错了,不是上面的问题,尴尬。

你可能感兴趣的:(HttpClient进行http请求出现403)