Apply HTTP basic authentication to jax ws (HttpSpiContextHandler) in embedded Jetty - jetty

There are some similar questions for earlier versions of Jetty (pre 9) but none that address this specific problem :
Server server = new Server();
System.setProperty("com.sun.net.httpserver.HttpServerProvider",
JettyHttpServerProvider.class.getName());
JettyHttpServer jettyServer = new JettyHttpServer(server, true);
Endpoint endpoint = Endpoint.create(new SOAPService()); // this class to handle all ws requests
endpoint.publish(jettyServer.createContext("/service")); // access by path
server.start()
Simplified code example above to show the only way that I have found to bridge between Jetty and incoming soap requests to my jax-ws service. All settings are in code with no web.xml, this is part of a larger solution that has multiple contexts and connections for different purposes (servlets etc..)
I have tried to add a handler class to the jettyServer.createContext("/service",new handler()) to see if I can perform a header extraction to simulate basic auth but it never gets executed.
My problem is that i cannot find a way to specify, by code against the Jetty server, to use basic authentication. Using the setSecurityHandler method of a ServletContextHandler is easy and works great for other contexts, i just can't figure out how to use this concept for the jax-ws service.
Any help would be much appreciated.
p.s. SSL is already implemented, I just need to add http basic auth.

For anyone else that may of come across the same problem here is the answer that i stumbled on eventually.
final HttpContext httpContext = jettyServer.createContext("/service");
com.sun.net.httpserver.BasicAuthenticator a = new com.sun.net.httpserver.BasicAuthenticator("") {
public boolean checkCredentials (String username, String pw)
{
return username.equals("username") && pw.equals("password");
}
};
httpContext.setAuthenticator(a);
endpoint.publish(httpContext);//access by path
You can expand the checkCredentials for something a bit more sophisticated of course, but this shows the basic working method.

Related

cxfendpoint change WS-Addressing namespace to 2005/08 and removal of Offer in CreateSequence

I hope it is ok to ask two somehow related Questions in one.
I am using a camel route to send a SOAP message to a webservice using Reliable Messaging. Now there is two Problems i ran into, first the WS-Addressing version that is used is wrong, i need to have 2005/08 but instead it is using 2004/08.
For setting up the endpoint i am using (shortend a bit)
CxfEndpoint cxfEndpoint = new CxfEndpoint();
cxfEndpoint.setWsdlURL(getWsdlURL());
cxfEndpoint.setDataFormat(DataFormat.CXF_MESSAGE);
cxfEndpoint.setCamelContext(camelContext);
camelContext.addEndpoint(outEndpoint.getId(), cxfEndpoint);
I also set up a cxfbus in the camel-context.xml file and a seperate http-conduit.xml
now my question for the WS-Addressing is, how can i change it to use WS-Addressing 2005/08? i already tried to add following to my route, before the endpoint is called, but it did not change the Addressing Namespace.
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
AddressingPropertiesImpl addrProps =
new AddressingPropertiesImpl("http://www.w3.org/2005/08/addressing");
Map<String, Object> requestContext = new HashMap<String, Object>();
requestContext.put("javax.xml.ws.addressing.context", addrProps);
exchange.getIn().setHeader(Client.REQUEST_CONTEXT, requestContext);
}
})
Regarding the Offer in the CreateSequence added the following before the endpoint is added to the CamelContext:
RMManager rmManager = cxfEndpoint.getBus().getExtension(RMManager.class);
rmManager.getSourcePolicy().setIncludeOffer(false);
Although this worked fine it had the nasty side effect that my http-conduit was no longer used. I fixed this with following:
cxfEndpoint.setBus(bus);
where bus is being #Autowired
but in my opinion this broke the WS-Reliable Messaging for my incoming CXF Endpoint that are created in a similiar way. It still sends the correct messages but before the CreateSequenceResponse is send, there is an empty SOAP message sent, that causes the client to drop out of the Sequence creation.
Now my question would be, is there a better way to remove the Offer from the CreateSequence?

Restlet + JAXRS extension - how to use filters?

