此处将为大家介绍关于我需要Android中HttpClient的另一个选项来向PHP发送数据,因为它不再受支持的详细内容,此外,我们还将为您介绍关于AndroidHttpClient、androidh
此处将为大家介绍关于我需要Android中HttpClient的另一个选项来向PHP发送数据,因为它不再受支持的详细内容,此外,我们还将为您介绍关于Android HttpClient、android httpClient (https/http) 的优化构建方式二、android httpClient 支持 HTTPS 的 2 种处理方式、android httpClient 支持 HTTPS 的访问方式的有用信息。
本文目录一览:- 我需要Android中HttpClient的另一个选项来向PHP发送数据,因为它不再受支持
- Android HttpClient
- android httpClient (https/http) 的优化构建方式二
- android httpClient 支持 HTTPS 的 2 种处理方式
- android httpClient 支持 HTTPS 的访问方式
我需要Android中HttpClient的另一个选项来向PHP发送数据,因为它不再受支持
目前,我正在使用中HttpClient
,HttpPost
从中发送数据给我PHP server
,Android app
但是所有这些方法在API 22中已被弃用,而在API 23中已被删除,那么还有哪些替代选择呢?
我到处搜索,但没有找到任何东西。
Android HttpClient
Android4.0 之后对使用网络有特殊要求,已经无法再在主线程中访问网络了,必须使用多线程访问的模式,
android httpClient (https/http) 的优化构建方式二
由于时间原因,这里只构建所有请求 https 都能通过的请求 client
首先定义(重写)信任管理器
public class SSLTrustManager implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager ,HostnameVerifier{
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
@Override
public boolean verify(String urlHostName, SSLSession session) { //允许所有主机
return true;
}
}
然后封装
public static HttpURLConnection connect(String strUrl) throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new SSLTrustManager();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((HostnameVerifier) tm);
URL url = new URL(strUrl);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
return urlConn;
}
测试一下
public void unitest()
{
HttpURLConnection urlConn = connect(''https://github.com/'');
urlConn.setDoInput(true);
urlConn.setRequestMethod("GET");
urlConn.connect();
InputStream is = urlConn.getInputStream();
StringBuffer sb = new StringBuffer();
if(is!=null)
{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String s = null;
while ((s=br.readLine())!=null)
{
sb.append(s).append("\n");
}
}
System.out.println("Content:\n"+sb.toString());
}
try do it!
android httpClient 支持 HTTPS 的 2 种处理方式
问题:
项目中 Android https 或 http 请求地址重定向为 HTTPS 的地址,相信很多人都遇到了这个异常 (无终端认证):
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
解决过程:
1. 没遇到过的问题,搜索吧,少年
log 里出现这个异常,作者第一次遇到,不知道啥意思。看下字面意思,是 ssl 协议中没有终端认证。SSL?作者没用到 ssl 协议呀,只是通过 httpClient 请求一个重定向 https 的地址。
好吧,google 下,知道了个差不多情况的帖子,http://www.eoeandroid.com/thread-161747-1-1.html。恩恩,一个不错的帖子,给出了个解决方案。照着来试下。添加个继承 SSLSocketFactory 的
自定义类。并在初始化 httpclient 支持 https 时,注册进去。看下面代码:
public class HttpClientHelper {
private static HttpClient httpClient;
private HttpClientHelper() {
}
public static synchronized HttpClient getHttpClient() {
if (null == httpClient) {
// 初始化工作
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //允许所有主机的验证
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params,
HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
// 设置连接管理器的超时
ConnManagerParams.setTimeout(params, 10000);
// 设置连接超时
HttpConnectionParams.setConnectionTimeout(params, 10000);
// 设置socket超时
HttpConnectionParams.setSoTimeout(params, 10000);
// 设置http https支持
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schReg.register(new Scheme("https", sf, 443));
ClientConnectionManager conManager = new ThreadSafeClientConnManager(
params, schReg);
httpClient = new DefaultHttpClient(conManager, params);
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
return httpClient;
}
}
class SSLSocketFactoryEx extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryEx(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port,
autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
ok,run 下,狂乱的点到测试按钮,深吸口气,盯着 eclipse 中的 logat。咦?神奇的竟然没有报之前的 javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 的异常了。服务端的数据正常返回了。, 狂喜中...
2. 了解并分析问题
狂喜中,得分析这问题诶。不然老大来问,啥情况?楞半天不知道咋说(作者就经常这样,所以吸取教训。所以的弄懂出现的问题,学习 + 汇报工作)。
思来想去,就是作者请求的是一个重定向 https 的地址。好吧,那就学习下 https(之前被老大深深的教过,http 就是 request/response)。继续搜索吧,少年。下面总结下学习到的 https 知识。
2.1 https
HTTPS: 超文本安全传输协议,和 HTTP 相比,多了一个 SSL/TSL 的认证过程,端口为 443。(鄙视下之前说的)
作者没用到 ssl 协议呀,只是通过 httpClient 请求一个重定向 https 的地址
1.peer 终端发送一个 request,https 服务端把支持的加密算法等以证书的形式返回一个身份信息(包含 ca 颁发机构和加密公钥等)。
2. 获取证书之后,验证证书合法性。
3. 随机产生一个密钥,并以证书当中的公钥加密。
4.request https 服务端,把用公钥加密过的密钥传送给 https 服务端。
5.https 服务端用自己的密钥解密,获取随机值。
6. 之后双方传送数据都用此密钥加密后通信。
看下面一张网上的得来的 https 的时序图:
2.2 分析下出现问题的原因
好吧,大概的流程知道了。定位已经非常清楚了。在第 2 步验证证书时,无法验证。为啥无法验证呢?没有添加信任。详细参考下
http://www.cnblogs.com/P_Chou/archive/2010/12/27/https-ssl-certification.html 讲的非常清楚 https-ssl 的认证过程,膜拜下该作者
这样想来,上面提供的解决方案就是添加默认信任全部证书。以此来通过接下来的通信。
3. 解决问题
但是,这样问题是解决了。但是觉得还是不带靠谱(信任全部证书有点危险)。继续噼噼啪啪的网上搜索一番。又找到了一种解决方案,其过程大致这样的:
1. 浏览器访问 https 地址,保存提示的证书到本地,放到 android 项目中的 assets 目录。
2. 导入证书,代码如下。
3. 把证书添加为信任。
String requestHTTPSPage(String mUrl) {
InputStream ins = null;
String result = "";
try {
ins = context.getAssets().open("app_pay.cer"); //下载的证书放到项目中的assets目录中
CertificateFactory cerFactory = CertificateFactory
.getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(ins);
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", cer);
SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);
Scheme sch = new Scheme("https", socketFactory, 443);
HttpClient mHttpClient = new DefaultHttpClient();
mHttpClient.getConnectionManager().getSchemeRegistry()
.register(sch);
BufferedReader reader = null;
try {
Log.d(TAG, "executeGet is in,murl:" + mUrl);
HttpGet request = new HttpGet();
request.setURI(new URI(mUrl));
HttpResponse response = mHttpClient.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
request.abort();
return result;
}
reader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
Log.d(TAG, "mUrl=" + mUrl + "\nresult = " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
// TODO: handle exception
} finally {
try {
if (ins != null)
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
接着,验证下呗。吼吼,稀里糊涂的又可以了。感动的泪流满面。
最后总结:
2 种方法都解决了作者遇到的问题,这里记录下。以防下次遇到,希望能给遇到相同问题朋友有所参考帮助。
android httpClient 支持 HTTPS 的访问方式
项目中 Android https 请求地址遇到了这个异常 (无终端认证):
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
是 SSL 协议中没有终端认证。
没有遇到过的问题,于是无奈的去找度娘。。。。。。。
看了不少大神的博客后得到的解决方案如下:
/**
* Post请求连接Https服务
* @param serverURL 请求地址
* @param jsonStr 请求报文
* @return
* @throws Exception
*/
public static synchronized String doHttpsPost(String serverURL, String jsonStr)throws Exception {
// 参数
HttpParams httpParameters = new BasicHttpParams();
// 设置连接超时
HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
// 设置socket超时
HttpConnectionParams.setSoTimeout(httpParameters, 3000);
// 获取HttpClient对象 (认证)
HttpClient hc = initHttpClient(httpParameters);
HttpPost post = new HttpPost(serverURL);
// 发送数据类型
post.addHeader("Content-Type", "application/json;charset=utf-8");
// 接受数据类型
post.addHeader("Accept", "application/json");
// 请求报文
StringEntity entity = new StringEntity(jsonStr, "UTF-8");
post.setEntity(entity);
post.setParams(httpParameters);
HttpResponse response = null;
try {
response = hc.execute(post);
} catch (UnknownHostException e) {
throw new Exception("Unable to access " + e.getLocalizedMessage());
} catch (SocketException e) {
e.printStackTrace();
}
int sCode = response.getStatusLine().getStatusCode();
if (sCode == HttpStatus.SC_OK) {
return EntityUtils.toString(response.getEntity());
} else
throw new Exception("StatusCode is " + sCode);
}
private static HttpClient client = null;
/**
* 初始化HttpClient对象
* @param params
* @return
*/
public static synchronized HttpClient initHttpClient(HttpParams params) {
if(client == null){
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryImp(trustStore);
//允许所有主机的验证
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
// 设置http和https支持
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient(params);
}
}
return client;
}
public static class SSLSocketFactoryImp extends SSLSocketFactory {
final SSLContext sslContext = SSLContext.getInstance("TLS");
public SSLSocketFactoryImp(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,
String authType)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType)
throws java.security.cert.CertificateException {
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host,
port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
run 下,小手发抖的点到测试按钮,深吸口气,咦?没反应。。。马蛋的,工作线程忘记 start (),唉,再次 run 下,终于的有点反应了,神奇的竟然没有报之前的
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
的异常了。服务端的数据正常返回了。
分析问题:
HTTPS: 超文本安全传输协议,和 HTTP 相比,多了一个 SSL/TSL 的认证过程,端口为 443。
1.peer 终端发送一个 request,https 服务端把支持的加密算法等以证书的形式返回一个身份信息(包含 ca 颁发机构和加密公钥等)。
2. 获取证书之后,验证证书合法性。
3. 随机产生一个密钥,并以证书当中的公钥加密。
4.request https 服务端,把用公钥加密过的密钥传送给 https 服务端。
5.https 服务端用自己的密钥解密,获取随机值。
6. 之后双方传送数据都用此密钥加密后通信。
HTTPS 流程清楚后,问题也就明显了,验证证书时,无法验证。
上面提供的解决方案就是添加默认信任全部证书。以此来通过接下来的通信。
但是,这样问题是解决了。但是觉得还是不带靠谱(信任全部证书有点危险)。继续噼噼啪啪的网上搜索一番。又找到了一种解决方案,其过程大致这样的:
1. 浏览器访问 https 地址,保存提示的证书到本地,放到 android 项目中的 assets 目录。
2. 导入证书,代码如下。
3. 把证书添加为信任。
public static String requestHTTPSPage(Context context, String mUrl) {
InputStream ins = null;
String result = "";
try {
ins = context.getAssets().open("my.key"); // 下载的证书放到项目中的assets目录中
CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(ins);
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null, null);
keyStore.setCertificateEntry("trust", cer);
SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);
Scheme sch = new Scheme("https", socketFactory, 443);
HttpClient mHttpClient = new DefaultHttpClient();
mHttpClient.getConnectionManager().getSchemeRegistry().register(sch);
BufferedReader reader = null;
try {
HttpGet request = new HttpGet();
request.setURI(new URI(mUrl));
HttpResponse response = mHttpClient.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
request.abort();
return result;
}
reader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (ins != null)
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
关于我需要Android中HttpClient的另一个选项来向PHP发送数据,因为它不再受支持的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Android HttpClient、android httpClient (https/http) 的优化构建方式二、android httpClient 支持 HTTPS 的 2 种处理方式、android httpClient 支持 HTTPS 的访问方式的相关信息,请在本站寻找。
本文标签: