【问题标题】:Spring WS Client — Authentication with Server and Client CertificatesSpring WS Client — 使用服务器和客户端证书进行身份验证
【发布时间】:2017-10-17 16:19:44
【问题描述】:

我需要能够为 SOAP 服务进行“客户端证书”身份验证。

我正在使用 Spring WS。我有:my.keymyCA.pemmyClient.crt

这是我的相关 Java 代码(我知道它仍然很乱,但我只是尝试先让它工作):

public TheResponse doIt(TheRequest request) {
  log.info("Sending request...");
  try {
    InputStream is = new FileInputStream(new File("src/main/resources/keystore.jks"));
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(is, "keystore!passwd".toCharArray());
    is.close();
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());

    InputStream is1 = new FileInputStream(new File("src/main/resources/truststore.jks"));
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(is1, "truststore!passwd".toCharArray());
    is1.close();
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(trustStore);

    HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
    messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
    messageSender.setTrustManagers(trustManagerFactory.getTrustManagers());
    setMessageSender(messageSender);

    return (TheResponse) getWebServiceTemplate().marshalSendAndReceive(request,
        new SoapActionCallback("https://domain/tld/icc/SomePathDownTheLine"));
  } catch (Throwable e) {
    log.error("Sh*t didn't work due to:", e);
    throw new GatewayConnectionException(String.format("Unexpected error while sending request [%s]", e.getMessage()));
  }
}

这就是我构建信任和密钥库的方式:

# KeyStore
$ openssl pkcs12 -export -in myClient.crt -inkey my.key -out keystore.p12 -name my_key -CAfile myCA.pem -caname root

$ keytool -importkeystore -deststorepass keystore!passwd -destkeypass keystore!passwd -destkeystore keystore.jks \
  -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass keystore!passwd -alias my_key

# Trustore (using truststore!passwd)
$ keytool -import -trustcacerts -alias my_ca -file myCA.pem -keystore truststore.jks

$ keytool -import -trustcacerts -alias my_cc -file myClient.crt -keystore truststore.jks

...这些是验证步骤:

$ keytool -list -keystore keystore.jks -storepass ********

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

my_key, Oct 17, 2017, PrivateKeyEntry,
Certificate fingerprint (SHA1): 1A:9D:6A:65:. . .:E6:C1:90

$ keytool -list -keystore truststore.jks -storepass ********

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

my_cc, Oct 17, 2017, trustedCertEntry,
Certificate fingerprint (SHA1): 1A:9D:6A:65:. . .:E6:C1:90
my_ca, Oct 17, 2017, trustedCertEntry,
Certificate fingerprint (SHA1): 36:82:F7:AB:. . .:70:B2:6C

...但是,每当我请求 SOAP 操作时,我都会返回一个 HTTP 401(未经授权)-org.springframework.ws.client.WebServiceTransportException: Unauthorized [401]

有什么线索吗?顺便说一句,我非常关注this 指南。我对 SSL 证书和所有这些东西不是很熟悉。


更新

SSL 握手工作正常。我可以通过设置-Djavax.net.debug=all VM 选项来了解它是如何工作的。现在发生的情况是,不管所有这些安全措施,服务器还需要用户名和密码。

【问题讨论】:

    标签: web-services ssl soap keystore spring-ws


    【解决方案1】:

    这一切都很好。最终,HTTP 401 (Unauthorized) 的原因是因为服务需要Basic auth 而我没有发送它。

    所有的密钥库和信任库生成都是完美的。这是“最终”解决方案(使用 Spring Web 服务):

      //
      // Spring Config
    
      // Inject messageSender() into a WebServiceTemplate or,
      // Have a class that extends from WebServiceGatewaySupport
    
      @Bean
      public HttpsUrlConnectionMessageSender messageSender() throws Exception {
        HttpsUrlConnectionMessageSender messageSender = new BasicAuthHttpsConnectionMessageSender(username, password);
        messageSender.setTrustManagers(trustManagersFactoryBean().getObject());
        messageSender.setKeyManagers(keyManagersFactoryBean().getObject());
        return messageSender;
      }
    
      @Bean
      public TrustManagersFactoryBean trustManagersFactoryBean() {
        TrustManagersFactoryBean trustManagersFactoryBean = new TrustManagersFactoryBean();
        trustManagersFactoryBean.setKeyStore(trustStore().getObject());
        return trustManagersFactoryBean;
      }
    
      @Bean
      public KeyManagersFactoryBean keyManagersFactoryBean() {
        KeyManagersFactoryBean keyManagersFactoryBean = new KeyManagersFactoryBean();
        keyManagersFactoryBean.setKeyStore(keyStore().getObject());
        keyManagersFactoryBean.setPassword(keyStorePassword);
        return keyManagersFactoryBean;
      }
    
      @Bean
      public KeyStoreFactoryBean trustStore() {
        KeyStoreFactoryBean keyStoreFactoryBean = new KeyStoreFactoryBean();
        keyStoreFactoryBean.setLocation(new ClassPathResource("truststore.jks")); // Located in src/main/resources
        keyStoreFactoryBean.setPassword(trustStorePassword);
        return keyStoreFactoryBean;
      }
    
      @Bean
      public KeyStoreFactoryBean keyStore() {
        KeyStoreFactoryBean keyStoreFactoryBean = new KeyStoreFactoryBean();
        keyStoreFactoryBean.setLocation(new ClassPathResource("keystore.jks"));
        keyStoreFactoryBean.setPassword(keyStorePassword);
        return keyStoreFactoryBean;
      }
    

    // You might need org.springframework.ws:spring-ws-support in order to
    // have HttpsUrlConnectionMessageSender
    public final class BasicAuthHttpsConnectionMessageSender extends HttpsUrlConnectionMessageSender {
      private String b64Creds;
    
      public BasicAuthHttpsConnectionMessageSender(String username, String password) {
        b64Creds = Base64.getUrlEncoder().encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8));
      }
    
      @Override
      protected void prepareConnection(HttpURLConnection connection) throws IOException {
        connection.setRequestProperty(HttpHeaders.AUTHORIZATION, String.format("Basic %s", b64Creds));
        super.prepareConnection(connection);
      }
    }
    

    另请参阅此one — 我自己也问过 O:)

    希望这可以帮助将来的人。我花了一段时间才整理好所有东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 2015-10-29
      • 2018-07-05
      • 2019-01-14
      • 1970-01-01
      相关资源
      最近更新 更多