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 w开发者_运维知识库ho 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 (XML Key Management Specification), XACML (eXtensible Access Control Markup Language), SAML (Secure Assertion Markup Language), 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.
- WSS X.509 Token Profile: Use the X.509 framework for a WSS X.509 security profile.
- 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 Here’s a detail example to show you how to handle application level authentication with JAX-WS.
- Container Authentication with JAX-WS + (Tomcat version) Here’s a detail example to show you how to implement container authentication with JAX-WS, under Tomcat.
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 e.g. 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
精彩评论