Secure a java embedded web service with javax.jws without application server
I wrote the following code to implement a Java web service that communicates with an application written in another language on the same host:
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name开发者_开发知识库 = "MyWebService")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class MyWebService {
@WebMethod(operationName = "methodName", action = "urn:#methodName")
@WebResult(name = "result", partName = "output")
public String methodName(@WebParam(name = "param1", partName = "input") String param1,
@WebParam(name = "param2", partName = "input") String param2){
// ...do something
return "You called this service with params: " + param1 + "," + param2;
}
Since requirements are not to use an application server to expose the web service I instantiated the service from another class as follows:
Endpoint endpoint = Endpoint.create(new MyWebService());
URL url = new URL("http://localhost:7777/MyWebService");
endpoint.publish(url.toString());
Questions:
1) Which is the simplest way to secure this service with username and password considering the architecture of this project? Any code sample would be greatly appreciated.
2) I made some research and found the use of SOAPHandler and I think it would work for me. In the case of using the SOAPHandler class how do I add headers to the message to require authentication from the client?
Thank you in advance
thanks so much for the response that's the direction I'm following too but
when I check any of the headers for example:
SOAPHeader header = soapContext.getMessage().getSOAPPart().getEnvelope().getHeader();
Iterator<SOAPElement> iterator = header.getAllAttributes();
I get a nullpointer exception...any ideas?
I did a working program. Just to add to what you already found out, following is a way to use handler
Endpoint endpoint = Endpoint.create(new MyWebService());
Binding binding = endpoint.getBinding();
List<Handler> handlerChain = new ArrayList<Handler>(1);
handlerChain.add(new MyHandler());
binding.setHandlerChain(handlerChain);
URL url = new URL("http://localhost:7777/MyWebService");
endpoint.publish(url.toString());
MyHandler
is class extending Handler
interface. Alternately, you can use @HandlerChain
annotation which will need an xml configuration file for handlers. Configure this for incoming messages only
public class MyHandler implements SOAPHandler{
@Override
public Set<?> getHeaders() {
// TODO Auto-generated method stub
return null;
}
@Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
@Override
public boolean handleFault(MessageContext context) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean handleMessage(MessageContext context) {
System.out.println("Hehehe the handler");
SOAPMessageContext soapContext = (SOAPMessageContext)context;
try {
SOAPHeader header = soapContext.getMessage().getSOAPPart().getEnvelope().getHeader();
//Check there if the required data (username/password) is present in header or not and return true/false accordingly.
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
From the client side also, if your client is using JAB-WS, you will have to use client handlers. Following is a typical JAX-WS client invocation example
Dispatch<Source> dispatch = … create a Dispatch<Source>
dispatch.getBinding().setHandlerChain(chain)
Source request = … create a Source object
Source response = dispatch.invoke(request);
Here the handler in chain will add header to outgoing request. Configure this for Outgoing messages only.
What you did is fair enough.
Concerning the authentication you can just expose a method for passing user name and password as login credentials.
Once the user has provided the correct credentials the user has been authenticated.
Note: Now you must maintain session data and make sure that an incoming request is from an authenticated user. The Endpoint
just deploys internally a lightweight http server. You must design you web service implementation to keep "state" among requests.
You have 2 more options.
- Do the authentication at the SOAP level. I would not really recomend
it. But if you do, note that the
Endpoint
does not deploy aWSDL
. So you must communicate exactly to the client connecting, theSOAP
header you expect. It is possible though to write aWSDL
by yourself and "attach" it to theEndpoint
. - Do the authentication at the http request level. I.e. add a token or
cookie to the http request. To be honest I do not remember if this
is easy using the
Endpoint
精彩评论