35

HTTPS を使用し、Firefox でうまく動作する、Grizzly で作成された REST サーバーがあります。コードは次のとおりです。

//Build a new Servlet Adapter.
ServletAdapter adapter=new ServletAdapter();
adapter.addInitParameter("com.sun.jersey.config.property.packages", "My.services");
adapter.addInitParameter(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, SecurityFilter.class.getName());
adapter.setContextPath("/");
adapter.setServletInstance(new ServletContainer());

//Configure SSL (See instructions at the top of this file on how these files are generated.)
SSLConfig ssl=new SSLConfig();
String keystoreFile=Main.class.getResource("resources/keystore_server.jks").toURI().getPath();
System.out.printf("Using keystore at: %s.",keystoreFile);
ssl.setKeyStoreFile(keystoreFile);
ssl.setKeyStorePass("asdfgh");

//Build the web server.
GrizzlyWebServer webServer=new GrizzlyWebServer(getPort(9999),".",true);

//Add the servlet.
webServer.addGrizzlyAdapter(adapter, new String[]{"/"});

//Set SSL
webServer.setSSLConfig(ssl);

//Start it up.
System.out.println(String.format("Jersey app started with WADL available at "
  + "%sapplication.wadl\n",
        "https://localhost:9999/"));
webServer.start();

今、私はJavaでそれに到達しようとしています:

SSLContext ctx=null;
try {
    ctx = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e1) {
    e1.printStackTrace();
}
ClientConfig config=new DefaultClientConfig();
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null,ctx));
WebResource service=Client.create(new DefaultClientConfig()).resource("https://localhost:9999/");

//Attempt to view the user's page.
try{
    service
        .path("user/"+username)
        .get(String.class);
}

そして得る:

com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:128)
 at com.sun.jersey.api.client.Client.handle(Client.java:453)
 at com.sun.jersey.api.client.WebResource.handle(WebResource.java:557)
 at com.sun.jersey.api.client.WebResource.get(WebResource.java:179)

ウェブで見つけた例から、トラストストアをセットアップしてから、ある種のトラストマネージャーをセットアップする必要があるようです。これは、私の単純な小さなプロジェクトの多くのコードとセットアップ作業のようです。もっと簡単に言う方法はありますか..私はこの証明書を信頼し、.cert ファイルを指していますか?

4

5 に答える 5

49

「この証明書を信頼する簡単な方法はありますか」と言うとき、それはまさに証明書をJavaトラストストアに追加することによって行っていることです。これは非常に簡単に行うことができ、トラスト ストアを認識または利用するためにクライアント アプリ内で何もする必要はありません。

クライアント マシンで、cacerts ファイルの場所を見つけます (これはデフォルトの Java トラスト ストアであり、デフォルトでは <java-home>/lib/security/certs/cacerts.

次に、次のように入力します。

keytool -import -alias <Name for the cert> -file <the .cer file> -keystore <path to cacerts>

これにより、証明書がトラスト ストアにインポートされ、その後、クライアント アプリは問題なく Grizzly HTTPS サーバーに接続できるようになります。

証明書をデフォルトのトラスト ストアにインポートしたくない場合 (つまり、この 1 つのクライアント アプリで証明書を使用できるようにしたいだけで、そのマシンの JVM で実行している他のアプリケーションでは証明書を使用したくない場合) は、次のことができます。アプリ専用の新しいトラスト ストアを作成します。既存のデフォルトの cacerts ファイルへのパスを keytool に渡す代わりに、新しいトラスト ストア ファイルへのパスを keytool に渡します。

keytool -import -alias <Name for the cert> -file <the .cer file> -keystore <path to new trust store>

トラスト ストア ファイルの新しいパスワードを設定して確認するよう求められます。次に、クライアント アプリを起動するときに、次のパラメーターを使用して起動します。

java -Djavax.net.ssl.trustStore=<path to new trust store> -Djavax.net.ssl.trustStorePassword=<trust store password>

本当に安っぽいです。

于 2009-11-18T17:19:39.243 に答える
13

これが苦痛なルートです:

    SSLContext ctx = null;
    try {
        KeyStore trustStore;
        trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream("C:\\truststore_client"),
                "asdfgh".toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory
                .getInstance("SunX509");
        tmf.init(trustStore);
        ctx = SSLContext.getInstance("SSL");
        ctx.init(null, tmf.getTrustManagers(), null);
    } catch (NoSuchAlgorithmException e1) {
        e1.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
    ClientConfig config = new DefaultClientConfig();
    config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
            new HTTPSProperties(null, ctx));

    WebResource service = Client.create(config).resource(
            "https://localhost:9999/");
    service.addFilter(new HTTPBasicAuthFilter(username, password));

    // Attempt to view the user's page.
    try {
        service.path("user/" + username).get(String.class);
    } catch (Exception e) {
        e.printStackTrace();
    }

お奨めはそれらの6つの異なるキャッチされた例外が大好きです:)。コードを少し単純化するために、確かにいくつかのリファクタリングがあります。しかし、私はVM上のdelfuegoの-Dオプションが好きです。設定できるjavax.net.ssl.trustStore静的プロパティがあればいいのにと思います。たった2行のコードで完了です。誰もがそれがどこにあるか知っていますか?

これは質問するには多すぎるかもしれませんが、理想的にはキーツールは使用されません。代わりに、trustedStoreはコードによって動的に作成され、実行時に証明書が追加されます。

より良い答えがあるに違いありません。

于 2009-11-18T20:07:31.983 に答える
3

このエラーは、自己署名証明書だけが原因ではないことに注意してください。新しい Entrust CA 証明書は同じエラーで失敗します。正しいことは、この重要なセキュリティ機能を無効にするのではなく、適切なルート証明書でサーバーを更新することです。

于 2011-11-23T00:16:55.867 に答える
1

これをチェックしてください: http://code.google.com/p/resting/ . REST を使用して HTTPS REST サービスを利用できます。

于 2011-07-28T06:44:43.060 に答える