我正在为Web服务创建客户端。我一直收到以下错误:
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)
这是我的环境:
虽然在互联网上搜索提供了很多关于如何通过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,我重写了handle(),它提供了WSPasswordCallback的密码。
这是我第一次收到回调时的print语句的输出:
org.apache.ws.security.WSPasswordCallback@50c713d2[
identifier=TestMerchant
password=<null>
key=<null>
usage=2
passwordType=<null>
]
以下是设置密码后的输出:
org.apache.ws.security.WSPasswordCallback@50c713d2[
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)
答案 0 :(得分: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。为了整理松散的目标,以下是修改后的方法:
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.PW_TEXT);
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.PW_CALLBACK_REF, this);
result = stub.runTransaction(request);
}
catch (Exception e) {
throw e;
}
return result;
}
完成这些修改后,您的客户将会工作。请记住,上面的一些设置是特定于我正在集成的服务。您可能需要调整这些以适合您的集成,这可能需要一些试验和错误。
再次感谢所有在SO上发布知识渊博文章的人,让像我这样的用户能够解决我们偶尔遇到的问题。