2016-06-10 103 views
0

當對需要相互身份驗證的API進行RESTful後臺調用時,我收到了handshake_failed異常。我已經與另一方的一位工程師進行了驗證,他們正在觀察堆棧跟蹤,證明服務器端證書已被我的客戶無故交換和接受,但是當服務器請求客戶端證書時,我的方不提供握手結束。Apache HTTPClient在相互身份驗證期間不發送客戶端證書

事情是我不知道如何驗證SSLSocketFactory是否無法識別正確的證書,或者只是不在首位尋找它。

這是我的代碼,這是js利用Apache Httpclient庫。

importPackage(Packages.org.apache.http.client); 
importPackage(Packages.org.apache.http.client.methods); 
importPackage(Packages.org.apache.http.impl.client); 
importPackage(Packages.org.apache.http.message); 
importPackage(Packages.org.apache.http.client.entity); 
importPackage(Packages.org.apache.http.util); 
importPackage(Packages.org.apache.commons.httpclient); 
importPackage(Packages.org.apache.http.params); 
importPackage(Packages.org.apache.http.ssl); 
importPackage(Packages.org.apache.http.ssl.SSLSocketFactory); 
importPackage(Packages.java.security.Keystore); 
importPackage(Packages.org.apache.http.conn.ssl); 
importPackage(Packages.javax.net.ssl); 
importPackage(Packages.java.io); 
importPackage(Packages.org.apache.http.impl.conn); 
importPackage(Packages.org.apache.http.conn.scheme); 

//Benchmark 1 
var healthMessageStatus = "0"; 
var xtn_startTime = DateUtil.getCurrentDate('yyyyMMddHHmmss'); 
channelMap.put('xtn_startTime',xtn_startTime); 

var url = 'https://smr.prodposturl.net/AuthenticatingXmlServer.aspx' 

//HTTP Connection Template 
var httpParams = new BasicHttpParams(); 
HttpConnectionParams.setConnectionTimeout(httpParams, 3600000); 
HttpConnectionParams.setSoTimeout(httpParams, 3600000); 

//APPROACH 3 
var KEY_STORE_PATH = "C:\\PHIA\\Certs\\mykeystore"; 
var KEY_STORE_PASSWORD = "changeit"; 

var TRUST_STORE_PATH = "C:\\PHIA\\Certs\\cacerts"; 
var TRUST_STORE_PASSWORD = "changeit"; 

var keystore = new KeyStore.getInstance(KeyStore.getDefaultType()); 
channelMap.put('keystore',keystore); 

var keystoreInput = new FileInputStream(KEY_STORE_PATH); 

keystore.load(keystoreInput, KEY_STORE_PASSWORD.split('')); 
var keystoreline = "Keystore has " + keystore.size() + " keys"; 

// load the truststore 
var truststore = new KeyStore.getInstance(KeyStore.getDefaultType()); 
var truststoreInput = new FileInputStream(TRUST_STORE_PATH); 
truststore.load(truststoreInput, TRUST_STORE_PASSWORD.split('')); 
var truststoreline = "Truststore has " + truststore.size() + " keys"; 

channelMap.put('keystoreline', keystoreline); 
channelMap.put('truststoreline', truststoreline); 


var schemeRegistry = new SchemeRegistry(); 
var lSchemeSocketFactory = new org.apache.http.conn.ssl.SSLSocketFactory("TLSv1", keystore, KEY_STORE_PASSWORD, truststore, null, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);//, keystore); 

var lSchemeSocketFactoryString = String(lSchemeSocketFactory); 
channelMap.put('lSchemeSocketFactoryString',lSchemeSocketFactoryString); 

schemeRegistry.register(new Scheme("https", lSchemeSocketFactory, 443)); 

var httpclient = new DefaultHttpClient(new org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager(httpParams, schemeRegistry), httpParams); 

httpclient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(10, false)); 

//Benchmark 2 
var xtn_postTime = DateUtil.getCurrentDate('yyyyMMddHHmmss'); 
channelMap.put('xtn_postTime',xtn_startTime); 

var httpPost = new HttpPost(url); 

httpPost.addHeader("Authorization", "Basic RiF2ZSR0YXI2UzpQUk4icV9APE0tdigj") 
httpPost.addHeader("Content-Type", "text/xml") 

//passes the results to a string builder/entity 
var se = new org.apache.http.entity.StringEntity(connectorMessage.getEncodedData().toString()); 
channelMap.put('se', se); 

//sets the post request as the resulting string 
httpPost.setEntity(se); 
var httpContents = String(httpPost); 
channelMap.put('httpContents',httpContents); 
var keystoreContents = String(keystore); 
channelMap.put('keystoreContents',keystoreContents); 

var response = httpclient.execute(httpPost); 

