首页 > Android 使用自带的HttpClient进行https请求出现403的解决过程记录

Android 使用自带的HttpClient进行https请求出现403的解决过程记录

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

出现的过程

    最近在用程序模拟一个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);





    2. 缺少cookie信息.

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

            Fiddler

            Wireshark

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



java端和android端部分关键代码

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

    java端:

    

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端的实现:

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没问题- -



转载于:https://my.oschina.net/atearsan/blog/205517

更多相关:

  • 菜鸟一枚,正在学习C++ Gui Qt4,整理很零碎,欢迎批评指正   1.窗口标题: QWidget *window = new QWidget; window->setWindowTitle("Enter Your Age"); **************************************** 关于标题...

  • 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 总体思路是: 比较两个链表头节点,较小的插入新链表指针之后,同时较小链表指针向后移动一位 实现如下: ListNode* mergeTwo...

  • 1.直接调用微软socket对象处理 static void Main(string[] args){try{IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });//在3721端口新建一个TcpListener对象TcpListener listener = new...

  •   现在很多地方都会用到zookeeper, 用到它的地方就是为了实现分布式。用到的场景就是服务注册,比如一个集群服务器,需要知道哪些服务器在线,哪些服务器不在线。   ZK有一个功能,就是创建临时节点,当机器启动应用的时候就会连接到一个ZK节点,然后创建一个临时节点,那么通过获取监听该路径,并且获取该路径下的节点数量就知道有哪些服务...

  • 前台到后台java时data日期类型的转化 在实体类中用@DataTimeFormat,这样设置即使传过来是空的字符串也是可以转的,要和前面传过来的格式一致,如 @XmlElement(name="BeginDate") @DateTimeFormat(pattern="yyyy-MM-dd") private Date begin...