WS-Security (Web Services Security, short WSS) is a flexible and feature-rich extension to SOAP to apply security to web services. It is a member of the WS-* family of web service specifications and was published by OASIS.
The protocol specifies how integrity and confidentiality can be enforced on messages and allows the communication of various security token formats. Its main focus is the use of XML Signature and XML Encryption to provide end-to-end security.
The specification allows a variety of signature formats, encryption algorithms and multiple trust domains, and is open to various security token models, such as:
- X.509 certificates,
- Kerberos tickets,
- UserID/Password credentials,
- SAML Assertions, and
- custom-defined tokens.
WS-Security incorporates security features in the header of a SOAP message. Below is a sample program on how to incorporate ws-security in SOAP message header. I am using the UserID/Password credentials.
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
public class WebservicesSecurityService {
public static final String SECURITY = "Security";
public static final String WSSE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
public static final String WSSE_PREFIX = "wsse";
public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
public static final String WSU_PREFIX = "wsu";
public static final String PAL_NS = "http://palin.com";
public static final String PAL_PREFIX = "pal";
public static final String PASSWORD_TEXT_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
public static final String ENCODING_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary";
public static final String USERNAME = "UserName";
public static final String PASSWORD = "Password";
public static final String WEBSERVICE_URL = "http://localhost:8080/axis2/services/PalinServ?wsdl";
public static Object makeRequest(int xml) throws IOException, SOAPException, Exception{
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPBody soapBody = soapEnvelope.getBody();
soapEnvelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
soapEnvelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
soapEnvelope.addNamespaceDeclaration("soap", "http://www.w3.org/2003/05/soap-envelope");
soapEnvelope.addNamespaceDeclaration(PAL_PREFIX, PAL_NS);
SOAPHeader soapHeader = soapMessage.getSOAPHeader();
if (soapHeader == null)
soapHeader = soapEnvelope.addHeader();
SOAPHeaderElement elHeader = soapHeader.addHeaderElement(
soapEnvelope.createName("Security", WSSE_PREFIX, WSSE_NS));
elHeader.setMustUnderstand(false);
Name usernameNameToken = soapEnvelope.createName("UsernameToken", WSSE_PREFIX, WSSE_NS);
SOAPElement elUnToken = elHeader.addChildElement(usernameNameToken);
elUnToken.setAttribute("wsu:Id","UsernameToken-2");
elUnToken.setAttribute("xmlns:wsu", WSU_NS);
Name usernameName = soapEnvelope.createName("Username", WSSE_PREFIX, WSSE_NS);
SOAPElement usernameMsgElem = soapFactory.createElement(usernameName);
usernameMsgElem.addTextNode(USERNAME);
elUnToken.addChildElement(usernameMsgElem);
Name passwordName = soapEnvelope.createName("Type", WSSE_PREFIX, WSSE_NS);
SOAPElement passwordMsgElem = soapFactory.createElement("Password", WSSE_PREFIX, WSSE_NS);
passwordMsgElem.addAttribute(passwordName, PASSWORD_TEXT_TYPE);
passwordMsgElem.addTextNode(PASSWORD);
elUnToken.addChildElement(passwordMsgElem);
Name nonceName = soapEnvelope.createName("EncodingType", WSSE_PREFIX, WSSE_NS);
SOAPElement nonceMsgElem = soapFactory.createElement("Nonce", WSSE_PREFIX, WSSE_NS);
nonceMsgElem.addAttribute(nonceName, ENCODING_TYPE);
nonceMsgElem.addTextNode("u6r/JZ+Y73epyvmENjBeZQ==");
elUnToken.addChildElement(nonceMsgElem);
SOAPElement createdElem = elUnToken.addChildElement("Created", WSU_PREFIX , WSU_NS);
createdElem.addTextNode(String.valueOf(new Date()));
soapBody.addChildElement(WebservicesSecurityService.makeOperation(xml));
soapBody.addChildElement(WebservicesSecurityService.makeOperation(xml));
soapMessage.writeTo(System.out);
return soapMessage;
}
public static void callService() throws IOException, Exception {
SOAPMessage soapMessageRequest = (SOAPMessage) WebservicesSecurityService.makeRequest(12321);
SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
SOAPConnection connection = sfc.createConnection();
URL endpoint = new URL(WEBSERVICE_URL);
SOAPMessage soapMessageResponse = connection.call(soapMessageRequest, endpoint);
soapMessageResponse.writeTo(System.out);
connection.close();
}
public static SOAPElement makeOperation(int number) throws SOAPException{
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPElement isPalin = soapFactory.createElement("isPalindrome", PAL_PREFIX, PAL_NS);
SOAPElement args = isPalin.addChildElement("args0", PAL_PREFIX, PAL_NS);
args.addTextNode(String.valueOf(number));
return isPalin;
}
public static void main(String[] args) {
try {
WebservicesSecurityService.callService();
} catch (Exception e) {
e.printStackTrace();
}
}
}
This is how the generated security request looks:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:pal="http://palin.com" xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="0">
<wsse:UsernameToken
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="UsernameToken-2">
<wsse:Username>UserName</wsse:Username>
<wsse:Password
wsse:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Password</wsse:Password>
<wsse:Nonce
wsse:EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">u6r/JZ+Y73epyvmENjBeZQ==</wsse:Nonce>
<wsu:Created>Fri Sep 28 17:45:38 CDT 2012</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<pal:isPalindrome>
<pal:args0>12321</pal:args0>
</pal:isPalindrome>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>