开发者

Secure a java embedded web service with javax.jws without application server

开发者 https://www.devze.com 2023-04-05 14:25 出处:网络
I wrote the following code to implement a Java web service that communicates with an application written in another language on the same host:

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.

  1. Do the authentication at the SOAP level. I would not really recomend it. But if you do, note that the Endpoint does not deploy a WSDL. So you must communicate exactly to the client connecting, the SOAP header you expect. It is possible though to write a WSDL by yourself and "attach" it to the Endpoint.
  2. 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
0

精彩评论

暂无评论...
验证码 换一张
取 消