Automatically pass a cookie with each web-service call - web-services

I have a standalone web-service client. When invoking any of the web-methods an additional "cookie" string must be implicitly(not as a web-method parameter) passed to the WS. The WS on the other end must be able to obtain the string and use it. How can this be achieved?
I invoke the service in the following way:
Service srv = Service.create(new URL(WSDL), QNAME);
myClassPort = srv.getPort(MyClass.class);
What I need is to put some code before the first line, which would make the client send this "cookie" string every time I invoke some remote method via myClassPort. Thx.

By default JAX-WS web services and clients are stateless. When a client makes a request, the server responds and sets a cookie on the connection, if it participates in a session. But, the JAX-WS client ignores that cookie and the server treats subsequent requests as new interaction. When the session is enabled, JAX-WS client sends the same cookie with each subsequent request so that server can keep track of the client session.
So you should not be using either cookies or HTTP sessions with web services. Return a token ID as part of the response; then the client can send that along with the next request.
Anyway:
JAX-WS web service clients must be configured to maintain session information (such as cookies), using the javax.xml.ws.session.maintain property.
Other web service stacks may have similar mechanisms.
On the Server Side
JAX-WS uses some handy annotations defined by Common Annotations for the Java Platform (JSR 250), to inject the web service context and declaring lifecycle methods.
WebServiceContext holds the context information pertaining to a request being served.
You don't need to implement javax.xml.rpc.server.ServiceLifecycle. With JAX-WS Web Service all you need to do is mark a field or method with #Resource. The type element MUST be either java.lang.Object or javax.xml.ws.WebServiceContext.
#WebService
public class HelloWorld {
#Resource
private WebServiceContext wsContext;
public void sayHello(){
MessageContext mc = wsContext.getMessageContext();
HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
}
}

There are some misleading answers to this question, so I will attempt to highlight current best practices. Most of these suggestions are part of the OWASP security guidelines, which I strongly recommend anyone working on web development to review.
1) ALWAYS use temporary (session scoped) cookies.
2) All cookies should be protected and encrypted.
3) Do not pass tokens in request payloads
4) For any requests which return data that may be sent back to the server, include a nonce (single use token) in your responses.
5) later requests should (must) include the nonce and the cookie
Again, my recommendation is to review the OWASP guidelines and proceed accordingly.
You may want to look into using a service provider for authentication - this is much smarter than brewing your own solution as there are literally a million details that all must be correct. Auth0.com is one of these.

Related

How to use FedEx Web Services in flutter

I'm developing an APP to track FedEx packages using flutter. Where should I integrate FedEx web service WSDL into my code so that I can send my tracking request to FedEx and get the response back?
Currently I'm testing with another api and able to get response by sending request directly to the url of this api. But FedEx web service does not work that way and I have to use their WSDL to set the url.
Beer.fromJSON(Map<String, dynamic> jsonMap) :
id = jsonMap['id'],
name = jsonMap['name'],
tagline = jsonMap['tagline'],
description = jsonMap['description'],
image_url = jsonMap['image_url'];
}
Future<Stream<Beer>> getBeers() async {
final String url = 'https://api.punkapi.com/v2/beers';
final client = new http.Client();
final streamedRest = await client.send(
http.Request('get', Uri.parse(url))
);
return streamedRest.stream
.transform(utf8.decoder)
.transform(json.decoder)
.expand((data) => (data as List))
.map((data) => Beer.fromJSON(data));
}
WSDL isn't something you import into your app, or at least not with dart. It describes the requests that can be made to the various endpoints their server supports.
Fedex's documentation does a better job explaining than I could:
A SOAP request to, or response from a service is generated according to the service’s WSDL definition.
A WSDL is an XML document that provides information about what the service does, the methods that are available, their parameters, and parameter types. It describes how to communicate with the service in order to generate a request to, or decipher a response from, the service.
The purpose of a WSDL is to completely describe a web service to a client. A WSDL generally defines where the service is available and which communication protocol is used to talk to the service. It defines everything required to write a program that will work with an XML web service.
There's a good chance that the endpoint actually uses SOAP for the communication, which dart doesn't currently fully support. You're going to have to use something like dart:xml to generate requests that match the description in the WSDL, and then you can send them with the http.Client the same way as you have done for the other API.

Asynchronous Web Service & Web Service without response?

The concept of Asynchronous Web Service is a web service where the client does not have to wait to receive a response from the server. in AJAX this is implemented by having a callback function to process the response. So the server indeed still sends the response to the client.
Is it possible to have an Asynchronous Web Service without response? Is there any platform that provide this?
Thank you.
I have done asynch web services in the past. They are very useful. YOu do not need a detailed response but you at least need an HTTP response, like 200 OK. If the client that makes the request provides some sort of ID or key for that request, then the client can use the same ID/key to later on query for the result/response of the request.
As far as frameworks that provide this, I do not know of any. In the past I would just have a shared memory store, like Memcache, to store the state and result of the request. As long as the state is shared across all nodes, any node can then process the call back request.
EDIT: Providing a key in the request can be done in either REST or SOAP environment. HTTP provides multiple places where a key can be communicated.
GET query param (REST)
HTTP header (SOAP/REST)
Added to the message body of a POST request. This can be done through two ways.
param in the message body (REST)
variable or attribute in serialized object (SOAP/REST))

