Android 接受带有自签名证书的 HTTPS 连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2012497/
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
accepting HTTPS connections with self-signed certificates
提问by Morten
I'm trying to make HTTPS connections, using HttpClientlib, but the problem is that, since the certificate isn't signed by a recognized Certificate Authority (CA) like Verisign,GlobalSIgn, etc., listed on the set of Android Trusted Certificates, I keep getting javax.net.ssl.SSLException: Not trusted server certificate.
我正在尝试使用HttpClientlib建立 HTTPS 连接,但问题是,由于证书不是由公认的证书颁发机构 (CA) 签署的,如Verisign、GlobalSIgn等,列在 Android 受信任证书集上,我不断得到javax.net.ssl.SSLException: Not trusted server certificate。
I've seen solutions where you simply accept all certificates, but what if I want to ask the user?
我已经看到您只接受所有证书的解决方案,但是如果我想问用户怎么办?
I want to get a dialog similar to that of the browser, letting the user decide to continue or not. Preferably I'd like to use the same certificatestore as the browser. Any ideas?
我想得到一个类似于浏览器的对话框,让用户决定是否继续。最好我想使用与浏览器相同的证书库。有任何想法吗?
回答by Nikolay Moskvin
The first thing you need to do is to set the level of verification. Such levels is not so much:
您需要做的第一件事是设置验证级别。这样的水平并没有那么多:
- ALLOW_ALL_HOSTNAME_VERIFIER
- BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
- STRICT_HOSTNAME_VERIFIER
- ALLOW_ALL_HOSTNAME_VERIFIER
- BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
- STRICT_HOSTNAME_VERIFIER
Although the method setHostnameVerifier() is obsolete for new library apache, but for version in Android SDK is normal.
And so we take ALLOW_ALL_HOSTNAME_VERIFIERand set it in the method factory SSLSocketFactory.setHostnameVerifier().
尽管 setHostnameVerifier() 方法对于新库 apache 已过时,但对于 Android SDK 中的版本是正常的。所以我们ALLOW_ALL_HOSTNAME_VERIFIER在方法工厂中获取并设置它SSLSocketFactory.setHostnameVerifier()。
Next, You need set our factory for the protocol to https. To do this, simply call the SchemeRegistry.register()method.
接下来,您需要将我们的协议工厂设置为 https。为此,只需调用该SchemeRegistry.register()方法。
Then you need to create a DefaultHttpClientwith SingleClientConnManager.
Also in the code below you can see that on default will also use our flag (ALLOW_ALL_HOSTNAME_VERIFIER) by the method HttpsURLConnection.setDefaultHostnameVerifier()
然后你需要创建一个DefaultHttpClientwith SingleClientConnManager. 同样在下面的代码中,您可以看到默认情况下也将ALLOW_ALL_HOSTNAME_VERIFIER通过方法使用我们的标志()HttpsURLConnection.setDefaultHostnameVerifier()
Below code works for me:
下面的代码对我有用:
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
// Example send http request
final String url = "https://encrypted.google.com/";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
回答by saxos
The following main steps are required to achieve a secured connection from Certification Authorities which are not considered as trusted by the android platform.
需要以下主要步骤来实现与 android 平台不信任的证书颁发机构的安全连接。
As requested by many users, I've mirrored the most important parts from my blog articlehere:
应许多用户的要求,我已将我博客文章中最重要的部分复制到此处:
- Grab all required certificates (root and any intermediate CA's)
- Create a keystore with keytool and the BouncyCastleprovider and import the certs
- Load the keystore in your android app and use it for the secured connections (I recommend to use the Apache HttpClientinstead of the standard
java.net.ssl.HttpsURLConnection(easier to understand, more performant)
- 获取所有必需的证书(根证书和任何中间 CA)
- 使用 keytool 和BouncyCastle提供程序创建密钥库并导入证书
- 在您的 android 应用程序中加载密钥库并将其用于安全连接(我建议使用Apache HttpClient而不是标准
java.net.ssl.HttpsURLConnection(更容易理解,性能更高)
Grab the certs
获取证书
You have to obtain all certificates that build a chain from the endpoint certificate the whole way up to the Root CA. This means, any (if present) Intermediate CA certs and also the Root CA cert. You don't need to obtain the endpoint certificate.
您必须获取从端点证书一直到根 CA 构建链的所有证书。这意味着,任何(如果存在)中间 CA 证书以及根 CA 证书。您不需要获取端点证书。
Create the keystore
创建密钥库
Download the BouncyCastle Providerand store it to a known location. Also ensure that you can invoke the keytool command (usually located under the bin folder of your JRE installation).
下载BouncyCastle Provider并将其存储到已知位置。还要确保您可以调用 keytool 命令(通常位于 JRE 安装的 bin 文件夹下)。
Now import the obtained certs (don't import the endpoint cert) into a BouncyCastle formatted keystore.
现在将获得的证书(不要导入端点证书)导入 BouncyCastle 格式的密钥库。
I didn't tested it, but I think the order of importing the certificates is important. This means, import the lowermost Intermediate CA certificate first and then all the way up to the Root CA certificate.
我没有测试过,但我认为导入证书的顺序很重要。这意味着,首先导入最下面的中间 CA 证书,然后一直导入根 CA 证书。
With the following command a new keystore (if not already present) with the password mysecretwill be created and the Intermediate CA certificate will be imported. I also defined the BouncyCastle provider, where it can be found on my file system and the keystore format. Execute this command for each certificate in the chain.
使用以下命令将创建密码为mysecret的新密钥库(如果尚未存在)并导入中间 CA 证书。我还定义了 BouncyCastle 提供程序,它可以在我的文件系统和密钥库格式中找到。对链中的每个证书执行此命令。
keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
Verify if the certificates were imported correctly into the keystore:
验证证书是否已正确导入密钥库:
keytool -list -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
Should output the whole chain:
应该输出整个链:
RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43
Now you can copy the keystore as a raw resource in your android app under res/raw/
现在您可以将密钥库复制为您的 android 应用程序中的原始资源 res/raw/
Use the keystore in your app
在您的应用程序中使用密钥库
First of all we have to create a custom Apache HttpClient that uses our keystore for HTTPS connections:
首先,我们必须创建一个自定义的 Apache HttpClient,它使用我们的密钥库进行 HTTPS 连接:
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
We have created our custom HttpClient, now we can just use it for secure connections. For example when we make a GET call to a REST resource.
我们已经创建了我们的自定义 HttpClient,现在我们可以将它用于安全连接。例如,当我们对 REST 资源进行 GET 调用时。
// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
That's it ;)
就是这样 ;)
回答by S.D.
If you have a custom/self-signed certificate on server that is not there on device, you can use the below class to load it and use it on client side in Android:
如果您在设备上没有服务器上的自定义/自签名证书,您可以使用以下类加载它并在 Android 的客户端使用它:
Place the certificate *.crtfile in /res/rawso that it is available from R.raw.*
将证书*.crt文件放入,/res/raw以便它可以从R.raw.*
Use below class to obtain an HTTPClientor HttpsURLConnectionwhich will have a socket factory using that certificate :
使用下面的类来获取一个HTTPClient或HttpsURLConnection将使用该证书的套接字工厂:
package com.example.customssl;
import android.content.Context;
import org.apache.http.client.HttpClient;
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.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
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.HttpParams;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
public class CustomCAHttpsProvider {
/**
* Creates a {@link org.apache.http.client.HttpClient} which is configured to work with a custom authority
* certificate.
*
* @param context Application Context
* @param certRawResId R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
* @param allowAllHosts If true then client will not check server against host names of certificate.
* @return Http Client.
* @throws Exception If there is an error initializing the client.
*/
public static HttpClient getHttpClient(Context context, int certRawResId, boolean allowAllHosts) throws Exception {
// build key store with ca certificate
KeyStore keyStore = buildKeyStore(context, certRawResId);
// init ssl socket factory with key store
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(keyStore);
// skip hostname security check if specified
if (allowAllHosts) {
sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
}
// basic http params for client
HttpParams params = new BasicHttpParams();
// normal scheme registry with our ssl socket factory for "https"
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
// create connection manager
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
// create http client
return new DefaultHttpClient(cm, params);
}
/**
* Creates a {@link javax.net.ssl.HttpsURLConnection} which is configured to work with a custom authority
* certificate.
*
* @param urlString remote url string.
* @param context Application Context
* @param certRawResId R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
* @param allowAllHosts If true then client will not check server against host names of certificate.
* @return Http url connection.
* @throws Exception If there is an error initializing the connection.
*/
public static HttpsURLConnection getHttpsUrlConnection(String urlString, Context context, int certRawResId,
boolean allowAllHosts) throws Exception {
// build key store with ca certificate
KeyStore keyStore = buildKeyStore(context, certRawResId);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
// Create a connection from url
URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
// skip hostname security check if specified
if (allowAllHosts) {
urlConnection.setHostnameVerifier(new AllowAllHostnameVerifier());
}
return urlConnection;
}
private static KeyStore buildKeyStore(Context context, int certRawResId) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
// init a default key store
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
// read and add certificate authority
Certificate cert = readCert(context, certRawResId);
keyStore.setCertificateEntry("ca", cert);
return keyStore;
}
private static Certificate readCert(Context context, int certResourceId) throws CertificateException, IOException {
// read certificate resource
InputStream caInput = context.getResources().openRawResource(certResourceId);
Certificate ca;
try {
// generate a certificate
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ca = cf.generateCertificate(caInput);
} finally {
caInput.close();
}
return ca;
}
}
Key points:
关键点:
Certificateobjects are generated from.crtfiles.- A default
KeyStoreis created. keyStore.setCertificateEntry("ca", cert)is adding certificate to key store under alias "ca". You modify the code to add more certificates (intermediate CA etc).- Main objective is to generate a
SSLSocketFactorywhich can then be used byHTTPClientorHttpsURLConnection. SSLSocketFactorycan be configured further, for example to skip host name verification etc.
Certificate对象是从.crt文件生成的。KeyStore已创建默认值。keyStore.setCertificateEntry("ca", cert)正在将证书添加到别名“ca”下的密钥库。您修改代码以添加更多证书(中间 CA 等)。- 主要目标是生成一个
SSLSocketFactory可供HTTPClient或使用的HttpsURLConnection。 SSLSocketFactory可以进一步配置,例如跳过主机名验证等。
More information at : http://developer.android.com/training/articles/security-ssl.html
更多信息:http: //developer.android.com/training/articles/security-ssl.html
回答by Markus Lenger
The top answer didn′t work for me. After some investigation I found the required information on "Android Developer": https://developer.android.com/training/articles/security-ssl.html#SelfSigned
最佳答案对我不起作用。经过一番调查,我在“Android Developer”上找到了所需的信息:https: //developer.android.com/training/articles/security-ssl.html#SelfSigned
Creating an empty implementation of X509TrustManager did the trick:
创建一个空的 X509TrustManager 实现可以解决问题:
private static class MyTrustManager implements X509TrustManager
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
...
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try
{
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
TrustManager[] tmlist = {new MyTrustManager()};
context.init(null, tmlist, null);
conn.setSSLSocketFactory(context.getSocketFactory());
}
catch (NoSuchAlgorithmException e)
{
throw new IOException(e);
} catch (KeyManagementException e)
{
throw new IOException(e);
}
conn.setRequestMethod("GET");
int rcode = conn.getResponseCode();
Please be aware that this empty implementation of TustManager is just an example and using it in a productive environment would cause a severe security threat!
请注意,这个 TustManager 的空实现只是一个例子,在生产环境中使用它会导致严重的安全威胁!
回答by Gonzalo Fernández
I was frustrated trying to connect my Android App to my RESTful service using https. Also I was a bit annoyed about all the answers that suggested to disable certificate checking altogether. If you do so, whats the point of https?
尝试使用 https 将我的 Android 应用程序连接到我的 RESTful 服务时,我感到很沮丧。此外,我对所有建议完全禁用证书检查的答案感到有些恼火。如果你这样做了,https 的意义何在?
After googled about the topic for a while, I finally found thissolution where external jars are not needed, just Android APIs. Thanks to Andrew Smith, who posted it on July, 2014
在搜索了一段时间后,我终于找到了这个不需要外部 jars 的解决方案,只需要 Android API。感谢 Andrew Smith,他于 2014 年 7 月发布
/**
* Set up a connection to myservice.domain using HTTPS. An entire function
* is needed to do this because myservice.domain has a self-signed certificate.
*
* The caller of the function would do something like:
* HttpsURLConnection urlConnection = setUpHttpsConnection("https://littlesvr.ca");
* InputStream in = urlConnection.getInputStream();
* And read from that "in" as usual in Java
*
* Based on code from:
* https://developer.android.com/training/articles/security-ssl.html#SelfSigned
*/
public static HttpsURLConnection setUpHttpsConnection(String urlString)
{
try
{
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// My CRT file that I put in the assets folder
// I got this file by following these steps:
// * Go to https://littlesvr.ca using Firefox
// * Click the padlock/More/Security/View Certificate/Details/Export
// * Saved the file as littlesvr.crt (type X.509 Certificate (PEM))
// The MainActivity.context is declared as:
// public static Context context;
// And initialized in MainActivity.onCreate() as:
// MainActivity.context = getApplicationContext();
InputStream caInput = new BufferedInputStream(MainActivity.context.getAssets().open("littlesvr.crt"));
Certificate ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
return urlConnection;
}
catch (Exception ex)
{
Log.e(TAG, "Failed to establish SSL connection to server: " + ex.toString());
return null;
}
}
It worked nice for my mockup App.
它适用于我的样机应用程序。
回答by ivanleoncz
Google recommends the usage of Android Volley for HTTP/HTTPS connections, since that HttpClientis deprecated. So, you know the right choice :).
Google 建议将Android Volley 用于 HTTP/HTTPS 连接,因为它HttpClient已被弃用。所以,你知道正确的选择:)。
And also, NEVER NUKE SSL Certificates (NEVER!!!).
而且,永远不要使用 NUKE SSL 证书(永远不要!!!)。
To nuke SSL Certificates, is totally against the purpose of SSL, which is promoting security. There's no sense of using SSL, if you're planning to bomb all SSL certificates that comes. A better solution would be, not using SSL, or a better solution, would be creating a custom TrustManageron your App + using Android Volley for HTTP/HTTPS connections.
核销SSL证书,完全违背了SSL促进安全的目的。如果您打算轰炸所有的 SSL 证书,那么使用 SSL 是没有意义的。更好的解决方案是不使用 SSL,或者更好的解决方案是TrustManager在您的应用程序上创建自定义+ 使用 Android Volley 进行 HTTP/HTTPS 连接。
Here's a Gistwhich I created, with a basic LoginApp, performing HTTPS connections, using a Self-Signed Certificate on the server-side, accepted on the App.
这是我创建的Gist,使用基本的 LoginApp,执行 HTTPS 连接,在服务器端使用自签名证书,在应用程序上接受。
Here's also another Gistthat may help, for creating Self-Signed SSL Certificates for setting up on your Server and also using the certificate on your App. Very important:you must copy the .crt file which was generated by the script above, to the "raw" directory from your Android project.
这里还有另一个可能有帮助的Gist,用于创建自签名 SSL 证书以在您的服务器上进行设置以及在您的应用程序上使用该证书。非常重要:您必须将上述脚本生成的 .crt 文件复制到 Android 项目的“raw”目录中。
回答by emmby
Here's how you can add additional certificates to your KeyStore to avoid this problem: Trusting all certificates using HttpClient over HTTPS
以下是向 KeyStore 添加其他证书以避免此问题的方法:通过 HTTPS 使用 HttpClient 信任所有证书
It won't prompt the user like you ask, but it will make it less likely that the user will run into a "Not trusted server certificate" error.
它不会像您询问的那样提示用户,但它会降低用户遇到“不受信任的服务器证书”错误的可能性。
回答by klimat
I wrote small library ssl-utils-androidto trust particular certificate on Android.
我编写了小型库ssl-utils-android来信任Android上的特定证书。
You can simply load any certificate by giving the filename from assets directory.
您可以通过提供资产目录中的文件名来简单地加载任何证书。
Usage:
用法:
OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());
回答by Mani kandan
Simplest way for create SSL certificate
创建 SSL 证书的最简单方法
Open Firefox (I suppose it's also possible with Chrome, but it's easier for me with FF)
打开 Firefox(我想 Chrome 也可以,但 FF 对我来说更容易)
Visit your development site with a self-signed SSL certificate.
使用自签名 SSL 证书访问您的开发站点。
Click on the certificate (next to the site name)
单击证书(站点名称旁边)
Click on "More information"
点击“更多信息”
Click on "View certificate"
点击“查看证书”
Click on "Details"
点击“详情”
Click on "Export..."
点击“导出...”
Choose "X.509 Certificate whith chain (PEM)", select the folder and name to save it and click "Save"
选择“X.509 Certificate whith chain (PEM)”,选择要保存的文件夹和名称,然后单击“Save”
Go to command line, to the directory where you downloaded the pem file and execute "openssl x509 -inform PEM -outform DM -in .pem -out .crt"
转到命令行,到您下载 pem 文件的目录并执行“openssl x509 -inform PEM -outform DM -in .pem -out .crt”
Copy the .crt file to the root of the /sdcard folder inside your Android device Inside your Android device, Settings > Security > Install from storage.
将 .crt 文件复制到 Android 设备中 /sdcard 文件夹的根目录 在 Android 设备中,设置 > 安全 > 从存储安装。
It should detect the certificate and let you add it to the device Browse to your development site.
它应该检测证书并让您将其添加到设备浏览到您的开发站点。
The first time it should ask you to confirm the security exception. That's all.
第一次它应该要求您确认安全异常。就这样。
The certificate should work with any browser installed on your Android (Browser, Chrome, Opera, Dolphin...)
该证书适用于安装在 Android 上的任何浏览器(浏览器、Chrome、Opera、Dolphin...)
Remember that if you're serving your static files from a different domain (we all are page speed bitches) you also need to add the certificate for that domain.
请记住,如果您从不同的域(我们都是页面速度的婊子)提供静态文件,您还需要为该域添加证书。
回答by Rudy
None of these fixes worked for my develop platform targeting SDK 16, Release 4.1.2, so I found a workaround.
这些修复程序均不适用于我的面向 SDK 16 版本 4.1.2 的开发平台,因此我找到了一种解决方法。
My app stores data on server using "http://www.example.com/page.php?data=somedata"
我的应用程序使用“ http://www.example.com/page.php?data=somedata”在服务器上存储数据
Recently page.php was moved to "https://www.secure-example.com/page.php" and I keep getting "javax.net.ssl.SSLException: Not trusted server certificate".
最近 page.php 被移到“ https://www.secure-example.com/page.php”,我不断收到“javax.net.ssl.SSLException:不可信服务器证书”。
Instead of accepting all certificates for only a single page, starting with this guideI solved my problem writing my own page.php published on "http://www.example.com/page.php"
不是只接受一个页面的所有证书,从本指南开始,我解决了我在“ http://www.example.com/page.php”上编写自己的 page.php 的问题
<?php
caronte ("https://www.secure-example.com/page.php");
function caronte($url) {
// build curl request
$ch = curl_init();
foreach ($_POST as $a => $b) {
$post[htmlentities($a)]=htmlentities($b);
}
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($post));
// receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);
echo $server_output;
}
?>

