Broadly, I'm looking for a way to secure web service implemented in Java (using Spring Boot). I secured it with HTTP basic first.
Currently it is secured using XWSS. The problem is, that soap header for xwss is
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" wsse:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>user</wsse:Username>
<wsse:Password>password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
while I need
<SecuritySOAPHeader>
<UserName>user</UserName>
<Password>password</Password>
</SecuritySOAPHeader>
It is "wsdl first" WS, how can I plug security in, when header is defined in WSDL?
edit:
If it helps, this is what is defined in WSDL
<wsdl:binding name="CreditLimitServiceSoap" type="tns:CreditLimitServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetCreditLimitAndBalanceDetails">
<soap:operation soapAction="http://cargowise.com/Accounting/GetCreditLimitAndBalanceDetails" style="document" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:GetCreditLimitAndBalanceDetailsSecuritySOAPHeader" part="SecuritySOAPHeader" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
It seems, that I'd be able to access the header when I change my current
#Endpoint
public class CustomerBalancesEndpoint {
...
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "GetCreditLimitAndBalanceDetails", )
#ResponsePayload
public GetCreditLimitAndBalanceDetailsResponse getCustomerBalance(#RequestPayload GetCreditLimitAndBalanceDetails request) {
...
}
...
}
to
#Endpoint
public class CustomerBalancesEndpoint {
...
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "GetCreditLimitAndBalanceDetails", )
#ResponsePayload
public GetCreditLimitAndBalanceDetailsResponse getCustomerBalance(#RequestHeader SecuritySOAPHeader securityHeader, #RequestPayload GetCreditLimitAndBalanceDetails request) {
...
}
...
}
As it seems, maven-jaxb2-plugin had no issue with that WSDL.
edit 2:
Currently I'm more inclined to modify the message from client (the one with SecuritySOAPHeader) and modify it to standard (XWSS) header to have SOAP-ENV:Fault generated if wrong password is passed.
Related
I have a WSDL like that :
...
<wsdl:message name="myHeader">
<wsdl:part name="parameter" element="header:myHeader"/>
</wsdl:message>
...
<wsdl:operation name="myOperation">
<soap:operation soapAction="myOperation" style="document" />
<wsdl:input name="myOperationRequest">
<soap:header message="mySession:myHeader" part="header" use="literal"/>
<soap:body parts="parameters" use="literal" />
</wsdl:input>
<wsdl:output name="myOperationResponse">
<soap:body parts="parameters" use="literal" />
</wsdl:output>
<wsdl:fault name="myOperationException">
<soap:fault name="createTroubleTicketByValueException" use="literal" />
</wsdl:fault>
</wsdl:operation>
....
I convert my WSDL into Java with wsdl2java, not problem during the conversion with the exsh set to true.
But when I start my application (Spring 4, CXF 2.7), I'm getting the following warning :
2015-09-28 14:19:04,640 WARN [main] o.a.c.s.f.ReflectionServiceFactoryBean(1525) - Method interface ....XXXSessionWSPort.myOperation is configured as BARE but there are more than one parameters with wrong #Webparam annotated or without #WebParam annotated.
If I look closer to the WsPort generated :
#WebResult(name = "myOperationResponse", targetNamespace = "http://myNamespace", partName = "parameters")
#WebMethod(action = "myOperation")
public myOperationResponse myOperation(
#WebParam(partName = "parameters", name = "myOperationRequest", targetNamespace = "http://myNameSpace")
myOperationRequest parameters,
#WebParam(partName = "parameters", name = "myheader", targetNamespace = "http://headerNameSpace", header = true)
myHeader parameters1) throws myOperationException;
Moreover, as a client when I make a call to myOperation CXF/JAXB/Jax-ws/...(?) add a "1" at the end of the myHeader tag, consequently the server cannot handle the header...
After debugging in the class ReflectionServiceFactoryBean, I see the problem coming from the same partName in the two #WebParam.
To correct this, I have to change the header's part name into the WSDL, but I can't : it's not mine.
So I would made this change in the jaxb binding xml file, if possible, how can I do that?
If you have a better solution don't hesitate!
A bit late, but maybe this can help you: "A customization file"
http://java-soa.blogspot.pe/2008/07/parameter-customization-in-jax-ws.html
This problem has had me stumped for almost two days now, I really need some help figuring it out.
I have used wsimport to generate code from two different .wsdl files for a Java project.
The first service works just fine but for some reason the response from the second service cannot be unmarshalled to a response object.
Working service:
#WebMethod(action = "[actionName]")
#WebResult(name = "getSimpleCompanyInfoResponse", partName = "getSimpleCompanyInfoResponse")
public GetSimpleCompanyInfoResponse getSimpleCompanyInfo(
#WebParam(name = "getSimpleCompanyInfoRequest", partName = "getSimpleCompanyInfoRequest") GetSimpleCompanyInfoRequest getSimpleCompanyInfoRequest);
Response POJO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "getSimpleCompanyInfoResponse", propOrder = {
//variables
})
public class GetSimpleCompanyInfoResponse {
//variables
}
Response XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:getSimpleCompanyInfoResponse>
<getSimpleCompanyInfoResponse>
//variables
</getSimpleCompanyInfoResponse>
</ns1:getSimpleCompanyInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
NOT working service:
#WebMethod(operationName = "PersonnelInfo", action = "[actionName]")
#WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse")
public PersonnelInfoResponse personnelInfo(
#WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest);
Response POJO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "PersonnelInfoResponse", propOrder = {
//variables
})
public class PersonnelInfoResponse {
//variables
}
Response XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:PersonnelInfoResponse>
//variables
</ns1:PersonnelInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Using -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true or monitoring with Wireshark I can see the Response envelope from the second service coming through just fine and unmarshalling doesn't throw any exceptions but in the end PersonnelInfoResponse is null.
The only difference I can see is that the second service response payload in the XML is missing the outer element which seems to be the problem. However, I do not know how to "fix" it so it doesn't look for the outer element.
If anything was unclear or missing please let me know and I'll try to give you all the information.
EDIT:
No, I unfortunately don't have any control over the service itself, I only have the .wsdl and .xsd.
I'm calling the service like this:
ReportsControllerPortType port = new ReportsControllerService().getReportsControllerPort();
PersonnelInfoRequest request = new PersonnelInfoRequest();
//fill the required fields in the request, username, password, etc.
PersonnelInfoResponse response = port.personnelInfo(request);
The client-side service stubs (ReportsControllerService & ReportsControllerPortType) are also automatically generated by wsimport according to the .wsdl and .xsd.
EDIT 2:
Removing the operation name doesn't work, the service fails to initialize. Following are the definitions from both .wsdl-s:
Working service:
<wsdl:message name="getSimpleCompanyInfoRequest">
<wsdl:part name="getSimpleCompanyInfoRequest" type="tns:getSimpleCompanyInfoRequest" />
</wsdl:message>
<wsdl:message name="getSimpleCompanyInfoResponse">
<wsdl:part name="getSimpleCompanyInfoResponse" type="tns:getSimpleCompanyInfoResponse" />
</wsdl:message>
<wsdl:portType name="MonitoringControllerPortType">
<wsdl:operation name="getSimpleCompanyInfo">
<wsdl:input message="tns:getSimpleCompanyInfoRequest" />
<wsdl:output message="tns:getSimpleCompanyInfoResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MonitoringControllerBinding" type="tns:MonitoringControllerPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="getSimpleCompanyInfo">
<soap:operation soapAction="[domain]/#getSimpleCompanyInfo" style="rpc" />
<wsdl:input>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MonitoringControllerService">
<wsdl:port name="MonitoringControllerPort" binding="tns:MonitoringControllerBinding">
<soap:address location="[serviceUri]" />
</wsdl:port>
</wsdl:service>
Not working service:
<wsdl:message name="PersonnelInfoRequest">
<wsdl:part name="PersonnelInfoRequest" type="tns:PersonnelInfoRequest" />
</wsdl:message>
<wsdl:message name="PersonnelInfoResponse">
<wsdl:part name="PersonnelInfoResponse" type="tns:PersonnelInfoResponse" />
</wsdl:message>
<wsdl:portType name="ReportsControllerPortType">
<wsdl:operation name="PersonnelInfo">
<wsdl:input message="tns:PersonnelInfoRequest" />
<wsdl:output message="tns:PersonnelInfoResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ReportsControllerBinding" type="tns:ReportsControllerPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="PersonnelInfo">
<soap:operation soapAction="[domain]/#PersonnelInfo" style="rpc" />
<wsdl:input>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" namespace="[namespaceUri]" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ReportsControllerService">
<wsdl:port name="ReportsControllerPort" binding="tns:ReportsControllerBinding">
<soap:address location="[serviceUri]" />
</wsdl:port>
</wsdl:service>
EDIT 3:
ReportsControllerService and MonitoringControllerService extend javax.xml.ws.Service and contain the definitions of the .wsdl schema location and namespace used. The service class returns a PortType object as you can see:
/**
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2
*/
#WebServiceClient(name = "ReportsControllerService", targetNamespace = "[namespaceUri]", wsdlLocation = "[wsdlUri]")
public class ReportsControllerService extends Service {
#WebEndpoint(name = "ReportsControllerPort")
public ReportsControllerPortType getReportsControllerPort() {
return super.getPort(new QName("[namespaceUri]", "ReportsControllerPort"), ReportsControllerPortType.class);
}
}
ReportsControllerPortType is an interface which contains methods for every operation endpoint that exists in the service
/**
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2
*/
#WebService(name = "ReportsControllerPortType", targetNamespace = "[namespaceUri]")
#SOAPBinding(style = SOAPBinding.Style.RPC)
#XmlSeeAlso({ObjectFactory.class})
public interface ReportsControllerPortType {
#WebMethod(operationName = "PersonnelInfo", action = "[actionName]")
#WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse")
public PersonnelInfoResponse personnelInfo(
#WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest);
}
}
The thing is, all of those classes are automatically generated by JAX-WS (as you can see from the comments) based on the .wsdl schema. The implementation is abstracted somewhere inside the JDK and I don't have control over that either. Yes, I can refactor the code so I bypass JAX-WS but as I understand it, this is supposed to be like a de facto standard way to consume .wsdl-based SOAP services.
The project uses Spring as a base-framework and I have already confirmed both services will work when I use Spring-WS instead so I can refactor but I want to understand why this way isn't working.
I believe I may have found out why your webservice is misbehaving. According to the specification, an RPC webservice must fulfill the following criteria in its soap binding (i.e. the #SOAPBinding annotation you have there)
A style of RPC: check
A use of LITERAL: check
A parameterStyle of WRAPPED: From the description you've given, it would appear that WRAPPED is not the case here, seeing as you're receiving a naked PersonnelInfoResponse (and possibly sending a naked PersonnelInfoRequest) without any wrapping indicates that the service itself is broken.
An excerpt from the JAX-WS spec:
Use of RPC style requires the use of WRAPPED parameter style. Deviations from this is an error
There is one obvious difference between your 2 calls :
You should try to remove operationName = "PersonnelInfo" from your second call which is not present in the first working one.
I'm a bit stuck here. We're trying to write WS Client using Spring WS. The challenge is to handle web services like getVersion() that do not need to pass any values to the server.
Here's a typical Client implementation you'd normally use:
public class MyServiceClient extends WebServiceGatewaySupport {
public String getVersion() {
SomeJaxbGeneratedClass request = new SomeJaxbGeneratedClass();
String response = (String) getWebServiceTemplate().marshalSendAndReceive(request,
new SoapActionCallback("someNameSpace/getVersion"));
return response;
}
}
The issue is when calling getVersion there's no SomeJaxbGeneratedClass to be passed as a request since it's only requesting to get the version number. So my question is what should be passed in as a request (RequestPayload) in this case? Does WebServiceTemplate have another method that would work better?
Here's how getVersion is defined in WSDL:
<WSDL:message name="getVersionRequest"/>
<WSDL:message name="getVersionResponse">
<WSDL:part name="version" type="xsd:string"/>
</WSDL:message>
<portType>
<WSDL:operation name="getVersion">
<WSDL:input message="tns:getVersionRequest"/>
<WSDL:output message="tns:getVersionResponse"/>
</WSDL:operation>
</portType>
<binding>
<WSDL:operation name="getVersion">
<SOAP:operation soapAction="someNameSpace/getVersion"/>
<WSDL:input>
<SOAP:body namespace="someNameSpace" use="literal"/>
</WSDL:input>
<WSDL:output>
<SOAP:body namespace="someNameSpace" use="literal"/>
</WSDL:output>
</WSDL:operation>
</binding>
Any help will be greatly appreciated.
Just want to give everyone an update in case you run into a similar issue. I got this resolved by switching from Spring WS to Spring JAX-WS solution using JaxWsPortProxyFactoryBean.
I am learning WSDL using online documentation, for WSDL Ports it is mentioned that:
A port MUST NOT specify more than one address.
A port MUST NOT specify any binding information other than address
information.
and the example given is:
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceInput"/>
<output message="tns:GetLastTradePriceOutput"/>
</operation>
</portType>
What is address in this example? also what it means that A port MUST NOT specify any binding information other than address information.? Please help me in understanding the concepts.
I think you have referred wrong example, It was talking about port under service tag. Something like this,
<wsdl:service name="StockQuote">
<wsdl:port name="StockQuoteSoap" binding="tns:StockQuoteSoap">
<soap:address location="http://www.webservicex.net/stockquote.asmx" />
</wsdl:port>
<wsdl:port name="StockQuoteSoap12" binding="tns:StockQuoteSoap12">
<soap12:address location="http://www.webservicex.net/stockquote.asmx" />
</wsdl:port>
<wsdl:port name="StockQuoteHttpGet" binding="tns:StockQuoteHttpGet">
<http:address location="http://www.webservicex.net/stockquote.asmx" />
</wsdl:port>
<wsdl:port name="StockQuoteHttpPost" binding="tns:StockQuoteHttpPost">
<http:address location="http://www.webservicex.net/stockquote.asmx" />
</wsdl:port>
Here you can see address location of this particular webservice i.e.
http://www.webservicex.net/stockquote.asmx
That means each time, you will send your request message on this address location under a specific binding.
There are 4 ports or you can say 1 webservices i.e. StockQuote but you can call it in 4 different ways as per bindings.
Bindings defines message format and protocol details for each port. For example.
<wsdl:binding name="StockQuoteSoap" type="tns:StockQuoteSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="GetQuote">
<soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
Lets say you are calling StockQuote webservice using "StockQuoteSoap" port. So while sending your request you will use above binding as referred in port tag.
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
http transport protocol and soap messaging protocol.
<wsdl:binding name="StockQuoteSoap" type="tns:StockQuoteSoap">
tns:StockQuoteSoap is referring at your port type
<wsdl:operation name="GetQuote">
GetQuote is your operation name.
This is more concerned, how your webservice is implemented on server side for this binding.
You can consider operation name as method name and port type as class name in traditional programming language.
Full port type difinition can be seen in wsdl as
<wsdl:portType name="StockQuoteSoap">
<wsdl:operation name="GetQuote">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Get Stock quote for a company Symbol</wsdl:documentation>
<wsdl:input message="tns:GetQuoteSoapIn" />
<wsdl:output message="tns:GetQuoteSoapOut" />
</wsdl:operation>
That means GetQuote method of StockQuoteSoap class will be executed at server for given input and output message in definition.
soap:operation soapAction="http://www.webserviceX.NET/GetQuote" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output
your binding also specifies input and output message format and style
SOAP Action is optional feature which is used by server to filter out incoming request.
(3) If I am developing a service in Java programming then we have classes defined in Java package, so where the package structure go in this WSDL?
Lets take an example where, you want to publish a webservice at
url "http://testhost:9999/ws/helloexample" in java in package examplePackage.
You have a class or interface named sayHello in which you have defined a method public String helloWorld (String Name).
You are publishing this class using
Endpoint.publish("http://testhost:9899/ws/helloexample", new sayHello());
So your generated wsdl will be mapped like below.
Interface or class name: PortType
Method name: Operation
Method name: input message (request)
Method name+Response: output message (response)
<portType name="sayHello">
<operation name="helloWorld">
<input message="tns:helloWorld"/>
<output message="tns:helloWorldResponse"/>
</operation>
</portType>
Endpoint.publish("http://testhost:9899/ws/helloexample",new sayHello())
: address location
<wsdl:service name="sayHelloService">
<wsdl:port name="sayHelloPort" binding="tns:sayHelloPortBinding">
<soap:address location="http://testhost:9899/ws/helloexample" />
</wsdl:port>
You can use various webservice annotations available like #WebParam, #WebMethod, #WebResult etc to change operation name, message part name, namespace etc in wsdl.
Further addidng binding in generated wsdl,
<wsdl:binding name="sayHelloPortBinding" type="tns:sayHello">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="helloWorld">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input>
<soap:body use="literal" namespace="http://examplePackage" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" namespace="http://examplePackage" />
</wsdl:output>
</wsdl:operation>
SOAPAction can be set in #WebMethod annotation. style can be set in #SOAPBinding anootation.
I've to provide a .jsp page(index.jsp) along with my Web Service project for testing purpose.
Basically the .jsp page has a textarea, for reading a soap request as a string & on submitting it the soap response will come.
I tried it with "javax.xml.ws.Service & Dispatch" class, it's working fine.
But now I'm asked for a javascript/ajax based code.
Can anybody help me regarding this.
I'm giving a sample .wsdl file here :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://zensar.com/greeting" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Greeting"
xmlns:grtng="http://zensar.com/greeting/schema"
targetNamespace="http://zensar.com/greeting">
<wsdl:types>
<xsd:schema targetNamespace="http://zensar.com/greeting">
<xsd:import namespace="http://zensar.com/greeting/schema"
schemaLocation="Greeting.xsd"></xsd:import>
</xsd:schema>
</wsdl:types>
<wsdl:message name="GreetingRequest">
<wsdl:part element="grtng:GreetingRequest" name="GreetingRequest" />
</wsdl:message>
<wsdl:message name="GreetingResponse">
<wsdl:part element="grtng:GreetingResponse" name="GreetingResponse" />
</wsdl:message>
<wsdl:portType name="GreetingPort">
<wsdl:operation name="Greeting">
<wsdl:input message="tns:GreetingRequest" />
<wsdl:output message="tns:GreetingResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Greeting" type="tns:GreetingPort">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Greeting">
<soap:operation soapAction="http://zensar.com/GreetingWS/Greeting" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Greeting">
<wsdl:port binding="tns:Greeting" name="Greeting">
<soap:address location="http://localhost:8085/Greeting/services" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>**
Personally, I'd say consuming the web service directly through javascript is a bit masochistic.
In my opinion it'd be much easier for the javascript to call a server side method (with whatever architecture that may be, c#, java, php etc) then do a CURL request and send the response back to the front end.
Writing out a soap endpoint by hand in javascript just seems pointless when you could use something like Axis2 at the server side to do the boiler plate heavy loading of the SOAP handshake.
You can try this ... http://www.ibm.com/developerworks/webservices/library/ws-wsajax/
This article explains everything in detail.