22

現在、クライアントが Web ブラウザーを使用して Web サイトにアクセスする限り、相互認証セキュリティの実装に成功しています。これは、ブラウザーがすべての証明書交換を処理するためです。次に、サーバーが必要とする相互認証を使用して、ユーザーが HTTPS 経由で Web サービスにアクセスできる安全なインターフェイスを作成する必要があります。

まず、これに役立つリソースを知っている人はいますか? 私はかなり長い間探しましたが、何も見つかりませんでした。これを行う方法について誰かが私に与えることができる他のヒントはありますか?

第二に、私の最大の障害は、証明書の処理方法を理解していないことだと思います。サーバーのキーを受け入れ、自分のキーをサーバーに提示することをネゴシエートするにはどうすればよいですか? これは Java です。

4

4 に答える 4

14

私はこれに長い時間を費やしましたが、最終的に実際に機能する例を見つけました。これは Glassfish と Netbeans ベースですが、いじってみると他の環境 (Eclipse や Tomcat など) でも動作するようになると思います。

http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511

私が見つけた問題は、glassfish にプリインストールされている証明書ではなく、独自の証明書を使用する場合です。

注: 私はセキュリティの専門家ではありません。これを本番環境にデプロイしないでください!

これを行うために、NetBeans 6.9、JDK 1.6、GlassFish 3.0.1、および OpenSSL v1.0 を使用しています (非公式の Win32 バイナリを使用しています)。

# Create the CA
mkdir ca server client
cd ca
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem
echo 02 > serial.txt
cd ..

# Creating the Server Keystore

openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt
openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server
keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12
keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer

# Create the Client Keystore

openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt
openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1
keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12
keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer

# Import public keys and certificates into each others keystores

keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks"
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts"
move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup"
copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks"

GlassFish 管理コンソールで、http リスナーのセキュリティを有効にし、SSL3、TLS、およびクライアント認証のボックスにチェックを入れ、証明書のニックネームをサーバーに、キー ストアを config\keystore.jks に、トラスト ストアを config\keystore.jks に設定します。 、信頼アルゴリズムを PKIX に変更し、証明書の最大長を 5 のままにします。

NetBeans で、新しい Web アプリケーション プロジェクトを作成します。その中で、新しい Web サービスを作成します。

私の Web サービス コードは次のようになります。

@WebService()
public class ListProducts {

  @Resource WebServiceContext context;

  @WebMethod(operationName = "listProducts")
  public String listProducts() {
    return context.getUserPrincipal().toString();
  }

}

Web サービスを右クリックし、[Web サービス属性の編集] を選択します。[セキュア サービス] ボックスにチェックを入れ、[セキュリティ メカニズム] として [相互証明書セキュリティ] を選択します。[構成...] ボタンをクリックし、[署名の暗号化] ボックスにチェックを入れます。Use Development Defaults ボックスのチェックを外し、Keystore ボタンをクリックします。server.jks キーストアの場所を設定し、serverエイリアスを選択します。トラストストア構成についても同じことを行います (ただし、ここでエイリアスを選択する必要はありません)。

client1.p12 クライアント証明書をブラウザーにインポートします。Web サービスを Glassfish にデプロイします。ブラウザーで Web サービスを開き、デプロイされた WSDL を HTTPS 経由で参照します。WSDL およびその他のスキーマをダウンロードします。WSDL2Java を使用するときに NetBeans がリモート リソースを使用しないように、参照されているスキーマの名前をローカル コピーに変更します。(この段落は、承認された証明書を持つクライアントに WSDL を制限したためですが、問題の証明書にアクセスできないため、NetBeans はそれをリモートでフェッチできません)。

新しい Java プロジェクトを作成します。新しい Web サービス クライアントを作成します。プロンプトが表示されたら、保存した WSDL ファイルを NetBeans に指定します。METRO2.0 ライブラリ ファイルをインポートします ( C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar)。私のコードは次のようになりました:

public static void main(String[] args) {
  System.getProperties().put("javax.net.ssl.keyStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
  System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit");
  System.getProperties().put("javax.net.ssl.trustStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
  System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit");
  System.out.println(new ListProductsService().getListProductsPort().listProducts());
}

webservices-api.jar を Java\jdk1.6\jre\lib\endorsed ディレクトリにコピーします。Web サービス参照を右クリックし、[Web サービス属性の編集] を選択します。キーストアの場所を client1.jks に設定し、エイリアスを に設定しclient1ます。トラストストアの場所を client1.jks に設定し、エイリアスを に設定しserverます。

うまくいけば、クライアントを実行できるようになり、次のような出力が表示されるはずです。 EMAILADDRESS=bob@anonymous.org, CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US

于 2010-05-27T04:43:04.860 に答える
13

For mutual authentication with SSL (aka two-way SSL) outside a browser, you'll need... Well, actually, let's see what you need for one-way SSL first:

  1. A server keystore
  2. A client truststore

The server keystore contains the server's (possibly self-signed) certificate and private key. This store is used by the server to sign messages and to return credentials to the client.

The client truststore contains the server's (self-signed) certificate (extracted from the server keystore into a stand-alone certificate, without the server private key). This is required if the certificate is not signed by a trusted CA for which you already have a certificate in the truststore bundled with the JRE. This step allows to create a chain of trust.

With this, you can implement one-way SSL (the traditional use case).

To implement two-way SSL, you need to make this setup "symmetric" so we'll need to add:

  1. A client keystore
  2. A server truststore

The client keystore contains the client's (possibly self-signed) certificate and private key. This store is used by the client for the same purpose than the server keystore i.e. to send client credentials to the server during the TLS mutual authentication handshake.

The server truststore contains the clients (self-signed) standalone certificates (extracted from the clients keystore into stand-alone certificates, without the clients private key). This is required for the exact same reasons as previously mentioned.

Some resources to help you to generate all this stuff and to implement the final solutions:

于 2010-02-11T00:25:22.243 に答える
6

Webサービスライブラリが標準java.net.URLクラスをHTTPクライアントとして使用する場合、いくつかのシステムプロパティを設定でき、双方向認証は組み込みのHTTPSサポートによって処理されます。

必要なプロパティは次のとおりです。

  • javax.net.ssl.trustStore:ルートCA証明書が含まれています
  • javax.net.ssl.keyStore:クライアント証明書と秘密鍵が含まれています
  • javax.net.ssl.keyStorePassword:クライアントの秘密鍵を保護するパスワード

これらの設定は、プロセスによるすべてのSSL接続のデフォルトになります。より細かく制御したい場合は、独自に設定する必要がありますSSLContext。Webサービスランタイムでそれが可能かどうかは、選択したランタイムによって異なります。

于 2010-02-10T23:01:47.607 に答える
1

このブログエントリに簡単なレシピが掲載されています。

しかし、実際の答えは、クライアント側の HTTP インタラクションを実装するために使用している Java API によって異なると思います。たとえば、JAX-RPC を使用すると、少し違ったことをするように見えます。

于 2010-02-10T22:58:52.220 に答える