0

これは、ブラウザがhttpsサイトに接続するときにssl証明書を処理する方法です。

  1. ブラウザにhttps://myDemoSite.comと入力すると、まずブラウザがmyDemoSite.comからの証明書を要求し(httpsが原因)、次にmyDemoSiteがその証明書をブラウザに送信します。

  2. ブラウザがその証明書を受信すると、ブラウザはそれが検証された機関によって署名されているかどうかを確認します。

  3. 2番目のステップで「はい」の場合、3番目のステップとして、証明書の問題にブラウザのユーザーが入力したのと同じURLがあるかどうかを確認します。

今、私はJavaプログラム(HttpsConnectProg1)を介してhttpsサイトに接続しています。私の質問は、programmei.e HttpsConnectProg1がhttpsサイト接続で発行されたこの証明書をどのように処理するかです(ただし、このhttpsサイトによって発行された証明書は確認済みです。

認定証明書を発行するhttpsサイトに接続する小さなプログラムを試しました。sslhandshakeエラーや証明書エラー(この証明書を$ JAVA_HOME \ jre \ lib \ securityフォルダーに追加しなかったため)などのエラーが予想されましたが、驚いたことにエラーは発生しませんでした。

ここで重要な質問は、HttpsConnectProg1がブラウザによって実行されたステップ3をチェックするかどうかです。これは、非常に重要なステップですか?ここでの参考のためにそれは

 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.Properties;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLSession;


 public class ConnectToDemoSite {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub

    String urlStr = "https://www.myDemoSite.com/demo1/";
    URL url;
    Properties reply = new Properties();
    try {
        url = new URL(urlStr);
        URLConnection conn = url.openConnection();
        if(conn instanceof HttpsURLConnection)
        {
        HttpsURLConnection conn1 = (HttpsURLConnection)url.openConnection();
            conn1.setHostnameVerifier(new HostnameVerifier()  
            {        
                public boolean verify(String hostname, SSLSession session)  
                {  
                    return true;  
                }  
            });  

        reply.load(conn1.getInputStream());
        }
        else 
        {
             conn = url.openConnection();
             reply.load(conn.getInputStream());
        }
    } catch (MalformedURLException e) {
       e.printStackTrace();
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("reply is"+reply);



 }

}
4

2 に答える 2

2

https://Javaを使用してURIに接続する場合、 Java Secure Socket Extension(JSSE)を使用します(SSL / TLSのカスタム実装を本当に使用したい場合を除きますが、それは非常にまれです)。

信頼管理を微調整する方法は複数ありますが(主にカスタムを使用TrustManager)、それ以外の場合は、特定の数の適切な設定を使用します。

この例では、証明書はデフォルトを使用して検証されSSLContext、それ自体がデフォルトで構成され、X509TrustManagerトラストアンカーが読み取られます( JSSE参照ガイドの「カスタマイズcacerts」セクションの表を参照)。

デフォルトでは、JREにはいくつかの事前に信頼されたCA証明書(ほとんどのブラウザーやOSなど)が付属していcacertsます。これは通常、ブラウザーで見られるものと似ています。これがJSSERef。ガイドはそれについて言います:

重要な注意:JDKには、/ lib / security/cacertsファイルに限られた数の信頼されたルート証明書が含まれています。keytoolに記載されているように、このファイルをトラストストアとして使用する場合は、このファイルに含まれる証明書を維持(つまり、追加/削除)するのはユーザーの責任です。

連絡するサーバーの証明書構成によっては、ルート証明書を追加する必要がある場合があります。適切なベンダーから必要な特定のルート証明書を取得します。

証明書が信頼できる場合は、ホスト名が目的のURLに対して有効かどうかを確認します。(チェックされるのは完全なURLではなく、ホスト名のみであることに注意してください。)

これらのルールは、RFC 2818(HTTPS仕様)のセクション3.1で定義されています。(Java7はまだRFC6125を実装していませんが、特にHTTPSの場合、ルールは非常に似ています。)編集:接続が確立されると、URLConnection(および基になるSSLSession)はサーバーのホスト名で設定されます。つまり、RFC 2818のルールに従って、証明書のサブジェクト代替名(SAN)拡張機能のDNSエントリのサーバー証明書を調べて、接続に設定されたホスト名と一致するかどうかを確認するか、その名前を探します。 SAN DNSエントリが存在しない場合は、証明書のサブジェクトDNの共通名(CN)にあります。

ホスト名の検証は通常、デフォルトのホスト名ベリファイアによって行われます。この例では、デフォルトのベリファイアを常にを返すベリファイアに置き換えていますtrue。したがって、この検証は実際には行われず、すべてが受け入れられます(これを行うことでセキュリティホールを導入します)。

さらに、Javaで行われるデフォルトのホスト名の検証は、多くのブラウザよりも厳密にRFC2818に準拠しています。特に、CNのIPアドレスは受け入れません。

(常にtrueを返すホスト名ベリファイアを使用する必要があるのと同じ理由で、何もしないトラストマネージャーを使用しないでください。いくつかの例があり、SSLのクイックフィックスを提供します。エラーメッセージ。)

于 2012-05-30T10:14:43.093 に答える
1

Javaには、有名な認証局からのルート証明書が含まれているため、実際の証明書がある場合は、ブラウザのように動作します。

独自の証明書に署名すると、ブラウザが警告を表示し、将来的に証明書を使用できるようにするためのUIを提供します。これは、Javaプログラムの状況が異なるところです。これを処理する正しい方法は、作成しているプログラムに完全に依存し、万能のアプローチはあり得ません。

アプリケーションにUIがある場合は、ブラウザーと同様のことを行うことができます。

一方、「ヘッドレス」アプリケーションは通常、必要なルート証明書を使用して事前構成されています。

最終的に、ブラウザとJava PKIX検証ライブラリの両方が、認証が最終的に依存するルート証明書を提供または承認することを要求することにより、TLSのセキュリティを維持しています。信頼されたルート証明書がないと、サーバーを認証することは不可能であり、したがって、通信のプライバシーまたは整合性を保証することは不可能です。

于 2019-05-14T21:27:41.063 に答える