try { 
var statusCode = response.getStatusLine().getStatusCode(); 
var entity = response.getEntity(); 
var responseString = EntityUtils.toString(entity, "UTF-8"); 

channelMap.put('statusCode', statusCode); 
channelMap.put('responseString', responseString); 

} finally { 
response.close(); 
} 

//Benchmark 3 
var xtn_finishTime = DateUtil.getCurrentDate('yyyyMMddHHmmss'); 
channelMap.put('xtn_finishTime',xtn_finishTime); 

//Response Calculations 
//var xtn_totalProcessing = (xtn_finishTimeMs - xtn_startTimeMs)/1000; 
var xtn_totalProcessing = xtn_finishTime - xtn_startTime; 
channelMap.put('xtn_totalProcessing',xtn_totalProcessing); 

//var xtn_totalPostTime = (xtn_finishTimeMs - xtn_postTimeMs)/1000; 
var xtn_totalPostTime = xtn_finishTime - xtn_postTime; 
channelMap.put('xtn_totalPostTime', xtn_totalPostTime); 

var finalStatusCheck = responseString.indexOf("<Code>010</Code>") 
var pendingStatusCheck = responseString.indexOf("<Code>000</Code>") 
var followUpMessage = false; 
channelMap.put('finalStatusCheck',finalStatusCheck); 
if (finalStatusCheck == -1 & pendingStatusCheck == -1) { 
healthMessageStatus = "2"; 
channelMap.put('healthMessageStatus', healthMessageStatus); 
throw('Bad HTTP Response Code: ' + statusCode + ' For GUID File ID: ' + $('GUID') + '. Response String: ' + responseString); 
} 
else if (pendingStatusCheck > -1) { 
channelMap.put('healthMessageStatus', healthMessageStatus); 
channelMap.put('followUpMessage', followUpMessage) 
followUpMessage = true; 
healthMessageStatus = "2"; 
throw('Bad HTTP Response Code: ' + statusCode + ' For GUID File ID: ' + $('GUID') + '. Response String: ' + responseString); 
} 
else 
{ 
healthMessageStatus = "1"; 
channelMap.put('healthMessageStatus', healthMessageStatus); 
channelMap.put('followUpMessage', followUpMessage) 
} 

這裏是例外,我得到:

JavaScript Writer error 
ERROR MESSAGE: Error evaluating JavaScript Writer 
com.mirth.connect.server.MirthJavascriptTransformerException: 
CHANNEL: 0 - Inbound Clinical PDF PROD 
CONNECTOR: SURESCRIPTS PROD API 
SCRIPT SOURCE: JavaScript Writer 
SOURCE CODE:  
541: var httpContents = String(httpPost); 
542: channelMap.put('httpContents',httpContents); 
543: var keystoreContents = String(keystore); 
544: channelMap.put('keystoreContents',keystoreContents); 
545: 
546: var response = httpclient.execute(httpPost); 
547: 
548: try { 
549:  var statusCode = response.getStatusLine().getStatusCode(); 
550:  var entity = response.getEntity(); 
LINE NUMBER: 546 
DETAILS: Wrapped javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 
    at 3f792644-5e4b-4bbf-af2d-3ac8ef00b5db:546 (doScript) 
    at 3f792644-5e4b-4bbf-af2d-3ac8ef00b5db:598 
    at com.mirth.connect.connectors.js.JavaScriptDispatcher$JavaScriptDispatcherTask.call(JavaScriptDispatcher.java:184) 
    at com.mirth.connect.connectors.js.JavaScriptDispatcher$JavaScriptDispatcherTask.call(JavaScriptDispatcher.java:122) 
    at java.util.concurrent.FutureTask.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 
    at sun.security.ssl.Alerts.getSSLException(Unknown Source) 
    at sun.security.ssl.Alerts.getSSLException(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) 
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:533) 
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:401) 
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:470) 
    at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:65) 
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177) 
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144) 
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:131) 
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611) 

回答

0

與服務器是由JRE製造(JSSE供應商是精確的)身份驗證時使用的私鑰的決定,而不是HttpClient的。然而,人們可以通過使用自定義覆蓋默認行爲PrivateKeyStrategy

SSLContext sslContext = SSLContexts.custom() 
     .loadKeyMaterial(myKeyStore, "mypassword".toCharArray(), new PrivateKeyStrategy() { 
      @Override 
      public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) { 
       // Pick a cert alias based on socket endpoint, SSL session or private key details 
       return "vip"; 
      } 
     }) 
     .build(); 

CloseableHttpClient client = HttpClients.custom() 
     .setSslcontext(sslContext) 
     .build(); 
+0

感謝oleg。看起來像我需要的,但我努力在JavaScript中正確實現這一點。你知道js中的語法是什麼樣子嗎? – Eagledare

+0

爲什麼不在COBOL中?我很抱歉我的JS技能是最好的 – oleg

相關問題