Apache CXF Request/Response

I am working on an application that I want to use to catch a SOAP request when it goes into the CXFServlet. There is some processing I need to do to the SOAP envelope on the server side, before the CXFServlet processes it.
I have been presuming that the SOAP envelope, once it reaches the server side, is one of the parameters in the HTTPServletRequest object. But looking at what comes in (using a debugger, of course), I cannot find it.
Can someone tell me where the SOAP request goes when a client sends it to the server? I know that the client is sending the request using an HTTP POST, and I know that the server is using information in the request in order to access the appropriate web service method, then placing any return values from the method into a SOAP response and returning it to the client. What I need to know is where where does the CXFServlet (or one of its filters) look in order to get the SOAP information? Is it somewhere in the parameters? In the servlet context? Does a filter process the SOAP information before it gets to the CXFServlet? How can I get that envelope and do things to it before the web service method is called?
Someone please advise...
Do you want to access the original request ? If yes the actual request or response object itself can be accessed using the WebServiceContext object.
First, declare a private field for the WebServiceContext in your service implementation, and annotate it as a resource
#Resource
private WebServiceContext context;
Then, within your implementing methods, you can access the MessageContext, HttpServletRequest, and HttpServletResponse as follows:
MessageContext ctx = context.getMessageContext();
HttpServletRequest request = (HttpServletRequest)ctx.get(AbstractHTTPDestination.HTTP_REQUEST);
For more info about WebServiceContext see the following url :
http://docs.oracle.com/javase/6/docs/api/javax/xml/ws/WebServiceContext.html
If you need to intercept the request before it is ever processed by the CXFServlet, you should look at developing a Servlet Filter.
If you just want to process the SOAP message before CXF does, you can likely use a CXF Interceptor. The phases noted in the documentation indicate the points you can intercept the message. Depending on what you want to do/change, you may need to play around with the phases.
The source for CXF's SoapHeaderInterceptor or SoapActionInInterceptor would be good places to start looking at how to work with the SOAP message.

Axis2 multiple connection authentication issue

I have two servlets that access two corresponding Axis2 web services on the same host. One of the servlets is read-only, while the other writes to a database.
Each of the Axis2 web services uses BASIC authentication. The read-only web service uses a system account, while the write web service uses the user's credentials (which are submitted as part of a web form).
The problem I'm running into is that the servlet called second always fails authentication to its web service. For example, I can query the read-only service through it's servlet all I want, but I get a "401: Authorization Required" when I try to use the write service. If I call the write service first, I get the same error when I try to use the read-only service.
Here is how I am setting the credentials for the connections in the servlets:
Stub service = new Stub(serviceUrl);
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);
auth.setPreemptiveAuthentication(true);
service._getServiceClient().getOptions().setProperty(HTTPConstants.AUTHENTICATE, auth);
The servlet that accesses the read-only service has this code in it's constructor. The servlet that accesses the write service has this code in it's doGet/doPost method.
It seems that the credentials for the first service called are getting cached somewhere, but I can't find where that could be. I saw a possible solution here, but I can't find where WSClientConstants.CACHED_HTTP_STATE is defined. The comments in this JIRA issue seems to imply that it's part of org.apache.axis2.transport.http.HTTPConstants but it's not there.
Specifics:
Axis version: 1.5.1
Tomcat Version: 6.0.26
Java version: 1.6.0_23
It turns out the connections to the two different services were using the same JSESSIONID. Thus, the connection to the second web service was trying to use a session authenticated for the first web service, causing the error.
My solution for this was to define an HttpClient for each service, done by the following
MultiThreadedHttpConnectionManager manager = new MuliThreadedHttpConnectionManager();
HttpClient client = new HttpClient(manager);
ConfigurationContext context = ConfigurationContextFactory.createDefaultConfigurationContext();
context.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, client);
context.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, true);
Stub service = new Stub(context, serviceUrl);
This allows both servlets to have a separate session for their corresponding services.
The important point is to create a dedicated ConfigurationContext.
I've solved in a simpler way using a default config context when creating the stub without the multithreaded connection factory
stub = new MyStub(ConfigurationContextFactory.createDefaultConfigurationContext(), myServicesUrl);

Spring Web Services: Redirect Web Service Request

I have different Spring Web Services, which are included into the context by the
Endpoint Annotation, so there are no dependencies despite the Annotation (no interface etc.). Therefore, no "context" information is present.
Now I want to chain a web service request, ie. an Endpoint is called which itself should call a web service on the same server. I can use Spring's WebServiceTemplate, however, I need the current server url for this request.
Is there any way how this url can be injected during application startup into the Endpoints? Since the Endpoints do not extend some class, there is no way to get this information anywhere inside the Endpoints, also the request parameters do not have this information (these are simple JAXB-classes, which are marshalled on request).
I believe the best option is to send the URL as part of the request.
This also enables you to dynamically change the URL to a third server later.