简体   繁体   中英

How to authenticate soap based java web services?

I am developing Soap based web services using Java. Can anyone please let me know how to authenticate the client who is consuming the web services?

Thanks.

Different ways and different types of security we can implement: Message-level security

  • Transport-level security : Such as HTTP Basic/Digest and SSL
  • Message level security : Such as WS-Security, XML digital signature, XML Encryption,XKMS ( X ML K ey M anagement S pecification), XACML (e X tensible A ccess C ontrol M arkup L anguage), SAML ( S ecure A ssertion M arkup L anguage), ebXML Message Service, The Liberty Alliance Project. for more detals
  • Access control security :A security role is a privilege granted to users or groups based on specific conditions.

Most commonly we use WS-Security for SOAP Web Services. A WS-security profile determines how WS-security is enabled.

  1. WSS X.509 Token Profile: Use the X.509 framework for a WSS X.509 security profile.
  2. WSS UsernameToken Profile : When specifying the X.509 Token Profile, you can also supply a UsernameToken in the SOAP request.

example:

<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-6138db82-5a4c-4bf7-915f-af7a10d9ae96">
  <wsse:Username>user</wsse:Username>
  <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">CBb7a2itQDgxVkqYnFtggUxtuqk=</wsse:Password>
  <wsse:Nonce>5ABcqPZWb6ImI2E6tob8MQ==</wsse:Nonce>
  <wsu:Created>2010-06-08T07:26:50Z</wsu:Created>
</wsse:UsernameToken>

The above element includes into SOAP header as follows:

SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
    SOAPHeader header = envelope.addHeader();
    SOAPElement security = header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
    SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
    SOAPElement username = usernameToken.addChildElement("Username", "wsse");
    username.addTextNode(user);

    SOAPElement password = usernameToken.addChildElement("Password", "wsse");
    password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
    password.addTextNode(encodedPass); //encodedPass = Base64 ( SHA-1 ( nonce + created + password ) )

    SOAPElement nonce =
        usernameToken.addChildElement("Nonce", "wsse");
    nonce.addTextNode(Base64.encodeBytes(nonceString.getBytes()));

    SOAPElement created = usernameToken.addChildElement("Created", "wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

    created.addTextNode(creatTime);

The following example is simple adding user and password to HTTP header only.

Application Authentication with JAX-WS using WebServiceContext interface

WebServiceImpl.java

package com.javacodegeeks.enterprise.ws;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(endpointInterface = "com.javacodegeeks.enterprise.ws.WebServiceInterface")
public class WebServiceImpl implements WebServiceInterface {

    @Resource
    WebServiceContext webServiceContext;

    @Override
    public String getHelloWorldAsString(String str) {

        MessageContext messageContext = webServiceContext.getMessageContext();

        // get request headers
        Map<?,?> requestHeaders = (Map<?,?>) messageContext.get(MessageContext.HTTP_REQUEST_HEADERS);
        List<?> usernameList = (List<?>) requestHeaders.get("username");
        List<?> passwordList = (List<?>) requestHeaders.get("password");

        String username = "";
        String password = "";

        if (usernameList != null) {
            username = usernameList.get(0).toString();
        }

        if (passwordList != null) {
            password = passwordList.get(0).toString();
        }

                // of course this is not real validation
                // you should validate your users from stored databases credentials
        if (username.equals("nikos") && password.equals("superpassword")) {

            return "Valid User :"+str;

        } else {

            return "Unknown User!";
        }
    }
}

WebServiceClient.java

package com.javacodegeeks.enterprise.ws.client;

import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import com.javacodegeeks.enterprise.ws.WebServiceInterface;

public class WebServiceClient{

    public static void main(String[] args) throws Exception {

        URL wsdlUrl = new URL("http://localhost:8888/webservice/helloworld?wsdl");    
        //qualifier name ...
        QName qname = new QName("http://ws.enterprise.javacodegeeks.com/", "WebServiceImplService");
         Service service = Service.create(wsdlUrl, qname);

        WebServiceInterface sayHello = service.getPort(WebServiceInterface.class);
        Map<String, Object> requestContext = ((BindingProvider)sayHello).getRequestContext();

        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8888/webservice/helloworld?wsdl");

        Map<String, List<String>> requestHeaders = new HashMap<String, List<String>>();
        requestHeaders.put("username", Collections.singletonList("nikos"));
        requestHeaders.put("Password", Collections.singletonList("superpassword"));
        requestContext.put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);

        System.out.println(sayHello.getHelloWorldAsString("- This is Java Code Geeks"));

    }
}

Probably the best but most complex is WS-Security with various authentication method. But it is most complex and its good for enterprise enviroment. It allows you to create end-to-end auth and there are lots of options. You can in simple case eg use Web Services Security UsernameToken Profile

    <S12:Envelope xmlns:S11="..." xmlns:wsse="..." xmlns:wsu= "...">
  <S12:Header>
  ...
    <wsse:Security>
      <wsse:UsernameToken>
        <wsse:Username>NNK</wsse:Username>
        <wsse:Password Type="...#PasswordDigest">weYI3nXd8LjMNVksCKFV8t3rgHh3Rw==</wsse:Password>
        <wsse:Nonce>WScqanjCEAC4mQoBE07sAQ==</wsse:Nonce>
        <wsu:Created>2003-07-16T01:24:32</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
  ...
  </S12:Header>
...
</S12:Envelope>

I don't know what library you use, but here is a nice article how to install Rampart into Axis2 and implement UsernameToken handling .

But in some, simplified cases you can simply make HTTP Basic Authentication to web server (through SSL). This may be worst solution but sometimes could be easiest to implement. Another solution, not connected with soap can be mutual authenticated SSL (with client auth).

WS-Security provides the standard way to secure SOAP based web services and WS-Security Policy says how to communicate those security requirements to out side world.

Authentication can be with username/password - with UsernameToken or certificate based.

Since you are Java based - you can use the open source WSO2 Application Server to deploy your service and with few clicks you can secure your service.

This further explains how to do it...

Thanks...

Here is a good example for a Webservice via JAX-WS with authentification

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM