Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding elements in SOAP Header request for authentication

I need to incorporate an authentication header (i.e. as a part of SOAP header request) in my new web service. That authentication header will verify the userId and password details. I have to verify the content of request header details for authentication in my Web Service. If authenticated, then the SOAP body of the request will be processed, else Invalid Authentication message will be send back by the Web Service to the client application invoking the service.

I am not able to understand how to create a web service where the SOAP Header will contain some elements(in my case, authentication elements such as userId and password).

Normally, whatever method exposed in the service will come as a part of the SOAP Body. Hence confused how to proceed with adding authentication elements in the SOAP Header.

Please help

Regards,

like image 447
user182944 Avatar asked Sep 05 '12 15:09

user182944


People also ask

How do you provide authentication for SOAP Web services?

The basic authentication is encoded in the HTTP request that carries the SOAP message. When the application server receives the HTTP request, the user name and password are retrieved and verified using the authentication mechanism specific to the server. Use transport-level security to enable basic authentication.

How do I pass a user ID and password in SOAP header?

ClientCridentials. UserName. Password = "testPass"; In this way you can pass username, password in the header to a SOAP WCF Service.


1 Answers

Recently I have wrote a class which adds user credentials to SOAP header. To do that you need to create a class which implements SOAPHandler<SOAPMessageContext> interface. For e.g.:

public class MyHandler implements SOAPHandler<SOAPMessageContext> {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class);

    private String username;

    private String password;

    /**
     * Handles SOAP message. If SOAP header does not already exist, then method will created new SOAP header. The
     * username and password is added to the header as the credentials to authenticate user. If no user credentials is
     * specified every call to web service will fail.
     *
     * @param context SOAP message context to get SOAP message from
     * @return true
     */
    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        try {
            SOAPMessage message = context.getMessage();
            SOAPHeader header = message.getSOAPHeader();
            SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
            if (header == null) {
                header = envelope.addHeader();
            }
            QName qNameUserCredentials = new QName("https://your.target.namespace/", "UserCredentials");
            SOAPHeaderElement userCredentials = header.addHeaderElement(qNameUserCredentials);

            QName qNameUsername = new QName("https://your.target.namespace/", "Username");
            SOAPHeaderElement username = header.addHeaderElement(qNameUsername );
            username.addTextNode(this.username);
            QName qNamePassword = new QName("https://your.target.namespace/", "Password");
            SOAPHeaderElement password = header.addHeaderElement(qNamePassword);
            password.addTextNode(this.password);

            userCredentials.addChildElement(username);
            userCredentials.addChildElement(password);

            message.saveChanges();
            //TODO: remove this writer when the testing is finished
            StringWriter writer = new StringWriter();
            message.writeTo(new StringOutputStream(writer));
            LOGGER.debug("SOAP message: \n" + writer.toString());
        } catch (SOAPException e) {
            LOGGER.error("Error occurred while adding credentials to SOAP header.", e);
        } catch (IOException e) {
            LOGGER.error("Error occurred while writing message to output stream.", e);
        }
        return true;
    }

    //TODO: remove this class after testing is finished
    private static class StringOutputStream extends OutputStream {

        private StringWriter writer;

        public StringOutputStream(StringWriter writer) {
            this.writer = writer;
        }

        @Override
        public void write(int b) throws IOException {
            writer.write(b);
        }
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        LOGGER.debug("handleFault has been invoked.");
        return true;
    }

    @Override
    public void close(MessageContext context) {
        LOGGER.debug("close has been invoked.");
    }

    @Override
    public Set<QName> getHeaders() {
        LOGGER.debug("getHeaders has been invoked.");
        return null;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Note that I am just adding the credentials to the header and returning true. You do what ever you want with whole message and return false if something that is expected fails.

I have implemented this one the client:

<bean id="soapHandler" class="your.package.MyHandler">
    <property name="username" value="testUser"/>
    <property name="password" value="testPassword"/>
</bean>

<jaxws:client "...">
    <jaxws:handlers>
        <ref bean="soapHandler"/>
    </jaxws:handlers>
</jaxws:client>

But it also can be implemented on the endpoint.

like image 71
Paulius Matulionis Avatar answered Sep 23 '22 14:09

Paulius Matulionis