x80*_*486 4 ssl soap web-services spring-ws keystore
我需要能够对 SOAP 服务进行“客户端证书”身份验证。
\n\n我正在使用 Spring WS。我有: a my.key、 amyCA.pem和 a myClient.crt。
这是我的相关 Java 代码(我知道它仍然很混乱,但我只是想让它先工作):
\n\npublic TheResponse doIt(TheRequest request) {\n log.info("Sending request...");\n try {\n InputStream is = new FileInputStream(new File("src/main/resources/keystore.jks"));\n KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());\n keyStore.load(is, "keystore!passwd".toCharArray());\n is.close();\n KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());\n keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());\n\n InputStream is1 = new FileInputStream(new File("src/main/resources/truststore.jks"));\n KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());\n trustStore.load(is1, "truststore!passwd".toCharArray());\n is1.close();\n TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());\n trustManagerFactory.init(trustStore);\n\n HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();\n messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());\n messageSender.setTrustManagers(trustManagerFactory.getTrustManagers());\n setMessageSender(messageSender);\n\n return (TheResponse) getWebServiceTemplate().marshalSendAndReceive(request,\n new SoapActionCallback("https://domain/tld/icc/SomePathDownTheLine"));\n } catch (Throwable e) {\n log.error("Sh*t didn\'t work due to:", e);\n throw new GatewayConnectionException(String.format("Unexpected error while sending request [%s]", e.getMessage()));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这就是我构建信任库和密钥库的方式:
\n\n# KeyStore\n$ openssl pkcs12 -export -in myClient.crt -inkey my.key -out keystore.p12 -name my_key -CAfile myCA.pem -caname root\n\n$ keytool -importkeystore -deststorepass keystore!passwd -destkeypass keystore!passwd -destkeystore keystore.jks \\\n -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass keystore!passwd -alias my_key\n\n# Trustore (using truststore!passwd)\n$ keytool -import -trustcacerts -alias my_ca -file myCA.pem -keystore truststore.jks\n\n$ keytool -import -trustcacerts -alias my_cc -file myClient.crt -keystore truststore.jks\nRun Code Online (Sandbox Code Playgroud)\n\n...这些是验证步骤:
\n\n$ keytool -list -keystore keystore.jks -storepass ********\n\nKeystore type: JKS\nKeystore provider: SUN\n\nYour keystore contains 1 entry\n\nmy_key, Oct 17, 2017, PrivateKeyEntry,\nCertificate fingerprint (SHA1): 1A:9D:6A:65:. . .:E6:C1:90\n\n$ keytool -list -keystore truststore.jks -storepass ********\n\nKeystore type: JKS\nKeystore provider: SUN\n\nYour keystore contains 2 entries\n\nmy_cc, Oct 17, 2017, trustedCertEntry,\nCertificate fingerprint (SHA1): 1A:9D:6A:65:. . .:E6:C1:90\nmy_ca, Oct 17, 2017, trustedCertEntry,\nCertificate fingerprint (SHA1): 36:82:F7:AB:. . .:70:B2:6C\nRun Code Online (Sandbox Code Playgroud)\n\n...但是,每当我请求 SOAP 操作时,我都会返回 HTTP 401 (Unauthorized) \xe2\x80\x94 org.springframework.ws.client.WebServiceTransportException: Unauthorized [401]。
有什么线索吗?顺便说一句,我基本上遵循本指南。我对 SSL 证书和所有这些东西不是很熟悉。
\n\n更新
\n\nSSL 握手工作正常。我可以通过设置-Djavax.net.debug=allVM 选项来了解它是如何工作的。现在发生的情况是,无论所有这些安全性如何,服务器也需要用户名和密码。
这一切都很好。最终,原因HTTP 401 (Unauthorized)是因为需要服务Basic auth而我没有发送。
所有密钥库和信任库生成都是完美的。这是“最终”解决方案(使用 Spring Web 服务):
\n\n //\n // Spring Config\n\n // Inject messageSender() into a WebServiceTemplate or,\n // Have a class that extends from WebServiceGatewaySupport\n\n @Bean\n public HttpsUrlConnectionMessageSender messageSender() throws Exception {\n HttpsUrlConnectionMessageSender messageSender = new BasicAuthHttpsConnectionMessageSender(username, password);\n messageSender.setTrustManagers(trustManagersFactoryBean().getObject());\n messageSender.setKeyManagers(keyManagersFactoryBean().getObject());\n return messageSender;\n }\n\n @Bean\n public TrustManagersFactoryBean trustManagersFactoryBean() {\n TrustManagersFactoryBean trustManagersFactoryBean = new TrustManagersFactoryBean();\n trustManagersFactoryBean.setKeyStore(trustStore().getObject());\n return trustManagersFactoryBean;\n }\n\n @Bean\n public KeyManagersFactoryBean keyManagersFactoryBean() {\n KeyManagersFactoryBean keyManagersFactoryBean = new KeyManagersFactoryBean();\n keyManagersFactoryBean.setKeyStore(keyStore().getObject());\n keyManagersFactoryBean.setPassword(keyStorePassword);\n return keyManagersFactoryBean;\n }\n\n @Bean\n public KeyStoreFactoryBean trustStore() {\n KeyStoreFactoryBean keyStoreFactoryBean = new KeyStoreFactoryBean();\n keyStoreFactoryBean.setLocation(new ClassPathResource("truststore.jks")); // Located in src/main/resources\n keyStoreFactoryBean.setPassword(trustStorePassword);\n return keyStoreFactoryBean;\n }\n\n @Bean\n public KeyStoreFactoryBean keyStore() {\n KeyStoreFactoryBean keyStoreFactoryBean = new KeyStoreFactoryBean();\n keyStoreFactoryBean.setLocation(new ClassPathResource("keystore.jks"));\n keyStoreFactoryBean.setPassword(keyStorePassword);\n return keyStoreFactoryBean;\n }\nRun Code Online (Sandbox Code Playgroud)\n\n// You might need org.springframework.ws:spring-ws-support in order to\n// have HttpsUrlConnectionMessageSender\npublic final class BasicAuthHttpsConnectionMessageSender extends HttpsUrlConnectionMessageSender {\n private String b64Creds;\n\n public BasicAuthHttpsConnectionMessageSender(String username, String password) {\n b64Creds = Base64.getUrlEncoder().encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8));\n }\n\n @Override\n protected void prepareConnection(HttpURLConnection connection) throws IOException {\n connection.setRequestProperty(HttpHeaders.AUTHORIZATION, String.format("Basic %s", b64Creds));\n super.prepareConnection(connection);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n另请参考这个\ xe2\x80\x94 也是我自己问的O:)
\n\n希望这可以帮助将来的人。我花了一段时间才把所有东西都整理好。
\n| 归档时间: |
|
| 查看次数: |
9243 次 |
| 最近记录: |