I have a REST service implemented in Restlet + JAXRS extension.
At a certain point, I had to add the CORS headers to responses.
I have a lot of REST calls, and adding by hand the headers as this is working:
return Response.status(200).header("Access-Control-Allow-Origin", "*").
header("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Content-Type").
header("Access-Control-Expose-Headers", "Location, Content-Disposition").
header("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, HEAD, OPTIONS").
entity(fsJSON).build();
but I'd like to use filters in order to add those headers to all the responses, without adding those manually. I found a lot of examples of using filters in JAX-RS, like those:
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
http://javatech-blog.blogspot.it/2015/04/jax-rs-filters-example.html
http://blog.dejavu.sk/2014/02/04/filtering-jax-rs-entities-with-standard-security-annotations/
But I can't understand how to integrate them with Restlet + JAX-RS environment. For example, I can't see the ContainerResponseFilter class anywhere.
Anyone can help me?
When creating a JaxRS application within Restlet, you create a JaxRsApplication (see this link: http://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs). This class extends the standard application of Restlet. The latter provides the way to configure services on it using the getServices method.
So in your case, you don't need to use filters...
See this answer regarding the configuration of the CorsService of Restlet: How to use CORS in Restlet 2.3.1?.
Here a way to configure CORS within a Restlet JaxRS application:
Component comp = new Component();
Server server = comp.getServers().add(Protocol.HTTP, 8182);
JaxRsApplication application = new JaxRsApplication(comp.getContext());
application.add(new ExampleApplication());
CorsService corsService = new CorsService();
corsService.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsService.setAllowedCredentials(true);
application.getServices().add(corsService);
component.getDefaultHost().attachDefault(application);
Otherwise JAX-RS filters aren't supported by the corresponding extensions of Restlet. To add a filter, you need to add it as a Restlet filter in front of the application, as described below:
JaxRsApplication application = new JaxRsApplication(comp.getContext());
application.add(new ExampleApplication());
MyRestletFilter filter = new MyRestletFilter();
filter.setNext(application);
component.getDefaultHost().attachDefault(filter);
Hope it helps you,
Thierry

Persisting data in an axis object

Forgive me if this is a dumb question, I unfortunately have an assignment due! I am running apache axis under tomcat and need to deploy a simple web service class, see below.
I installed the counter file below as "MyCounter.jws" in the /tomcat/webapps/axis/ folder. Tomcat finds it and makes a corresponding MyCounter.xml. I use WSDL2Java on the XML file and client calls seem to work, but internal state is not saved:
Every time I call MyCounter.call from the client side, the return value is always 1. It seems the constructor is always called before the method call. How can I make it so the mycounter integer persists across requests?
public class MyCounter
{
int mycounter;
public MyCounter()
{
mycounter = 0;
}
public int call()
{
mycounter++;
return mycounter;
}
}
I think persisting is maybe the wrong word, I think what you mean is that the Java Class is not instantiated every time you call the service.
See: https://axis.apache.org/axis/java/user-guide.html#Scoped_Services
So you would need to change the Service definition yo achieve this.
I don't think that with the JWS files you will be able to configure the session scope. As the docs say:
https://axis.apache.org/axis/java/user-guide.html#JWS_Java_Web_Service_Files_-_Instant_Deployment
Quote:
Important: JWS web services are intended for simple web services. You
cannot use packages in the pages, and as the code is compiled at run
time you can not find out about errors until after deployment.
Production quality web services should use Java classes with custom
deployment.
So if you want to use such features you should consider using some of the other ways Axis offers to setup a WebService.
Also I would strongly recommend using Axis2 instead of Axis1:
http://axis.apache.org/axis2/java/core/
Axis1 can be quite complicated with the WSDD files to setup. Apart from Axis1 no more actively developed/maintained.

Pass custom HTTP header from Windows Phone to ASMX service

Problem: Want to send a custom HTTP header from Windows Phone 7.1 app to ASMX service. The ASMX service is developed by different team.
Solutions tried: There are number of questions & answers on net for this, but nothing seem to work in our case.
Refered HttpRequestMessageProperty,
and this.
Client Side Code:
HttpRequestMessageProperty httpProps = new HttpRequestMessageProperty();
httpProps.SuppressEntityBody = false;
httpProps.Headers["HeaderKey"] = "HeaderValue";
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpProps;
Service Side Code:
public string GetHeaderValue()
{
var properties = OperationContext.Current.IncomingMessageProperties;
var property = properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
string headerValue = property.Headers["HeaderKey"];
return headerValue;
}
The "HeaderKey" value is not available on service side. Can any one point us in right direction ? Any help will be appreciated.
Thank you.
Ok, So after some hits and misses, the below code worked:
HttpContext.Current.Request.Headers.GetValues("HeaderKey")[0];
The issue with using OperationContext was for ASMX the OperationContext.Current was null. In WCF service, the OperationContext.Current is available.
Thanks #user623396 for your time and efforts. Hope this helps someone out.

How to call Soap\WSDL Service through a login required webpage using matlab?

I am new to the wsdl\soapmessage query\reply world( if i can put it in this way), and I am facing some difficulties using the following wsdl( which I really really hope, one will be so kind to look at at least one of the services described there)
http://almdemo.polarion.com/polarion/ws/services/TrackerWebService?wsdl
which was provided to me to develop a matlab webinterface. Right now my matlab code looks like this:
targetNamespace = 'http://ws.polarion.com/TrackerWebService';
method = 'queryWorkItems';
values= {'Query','Sort'}
names = {'query', 'sort'}
types ={'xsd:string','xsd:string'}
message = createSoapMessage( targetNamespace, method, values, names, types)
response = callSoapService('http://almdemo.polarion.com/polarion/ws/services',...
% Service's endpoint
'http://almdemo.polarion.com/polarion/#/workitems',...
% Server method to run
message)
% SOAP message created using createSoapMessage
author = parseSoapResponse(response)
Herewith to save you time I will just enonce my two problems:
Is the code correct?
Could someone tell me if such a wsdl link is just a definition of webservices or it is also a service's endpoint?
Normally to execute manually\per clicks this services on the weppage
http://almdemo.polarion.com/polarion, you have to login!
So how do I send a message in matlab which first log me in? Or must such a service be introduced into that wsdl for me to do it?? Could you be kind enough to write how it must be defined, because I don't really
write wsdl files, but I shall learn!**
I will be really thankful for your help and I wish you a happy week(-end) guys(& girls)!!!
Regards
Chrysmac
ps: I tried to use Soapui and gave that webpage as endpoint, but the toool crashes each time I enter my credentials! Maybe because of the dataload!??