2012-04-21 81 views
2

我在一個Web服務創建一個客戶端的過程中來的。我不斷收到以下錯誤:WSSecurityEngine說,回調過程中沒有提供的密碼,即使它提供

AxisFault 
    faultCode: {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}InvalidSecurity 
    faultSubcode: 
    faultString: 
     Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 
    faultActor: 
    faultNode: 
    faultDetail: {http://xml.apache.org/axis/} 
    stackTrace: 
     Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 

這是我在這裏的環境:

  • IntelliJ IDEA的IDE
  • Apache Axis的
  • Apache的WSS4J 1.5.1
  • 的Apache XML安全1.4。 0
  • JDK 1.6
  • 最大OS X

雖然在互聯網上搜索提供了很多如何通過XML配置將安全頭添加到請求中的示例,但我的要求是通過程序動態執行此操作。因此,這裏是我的代碼:

public class AxisClient implements CallbackHandler { 

    ServerEnvironment environment; 

    AxisClient(ServerEnvironment environment) { 
     this.environment = environment; 
    } 

    public enum ServerEnvironment { 
     LIVE("https://ics2ws.ic3.com/commerce/1.x/transactionProcessor"), 
     TEST("https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor"); 

     String url; 

     ServerEnvironment (String url) { 
      this.url = url; 
     } 

     public String getUrl() { 
      return url; 
     } 
    } 

    public enum Merchant { 
     TestMerchant ("testpassword"); 

     private String transactionKey; 

     Merchant(String transactionKey) { 
      this.transactionKey = transactionKey; 
     } 

     public String getTransactionKey() { 
      return transactionKey; 
     } 
    } 

    public static void main(String[] argv) { 
     String ani = "7162502800"; 
     String zipCode = "14221"; 
     String ccNum ="5555555555554444"; 
     String expMonth = "01"; 
     String expYear = "15"; 
     String cvv = "123"; 
     String unitPrice = "9.99"; 
     String qty = "2"; 

     try { 
      new AxisClient(ServerEnvironment.TEST).doAuth(Merchant.TestMerchant, ani, zipCode, ccNum, expMonth, expYear, cvv, String.valueOf(new Date().getTime()), unitPrice, qty); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public Boolean doAuth(Merchant merchant, String ani, String zipCode, String ccNum, String expMonth, String expYear, String cvv, String id, String unitPrice, String qty) throws Exception { 
     Boolean result = false; 

     RequestMessage request; 
     BillTo billTo; 
     Card card; 
     PurchaseTotals purchaseTotals; 
     Item item; 
     Item[] items; 
     ReplyMessage reply; 

     try { 
      // billing info 
      billTo = new BillTo(); 
      billTo.setPhoneNumber(ani); 
      billTo.setPostalCode(zipCode); 

      // card info 
      card = new Card(); 
      card.setAccountNumber(ccNum); 
      card.setExpirationMonth(new BigInteger(expMonth)); 
      card.setExpirationYear(new BigInteger(expYear)); 
      card.setCvNumber(cvv); 

      // currency info 
      purchaseTotals = new PurchaseTotals(); 
      purchaseTotals.setCurrency("USD"); 

      // item 
      item = new Item(); 
      item.setId(new BigInteger(id)); 
      item.setUnitPrice(unitPrice); 
      item.setQuantity(new BigInteger(qty)); 

      // add item to items array 
      items = new Item[1]; 
      items[0] = item; 

      // create our request 
      request = new RequestMessage(); 
      request.setMerchantID(merchant.toString()); 
      request.setCcAuthService(new CCAuthService()); 
      request.getCcAuthService().setRun("true"); 

      // add request specific params 
      request.setBillTo(billTo); 
      request.setCard(card); 
      request.setPurchaseTotals(purchaseTotals); 
      request.setItem(items); 

      reply = post(merchant, request); 

      if (reply != null) { 
       System.out.println(ReflectionToStringBuilder.toString(reply, ToStringStyle.MULTI_LINE_STYLE)); 
      } 
     } 
     catch (Exception e) { 
      throw e; 
     } 

     return result; 
    } 

    public EngineConfiguration createConfigurationWithSecurityHeaders(Merchant merchant) throws Exception { 
     SimpleProvider result; 

     Handler securityHandler; 
     SimpleChain requestHandler; 
     SimpleChain responseHandler; 
     Handler pivot; 
     Handler transport; 

     try { 
      result = new SimpleProvider(); 

      securityHandler = new WSDoAllSender(); 
      securityHandler.setOption(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
      securityHandler.setOption(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT); 
      securityHandler.setOption(WSHandlerConstants.PW_CALLBACK_REF, this); 
      securityHandler.setOption(WSHandlerConstants.USER, merchant.toString()); 
      securityHandler.setOption(WSHandlerConstants.MUST_UNDERSTAND, "false"); 

      requestHandler = new SimpleChain(); 
      requestHandler.addHandler(securityHandler); 

      responseHandler = new SimpleChain(); 
      responseHandler.addHandler(securityHandler); 

      pivot = new HTTPSender(); 

      transport = new SimpleTargetedChain(requestHandler, pivot, responseHandler); 

      result.deployTransport(HTTPTransport.DEFAULT_TRANSPORT_NAME, transport); 
     } 
     catch (Exception e) { 
      throw e; 
     } 

     return result; 
    } 

    public ReplyMessage post (Merchant merchant, RequestMessage request) throws Exception { 
     ReplyMessage result; 

     TransactionProcessorLocator locator; 
     URL endPoint; 
     ITransactionProcessorStub stub; 
     EngineConfiguration configuration; 

     try { 
      locator = new TransactionProcessorLocator(); 

      // use client config 
      configuration = createConfigurationWithSecurityHeaders(merchant); 
      locator.setEngineConfiguration(configuration); 
      locator.setEngine(new org.apache.axis.client.AxisClient(configuration)); 

      endPoint = new URL(environment.getUrl()); 

      stub = (ITransactionProcessorStub) locator.getportXML(endPoint); 
      stub._setProperty(WSHandlerConstants.USER, request.getMerchantID()); 
      stub._setProperty(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
      stub._setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT); 
      stub._setProperty(WSHandlerConstants.PW_CALLBACK_REF, this); 
      stub._setProperty(WSHandlerConstants.MUST_UNDERSTAND, "false"); 

      result = stub.runTransaction(request); 
     } 
     catch (Exception e) { 
      throw e; 
     } 

     return result; 
    } 

    @Override 
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 

     for (Callback callback : callbacks) { 

      System.out.println(ReflectionToStringBuilder.toString(callback, ToStringStyle.MULTI_LINE_STYLE)); 

      if (callback instanceof WSPasswordCallback) { 

       WSPasswordCallback passwordCallback = (WSPasswordCallback) callback; 

       switch (Merchant.valueOf(passwordCallback.getIdentifer())) { 

        case TestMerchant: 
         passwordCallback.setPassword(Merchant.TestMerchant.getTransactionKey()); 
         System.out.println(ReflectionToStringBuilder.toString(passwordCallback, ToStringStyle.MULTI_LINE_STYLE)); 
         break; 

        default: 
         throw new UnsupportedCallbackException(callback, "Unrecognized prompt!"); 
       } 
      } 
      else { 
       throw new UnsupportedCallbackException(callback, "Unrecognized callback!"); 
      } 
     } 
    } 
} 

正如你可以從上面看到,我的類實現CallbackHandler,並將我重寫手柄(),它提供了WSPasswordCallback密碼。

這裏是print語句,當我拿到第一個回調的輸出:

[email protected][ 
    identifier=TestMerchant 
    password=<null> 
    key=<null> 
    usage=2 
    passwordType=<null> 
] 

這裏是輸出設置密碼後:

[email protected][ 
    identifier=TestMerchant 
    password=testpassword 
    key=<null> 
    usage=2 
    passwordType=<null> 
] 

所以,我不是真的確定爲什麼我不斷收到該錯誤消息。任何幫助解決這個問題將不勝感激。一種不同的方法(Axis2中,CXF)

還建議,歡迎選購。

這裏是我完整的堆棧跟蹤,如果它是任何幫助:

AxisFault 
faultCode: {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}InvalidSecurity 
faultSubcode: 
faultString: 
Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 
General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 

faultActor: 
faultNode: 
faultDetail: 
    {http://xml.apache.org/axis/}stackTrace: 
Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 
General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 

    at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222) 
    at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129) 
    at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2939) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648) 
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) 
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205) 
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522) 
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:395) 
    at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227) 
    at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696) 
    at org.apache.axis.Message.getSOAPEnvelope(Message.java:435) 
    at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUnderstandChecker.java:62) 
    at org.apache.axis.client.AxisClient.invoke(AxisClient.java:206) 
    at org.apache.axis.client.Call.invokeEngine(Call.java:2784) 
    at org.apache.axis.client.Call.invoke(Call.java:2767) 
    at org.apache.axis.client.Call.invoke(Call.java:2443) 
    at org.apache.axis.client.Call.invoke(Call.java:2366) 
    at org.apache.axis.client.Call.invoke(Call.java:1812) 
    at itg.cybersource.axis.ITransactionProcessorStub.runTransaction(ITransactionProcessorStub.java:1284) 
    at itg.AxisClient.post(AxisClient.java:208) 
    at itg.AxisClient.doAuth(AxisClient.java:132) 
    at itg.AxisClient.main(AxisClient.java:75) 

    {http://xml.apache.org/axis/}hostname:C02GD302DRJL.local 


Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 
General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant) 

    at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222) 
    at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129) 
    at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2939) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648) 
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) 
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205) 
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522) 
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:395) 
    at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227) 
    at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696) 
    at org.apache.axis.Message.getSOAPEnvelope(Message.java:435) 
    at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUnderstandChecker.java:62) 
    at org.apache.axis.client.AxisClient.invoke(AxisClient.java:206) 
    at org.apache.axis.client.Call.invokeEngine(Call.java:2784) 
    at org.apache.axis.client.Call.invoke(Call.java:2767) 
    at org.apache.axis.client.Call.invoke(Call.java:2443) 
    at org.apache.axis.client.Call.invoke(Call.java:2366) 
    at org.apache.axis.client.Call.invoke(Call.java:1812) 
    at itg.cybersource.axis.ITransactionProcessorStub.runTransaction(ITransactionProcessorStub.java:1284) 
    at itg.AxisClient.post(AxisClient.java:208) 
    at itg.AxisClient.doAuth(AxisClient.java:132) 
    at itg.AxisClient.main(AxisClient.java:75) 

回答

4

嘗試很多不同的事情很多天後,我終於想通了回答我的問題。談談鍵盤和椅子之間的問題!!!!!

因此,沒有在這裏廢話少說是什麼,問題是:

securityHandler.setOption(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT); 

現在WSConstants.PASSWORD_TEXT實際上等同於"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"。我必須用真的有是WSConstants.PW_TEXT這相當於"PasswordText"這是我需要在我的代碼是什麼。一旦我做出改變,一切都很好。

流行的看法相反,你完全可以做到這一切在一個綱領性的方式。你並不需要配置WSDD XML爲你攔截的消息,在SOAP頭處理的WS-Security。要清理鬆散的末端,以下是修改後的方法:

一旦進行了這些修改,您的客戶端就可以工作。請記住,上面的一些設置是特定於我正在與之集成的服務。您可能需要調整這些以適合您的集成,這可能需要一些試驗和錯誤。

再次感謝所有在SO中發佈難以置信的知識性文章的人們,使像我這樣的用戶能夠解決我們偶爾遇到的問題。