Java HTTPS连接安卓
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/995514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Https Connection Android
提问by Sam97305421562
I am doing a https post and I'm getting an exception of ssl exception Not trusted server certificate. If i do normal http it is working perfectly fine. Do I have to accept the server certificate somehow?
我正在做一个 https 帖子,我收到了 ssl 异常不受信任的服务器证书的异常。如果我做正常的 http,它工作得很好。我是否必须以某种方式接受服务器证书?
采纳答案by Nate
I'm making a guess, but if you want an actual handshake to occur, you have to let android know of your certificate. If you want to just accept no matter what, then use this pseudo-code to get what you need with the Apache HTTP Client:
我在猜测,但是如果您希望发生实际的握手,则必须让 android 知道您的证书。如果你无论如何都想接受,那么使用这个伪代码来获得你需要的 Apache HTTP 客户端:
SchemeRegistry schemeRegistry = new SchemeRegistry ();
schemeRegistry.register (new Scheme ("http",
PlainSocketFactory.getSocketFactory (), 80));
schemeRegistry.register (new Scheme ("https",
new CustomSSLSocketFactory (), 443));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager (
params, schemeRegistry);
return new DefaultHttpClient (cm, params);
CustomSSLSocketFactory:
自定义SSLSocketFactory:
public class CustomSSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
private SSLSocketFactory FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory ();
public CustomSSLSocketFactory ()
{
super(null);
try
{
SSLContext context = SSLContext.getInstance ("TLS");
TrustManager[] tm = new TrustManager[] { new FullX509TrustManager () };
context.init (null, tm, new SecureRandom ());
FACTORY = context.getSocketFactory ();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public Socket createSocket() throws IOException
{
return FACTORY.createSocket();
}
// TODO: add other methods like createSocket() and getDefaultCipherSuites().
// Hint: they all just make a call to member FACTORY
}
FullX509TrustManager is a class that implements javax.net.ssl.X509TrustManager, yet none of the methods actually perform any work, get a sample here.
FullX509TrustManager 是一个实现 javax.net.ssl.X509TrustManager 的类,但实际上没有一个方法执行任何工作,请在此处获取示例。
Good Luck!
祝你好运!
回答by Matti Lyra
I don't know about the Android specifics for ssl certificates, but it would make sense that Android won't accept a self signed ssl certificate off the bat. I found this post from android forums which seems to be addressing the same issue: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html
我不知道 ssl 证书的 Android 细节,但 Android 不会立即接受自签名 ssl 证书是有道理的。我从 android 论坛上找到了这篇文章,它似乎解决了同样的问题:http: //androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html
回答by Ulrich Scheller
This is what I am doing. It simply doesn't check the certificate anymore.
这就是我正在做的。它只是不再检查证书。
// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
and
和
HttpURLConnection http = null;
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setHostnameVerifier(DO_NOT_VERIFY);
http = https;
} else {
http = (HttpURLConnection) url.openConnection();
}
回答by bajohns
While trying to answer this question I found a better tutorial. With it you don't have to compromise the certificate check.
在尝试回答这个问题时,我找到了一个更好的教程。有了它,您不必妥协证书检查。
http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
*I did not write this but thanks to Bob Lee for the work
*这不是我写的,但感谢 Bob Lee 的工作
回答by saxos
You can also look at my blog article, very similar to crazybobs.
你也可以看看我的博客文章,和crazybob很像。
This solution also doesn't compromise certificate checking and explains how to add the trusted certs in your own keystore.
此解决方案也不会影响证书检查,并解释了如何在您自己的密钥库中添加受信任的证书。
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/
回答by Adrian Spinei
None of these worked for me (aggravated by the Thawte bugas well). Eventually I got it fixed with Self-signed SSL acceptance on Androidand Custom SSL handling stopped working on Android 2.2 FroYo
这些都不适合我(也因Thawte 错误而加剧)。最后,我把它固定在Android上的自签名SSL验收和自定义SSL处理不辍上的Android 2.2 Froyo
回答by alumat
This is a known problem with Android 2.x. I was struggling with this problem for a week until I came across the following question, which not only gives a good background of the problem but also provides a working and effective solution devoid of any security holes.
这是 Android 2.x 的一个已知问题。我在这个问题上挣扎了一个星期,直到我遇到了以下问题,这不仅提供了问题的良好背景,而且还提供了一个没有任何安全漏洞的有效解决方案。
回答by Syed Ghulam Akbar
For some reason the solution mentioned for httpClient above didn't worked for me. At the end I was able to make it work by correctly overriding the method when implementing the custom SSLSocketFactory class.
出于某种原因,上面为 httpClient 提到的解决方案对我不起作用。最后,我能够通过在实现自定义 SSLSocketFactory 类时正确覆盖该方法来使其工作。
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException
{
return sslFactory.createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslFactory.createSocket();
}
This is how it worked perfectly for me. You can see the full custom class and implementing on the following thread: http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/
这就是它对我来说完美的方式。您可以在以下线程中查看完整的自定义类并实现:http: //blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/
回答by Speise
Any of this answers didn't work for me so here is code which trust any certificates.
这些答案中的任何一个对我都不起作用,所以这里是信任任何证书的代码。
import java.io.IOException;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class HttpsClientBuilder {
public static DefaultHttpClient getBelieverHttpsClient() {
DefaultHttpClient client = null;
SchemeRegistry Current_Scheme = new SchemeRegistry();
Current_Scheme.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
try {
Current_Scheme.register(new Scheme("https", new Naive_SSLSocketFactory(), 8443));
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpParams Current_Params = new BasicHttpParams();
int timeoutConnection = 8000;
HttpConnectionParams.setConnectionTimeout(Current_Params, timeoutConnection);
int timeoutSocket = 10000;
HttpConnectionParams.setSoTimeout(Current_Params, timeoutSocket);
ThreadSafeClientConnManager Current_Manager = new ThreadSafeClientConnManager(Current_Params, Current_Scheme);
client = new DefaultHttpClient(Current_Manager, Current_Params);
//HttpPost httpPost = new HttpPost(url);
//client.execute(httpPost);
return client;
}
public static class Naive_SSLSocketFactory extends SSLSocketFactory
{
protected SSLContext Cur_SSL_Context = SSLContext.getInstance("TLS");
public Naive_SSLSocketFactory ()
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException
{
super(null, null, null, null, null, (X509HostnameVerifier)null);
Cur_SSL_Context.init(null, new TrustManager[] { new X509_Trust_Manager() }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException
{
return Cur_SSL_Context.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException
{
return Cur_SSL_Context.getSocketFactory().createSocket();
}
}
private static class X509_Trust_Manager implements X509TrustManager
{
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
}
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
};
}
回答by Juan Sánchez
If you are using a StartSSL or Thawte certificate, it will fail for Froyo and older versions. You can use a newer version's CAcert repositoryinstead of trusting every certificate.
如果您使用的是 StartSSL 或 Thawte 证书,则 Froyo 和旧版本将失败。您可以使用较新版本的 CAcert 存储库,而不是信任每个证书。