当前位置: 首页 > news >正文

android下使用https协议发请求

Android用Java开发,Java自带的http API有HttpURLConnection,Android系统又加上了Apache Httpclient,后来在22版本中HttpClient又被Google删除,所以我们不使用HttpClient来做网络请求了,这里只给出HttpURLConnection的方式。
原生的写法理解的没问题了,用第三方的写法也好弄.这里就不写了,有需要的同学联系我哈.我再补充

在讲android连接https的请求之前,其实应该先学习一下https的知识.https是另一种协议,跟http类似,也是发一次请求request建立一次链接connection带回一次信息response后再把链接断开.但又增加了新的内容:在发送请求前,要先把数据用SSL加密,而接收的信息也是服务端用SSL加密后的,需要先解密后才能正常使用.这样就确保了有人即便在网络上抓包,也无法知道到底传输的数据是什么,因为别人不知道你们的密钥是什么,比较安全.那有人就说了,客户端client怎么和服务端server商定一个只有双方知道的密钥呢?啊,能这样想就证明你已经对HTTPS的SSL加密有一些认识了.其实过程也简单.一般来说服务端server都是些网站,都是任何人都能访问的,但客户端又得得到一个只有自己和server知道而其它client不知道的密钥.其实这步也不难啊,只要client第一次访问server时,server象管理session一样给它一个唯一字符串,以后双方都用这个做密钥就好了嘛.
有了上一步的想法,好象HTTPS也很好理解,但是,人家HTTPS想的事情比这个要多.人家是这样想的:在做某些事情之前客户端client必须要先信任这个server不是仿冒的才跟它通信.也就是说有些事情是不能在钓鱼网站(仿冒的网站,就算你搞了DNS进攻让别人比如支付宝的域名指向你的服务器)上做的.这一步又是如何完成的呢?其实是客户端要先有服务端的一个签名文件(有时又叫指纹信息),也就是CA证书.终于说到服务端的CA证书了,好了,下面说对我们这次工作有用的东西,有关HTTPS和SSL的更多知识,大家可以去参考百度百科.
服务端用的CA证书,其实分为两种,一:花了钱向一个什么中心申请注册的,另一种是自己用工具生成一个而不去花钱注册.
第一种,就象百度这样的,我们可以直接象用HTTP一样是去这样的HTTPS的链接.因为这样的,你的connection会自动从注册中心下载证书并配置.大网站一般都这样.
第二种,就需要做处理.要做的处理写下面.

处理如下:
先跟服务端要一个证书文件,然后通过一大段代码设置到我们的HttpURLConnection中.其实就是让我们的client端信任此server.
((HttpsURLConnection) httpConn).setSSLSocketFactory(sslSocketFactory); //至于这个sslSocketFactory如何通过证书产生,哈哈.好大一段代码,参考完整的代码中的写法吧.

但好象还有没有证书的,配置就是让HttpURLConnection相信一个没证书的配置,然后添加信任的域名,其实可以理解为只要是域名符合我就相信啦!!靠,这client客户端这次可以被加了dns欺骗的钓鱼网站进攻了...
((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
((HttpsURLConnection) urlConnection).setHostnameVerifier(SSLContextUtil.hostnameVerifier);
看,多了一行吧.
经测试,没有证书只相信域名的这种做法,其实对那些需要证书且需要配置的网站,也能正常访问.看来CA证书还真是仅仅只做了让客户端如何相信他啊,也就是防钓鱼进攻.

简单说一下什么是钓鱼进攻:就是进攻者为了得到你的支付宝账号和密码,就做了一个跟支付宝网站看上去一样的网站,然后想办法引导你在他的网站上登录你的支付宝....这就是钓鱼....
所谓的DNS进攻,就是让别人的正常域名不再指向别人的网站,比如支付宝的域名本来是指向阿里的支付宝网站服务器的ip的,但被进攻成功后,就变成了指向进攻者的钓鱼网站的IP了..此时用户就算检查浏览器中地址栏的域名,也无法排除.
为了防止这样的事情发生,HTTPS协议规定了客户端在使用HTTPS之前,必须得先确认server服务端的身份,于是引入CA证书.为了方便客户端client去访问他,又引入一个什么注册中心.

下面是我的例子的所有代码

SSLContextUtil类,核心类.
package cn.wei.https;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import javax.net.ssl.TrustManagerFactory;

import android.content.Context;

public class SSLContextUtil {

private static SSLContext mSSLContext;
private static SSLContext mNoCarSSLContext;
private static HostnameVerifier hostnameVerifier = new HostnameVerifier() {br/>@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};

public static SSLContext getSSLContext() {
return mSSLContext;
}
public static SSLContext getNoCarSSLContext() {
return mNoCarSSLContext;
}
public static HostnameVerifier getHostnameVerifier(){
return hostnameVerifier;
}

public static void init(Context c) {
try {
mSSLContext = getSSLContext2(c);
} catch (Exception e) {
e.printStackTrace();
}
try {
mNoCarSSLContext = getNoCarSLLContext2();
} catch (Exception e) {
e.printStackTrace();
}
}
private static SSLContext getNoCarSLLContext2() {
// SSLContext sslContext = null;
//X509TrustManager a;//为了import这个类,就得这样写一下.
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {br/>@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {}

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {}

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }}, new SecureRandom());
} catch (Exception e) {
    e.printStackTrace();
}
return sslContext;

}

