受け入れHTTPS接続の自己署名証明書
-
19-09-2019 - |
質問
ようにしていくHTTPS接続の使用 HttpClient
libが、問題は、証明書のいない署名した認定証明書発行局(CA)のように ベリサイン,"ハイパー特許※")の独占的, 等 記載のセットにAndroid信頼できる証明書でも、"今日の javax.net.ssl.SSLException: Not trusted server certificate
.
私は見たソリューションまで全ての証明書を受け入れもしたい場合はどうすればよい、ユーザー
用していただきたいと思いダイアログと同様のブラウザのユーザーを決め続けます。好ましくはお使いのと同じcertificatestoreとしてのジーンズのブランド、、、。そのアイデア?
解決
最初にやるべきことなの設定のレベルを検証した。どのレベルにするのではなく:
- ALLOW_ALL_HOSTNAME_VERIFIER
- BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
- STRICT_HOSTNAME_VERIFIER
この方法setHostnameVerifier()は老朽化のための新しい図書館、apacheバージョンAndroid SDKは正常です。なし ALLOW_ALL_HOSTNAME_VERIFIER
設定する方法に工場 SSLSocketFactory.setHostnameVerifier()
.
次に、必要なセット工場のプロトコル*https.このためには、にしなければな SchemeRegistry.register()
方法。
それを作成する必要があります DefaultHttpClient
と SingleClientConnManager
.また、以下のコードをするのか、デフォルトもご利用フラグ(ALLOW_ALL_HOSTNAME_VERIFIER
法によって HttpsURLConnection.setDefaultHostnameVerifier()
以下のコードの作品が私にとって:
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);
他のヒント
以下のメインステップに達するのに必要な担保からの接続を認証局しているとみなされないとして信頼されるandroidプラットフォーム.
ご要望により多くのユーザーか鏡の最も重要なパーツから ブログ記事 こちら:
- むすべての必要な証明書のルートで、任意の中間CAの)
- をキーストアのkeytoolの BouncyCastle プロバイダとインポートしcerts
- 負荷のキーストアおandroidアプリに使ってみては如何でしょうか確保しながらおくつろぎをお薦めいたしますの Apache HttpClient 代わりに標準の
java.net.ssl.HttpsURLConnection
(、よりわかりやすく、よりperformant)
鷲掴みにcerts
お取得した全ての証明書を構築できるチェーンからの評価項目で証明書を一括して定期的に行うこととなり、ルートCA.これは、(存在する場合)中間CA certsのルートCAのcert.だけを取得する必要があるの評価項目です。
の作成、キーストア
ダウンロード BouncyCastleプロバイダ ダウンロードしましょう既知の場所です。を行うものであることを呼び出すことができ、keytoolコマンド(通常の地下にあbinフォルダおよびJREの設置)。
現在の輸入を得られたcertsな輸入の評価項目cert)BouncyCastle形式のkeystore.
かれいと思うの輸入の証明書が重要になります。これは、輸入の最下部中間CA証明書が最初で、そのすべてのルートCAの証明書。
以下のコマンドの新しいキーストアが存在しない)のパスワード 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
なる場合には証明書に輸入された正しくはキーストア
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
出力のチェーン
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
今コピーすることができ、キーストアを原料として、これを資源としてのandroidアプリの下で res/raw/
軒のキーストアにアプリ
初の全てをカスタム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);
}
}
}
また当社ではカスタムHttpClient、今まで使用でセキュアに接続します。例えばまで取得し、残ります。
// 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();
それ;)
とした場合のハードウェア、ソフトウェア自己署名証明書サーバではないが、デバイスで利用できます以下のクラスローでパッケージを採用していクライアント側でAndroid:
場所の証明書 *.crt
ファイル /res/raw
こから入手可能となってい R.raw.*
以下のご利用クラスを得る 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;
}
}
キーポイント:
Certificate
物から発生する.crt
ファイルです。- デフォルト
KeyStore
を作成します。 keyStore.setCertificateEntry("ca", cert)
する追加証明書をキーストアの下でのエイリアス"ca".き具体的な方法を以下に示する追加証明書(中間CAます。- 主要な目的は、生成する
SSLSocketFactory
与するものである"と認められるHTTPClient
またはHttpsURLConnection
. SSLSocketFactory
設定できさらに、例えばスキップホスト名の検証等
詳細情報は: http://developer.android.com/training/articles/security-ssl.html
の回答質問の仕事でした。その後の調査に必要な情報"のAndroid開発者":https://developer.android.com/training/articles/security-ssl.html#SelfSigned
創造空の実装の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();
くださいここを空に実施TustManager、あくまで目安ですが、例えば、これを生産的な環境が厳しい安全保障の脅威!
私は、HTTPSを使用して、私のRESTfulなサービスに私のAndroidのアプリケーションを接続しようとする欲求不満でした。また、私は完全に確認する証明書を無効にすることが示唆すべての答えについて少しイライラしました。その場合、いただきました!HTTPS?
のポイントの後しばらくの間、トピックについてググ、私は最終的に<のhref = "http://littlesvr.ca/grumble/2014/07/21/android-programming-connect-to-an-https-server-ました自己署名証明書/」のrel = 『noreferrer』>外部のjarファイルが必要とされていないこののソリューションだけのAndroidのAPI。 7月にそれを掲載アンドリュー・スミス、2014年
に感謝 /**
* 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;
}
}
これは、私のモックアップアプリケーションのための素晴らしい働いています。
Google用を推奨しての AndroidバレーのためのHTTP/HTTPS接続の場合, その HttpClient
で推奨されていません。かの選択肢).
とともに、 な劇SSL証明書のない!!!).
を劇SSL証明書は完全に対する目的でSSLを推進 安全保障.あの感覚は、暗号化(SSL)を用いて,一歩間違えれば爆のすべてのSSL証明書が付属します。うなSSLを利用や、よりよい解決方法は、作成したい TrustManager
自アプリをAndroidバレーのためのHTTP/HTTPS接続します。
この 概要 作成した基本LoginApp、HTTPS接続を使用し、自己署名証明書をサーバ側では、受け入れのアプリです。
この他にも 概要 この場合、作成自己署名SSLの証明書の設定はサーバのものを使用証明書アプリです。 重要: 必ずコピーします。crtファイルを生成したスクリプトにより、上記の"原"ディレクトリからAndroidプロジェクト.
これがその方法を追加できる追加証明書をキーストアのこの問題を回避するためには: 信頼すべての証明書を使用HttpClient HTTPS通信
んのユーザーのようにお願いですが、ユーザーが行われ、"信頼できないサーバ証明書の"エラーになります。
そのためにSSL証明書の作成
開Firefoxかしている可能性もありますとのクロムができますが、私にとってはFF)
だ開発サイトとの自己署名SSL証明書。
をクリックし、証明書にサイト名)
"をクリックします。
"をクリックしュ証明書"
クリックし"詳細"
をクリックし、"エクスポート"
を選択"X.509証明書whithチェーン(PEM)"を選択し、フォルダとフォルダの名前を保存し、"保存"ボタンをクリックします"
行コマンドラインにあるディレクトリにダウンロードのpemファイル実行"openssl x509-お知らせPEM-outform DMす。pemています。crt"
コピーします。crtファイルのルート/sdカードのフォルダ内のAndroidデバイス 内Androidデバイス設定>セキュリティ>インストールから保管します。
この検出証明書、または追加のデバイス 閲覧には開発サイトです。
初めてでを確認させていただき、セキュリティ例外.ることはありません。
証明書を企業に提供している他のブラウザーがインストールされAndroid端末(ブラウザ、クロム、データの再活用やホームページイルカ...)
覚えていればお使いいただける静的ファイルから別のドメイン(また、お客様のご期待に応えるたページ速度の影響)を追加する必要がありまを証する領域です。
私は小さなライブラリを書いた SSL-utilsの - アンドロイドAndroid上で特定の証明書を信頼するようにする。
あなたは、単に資産ディレクトリからファイル名を与えることによって、すべての証明書を読み込むことができます。
使用方法:
OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());
これらの修正プログラムのいずれもSDK 16をターゲットに私の開発プラットフォーム、4.1.2のリリースのために働いていないので、私は回避策を見つけます。
「 http://www.example.comを使用して、サーバー上のマイアプリにデータを格納します/page.php?data=somedata
の "最近page.phpは https://www.secure-example.com」に移動しました/page.php のjavax.net.ssl.SSLException」と私が得続ける 『:』信頼されていないサーバ証明書を
の代わりに、このガイドで始まるhref="https://stackoverflow.com/questions/5576619/php-redirect-with-post-data">つだけのページのすべての証明書、 http://www.example.com/page」に掲載され、私自身page.phpを書いて私の問題を解決しました.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;
}
?>
たぶん、この意志役立つ...それは自己署名証明書を使用してJavaクライアント上で動作します(証明書の検査は行われません)。注意してください、それはまったく安全でないため、唯一の開発事例のためにそれを使用!!
方法ApacheのHttpClientを4.0 のでSSL証明書エラーを無視する
これは、Android上の作品はただのHttpClientライブラリーを追加することを願っています...幸運!!
これは、SNI(サーバー名識別)をサポートINA、ndroid 2.xの不足に起因する問題であり、私は、問題の良い背景を与えるだけでなく、任意のセキュリティホールを欠いての作業で効果的なソリューションを提供するだけでなく、次の質問、出くわしたまで、私は一週間のために、この問題に苦しんでいた。
'はピア証明書ありません'アンドロイド2.3ではなく、4 の中のエラー