private static SSLContext getSSLContext2(Context c)
throws NoSuchAlgorithmException, IOException, CertificateException,
KeyStoreException, UnrecoverableKeyException,
KeyManagementException {
// 生成SSLContext对象
SSLContext sslContext = SSLContext.getInstance("TLS");
// 从assets中加载证书
InputStream inStream = c.getAssets().open("srca.cer");

// 证书工厂
CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(inStream);

// 密钥库
KeyStore kStore = KeyStore.getInstance("PKCS12");
kStore.load(null, null);
kStore.setCertificateEntry("trust", cer);// 加载证书到密钥库中

// 密钥管理器
KeyManagerFactory keyFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(kStore, null);// 加载密钥库到管理器

// 信任管理器
TrustManagerFactory tFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tFactory.init(kStore);// 加载密钥库到信任管理器

// 初始化
sslContext.init(keyFactory.getKeyManagers(),
tFactory.getTrustManagers(), new SecureRandom());
return sslContext;
}

}

Application类,辅助初始化的

public class MyApp extends Application {

@Override
public void onCreate() {
super.onCreate();
SSLContextUtil.init(this);
}
}

Activity类,使用的.

package cn.wei.https;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
TextView tv_html;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_html = (TextView) this.findViewById(R.id.tv_html);

AsyncTask<String, String, String> at = new AsyncTask<String, String, String>() {

@Override
protected String doInBackground(String... params) {
HttpURLConnection httpConn = null;
try {
URL url = new URL(params[0]);
URLConnection conn = url.openConnection();
httpConn = (HttpURLConnection) conn;
// 设置SSLSocketFoactory,这里有两种:1.需要安全证书 2.不需要安全证书;看官且往下看
if (httpConn instanceof HttpsURLConnection) { // 是Https请求
// 0.需要证书但不需要配的.什么也不用写.比如百度的https://www.baidu.com
// 1.需要安全证书且需要配的.
// SSLContext sslContext = SSLContextUtil.getSSLContext();
// if (sslContext != null) {
// SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// ((HttpsURLConnection) httpConn).setSSLSocketFactory(sslSocketFactory);
//
//
// }
// 2.不需要安全证书但需要配的:server端有但没给,client端配置直接相信此域名.
// SSLContext sslContext = SSLContextUtil.getNoCarSSLContext();
// if (sslContext != null) {
// SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// ((HttpsURLConnection) httpConn).setSSLSocketFactory(sslSocketFactory);
// ((HttpsURLConnection) httpConn).setHostnameVerifier(SSLContextUtil.getHostnameVerifier());
// }
}
httpConn.setRequestMethod("GET");
httpConn.setReadTimeout(16000);
httpConn.setConnectTimeout(16000);
int resCode = httpConn.getResponseCode();
if (resCode == 200) {
try (InputStream in = httpConn.getInputStream();
Reader r = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(r);) {
String line = null;
StringBuilder sb = new StringBuilder();
do {
line = br.readLine();
sb.append(line).append("\n");
} while (line != null);
return sb.toString();
} catch (IOException e) {
throw e;
}
} else {
return "网络请求错误.resCode:" + resCode;
}
} catch (MalformedURLException e) {
e.printStackTrace();
return "err:" + e.getMessage();
} catch (IOException e) {
e.printStackTrace();
return "err:" + e.getMessage();
} finally {
httpConn.disconnect();
}

}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tv_html.setText(result);

}

};
//at.execute("https://kyfw.12306.cn/otn/");//这个是有证书需要配的.
//at.execute("https://www.baidu.com");//百度是有证书但不用配的.
at.execute("https://www.alipay.com/");//有证书但不用配的.

}

}

.

转载于:https://blog.51cto.com/12093642/2049505

相关文章:

  • 【转】Android开发之线程池使用总结
  • 小知识三、USerDefault我换个姿势来实现
  • 581 Shortest Unsorted Continuous Subarray
  • v4l2 Camera详细设置【转】
  • iOS核心动画高级技术(十三) 高效绘图
  • ant任务调用和参数传递
  • 好玩的 RAC
  • Matlab2013a许可证过期问题,反复提示激活
  • 北京司法网拍首尝线下预展 海淀法院900万红木家具亮相京东秋拍
  • java进阶-常用数据结构以及算法思想
  • Nginx服务状态的监控
  • spring cloud Dalston.SR4 feign 实际开发中踩坑(二)
  • Kibana插件sentinl实现邮件报警
  • Vue slot分发内容
  • 前端面试总结(at, md)
  • [Vue CLI 3] 配置解析之 css.extract
  • Apache的80端口被占用以及访问时报错403
  • flask接收请求并推入栈
  • Hibernate最全面试题
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Meteor的表单提交:Form
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • 从setTimeout-setInterval看JS线程
  • 构建工具 - 收藏集 - 掘金
  • 机器学习学习笔记一
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​​​​​​​​​​​​​​Γ函数
  • ​520就是要宠粉,你的心头书我买单
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • (1)常见O(n^2)排序算法解析
  • (13):Silverlight 2 数据与通信之WebRequest
  • (Git) gitignore基础使用
  • (vue)页面文件上传获取:action地址
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (论文阅读11/100)Fast R-CNN
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (四)Android布局类型(线性布局LinearLayout)
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .net 验证控件和javaScript的冲突问题
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .NET基础篇——反射的奥妙
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • @hook扩展分析
  • [ C++ ] STL---stack与queue
  • [17]JAVAEE-HTTP协议