org.apache.ws.security.message.token.Timestamp Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wss4j Show documentation
Show all versions of wss4j Show documentation
The Apache WSS4J project provides a Java implementation of the primary security standards
for Web Services, namely the OASIS Web Services Security (WS-Security) specifications
from the OASIS Web Services Security TC.
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.ws.security.message.token;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.util.DOM2Writer;
import org.apache.ws.security.util.DateUtil;
import org.apache.ws.security.util.WSCurrentTimeSource;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.security.util.WSTimeSource;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
/**
* Timestamp according to SOAP Message Security 1.0,
* chapter 10 / appendix A.2
*
* @author Christof Soehngen ([email protected])
*/
public class Timestamp {
private static final org.apache.commons.logging.Log LOG =
org.apache.commons.logging.LogFactory.getLog(Timestamp.class);
protected Element element = null;
protected List customElements = null;
protected Date createdDate;
protected Date expiresDate;
/**
* Constructs a Timestamp
object and parses the
* wsu:Timestamp
element to initialize it.
*
* @param timestampElement the wsu:Timestamp
element that
* contains the timestamp data
*/
public Timestamp(Element timestampElement) throws WSSecurityException {
this(timestampElement, true);
}
/**
* Constructs a Timestamp
object and parses the
* wsu:Timestamp
element to initialize it.
*
* @param timestampElement the wsu:Timestamp
element that
* contains the timestamp data
* @param bspCompliant whether the Timestamp processing complies with the BSP spec
*/
public Timestamp(Element timestampElement, boolean bspCompliant) throws WSSecurityException {
element = timestampElement;
customElements = new ArrayList();
String strCreated = null;
String strExpires = null;
for (Node currentChild = element.getFirstChild();
currentChild != null;
currentChild = currentChild.getNextSibling()
) {
if (Node.ELEMENT_NODE == currentChild.getNodeType()) {
Element currentChildElement = (Element) currentChild;
if (WSConstants.CREATED_LN.equals(currentChild.getLocalName()) &&
WSConstants.WSU_NS.equals(currentChild.getNamespaceURI())) {
if (strCreated == null) {
String valueType = currentChildElement.getAttributeNS(null, "ValueType");
if (bspCompliant && valueType != null && !"".equals(valueType)) {
// We can't have a ValueType attribute as per the BSP spec
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
);
}
strCreated = ((Text)currentChildElement.getFirstChild()).getData();
} else {
// Test for multiple Created elements
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
);
}
} else if (WSConstants.EXPIRES_LN.equals(currentChild.getLocalName()) &&
WSConstants.WSU_NS.equals(currentChild.getNamespaceURI())) {
if (strExpires != null || (bspCompliant && strCreated == null)) {
//
// Created must appear before Expires and we can't have multiple Expires
// elements
//
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
);
} else {
String valueType = currentChildElement.getAttributeNS(null, "ValueType");
if (bspCompliant && valueType != null && !"".equals(valueType)) {
// We can't have a ValueType attribute as per the BSP spec
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
);
}
strExpires = ((Text)currentChildElement.getFirstChild()).getData();
}
} else {
if (bspCompliant) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
);
}
customElements.add(currentChildElement);
}
}
}
// We must have a Created element
if (bspCompliant && strCreated == null) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
);
}
// Parse the dates
DateFormat zulu = new XmlSchemaDateFormat();
if (bspCompliant) {
zulu.setLenient(false);
}
try {
if (LOG.isDebugEnabled()) {
LOG.debug("Current time: " + zulu.format(new Date()));
}
if (strCreated != null) {
createdDate = zulu.parse(strCreated);
if (LOG.isDebugEnabled()) {
LOG.debug("Timestamp created: " + zulu.format(createdDate));
}
}
if (strExpires != null) {
expiresDate = zulu.parse(strExpires);
if (LOG.isDebugEnabled()) {
LOG.debug("Timestamp expires: " + zulu.format(expiresDate));
}
}
} catch (ParseException e) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY, "invalidTimestamp", null, e
);
}
}
/**
* Constructs a Timestamp
object according
* to the defined parameters.
*
* @param doc the SOAP envelope as Document
* @param ttl the time to live (validity of the security semantics) in seconds
*/
public Timestamp(boolean milliseconds, Document doc, int ttl) {
this(milliseconds, doc, new WSCurrentTimeSource(), ttl);
}
/**
* Constructs a Timestamp
object according
* to the defined parameters.
*
* @param doc the SOAP envelope as Document
* @param ttl the time to live (validity of the security semantics) in seconds
*/
public Timestamp(boolean milliseconds, Document doc, WSTimeSource timeSource, int ttl) {
customElements = new ArrayList();
element =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
);
DateFormat zulu = null;
if (milliseconds) {
zulu = new XmlSchemaDateFormat();
} else {
zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
}
Element elementCreated =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
);
createdDate = timeSource.now();
elementCreated.appendChild(doc.createTextNode(zulu.format(createdDate)));
element.appendChild(elementCreated);
if (ttl != 0) {
expiresDate = timeSource.now();
expiresDate.setTime(createdDate.getTime() + ((long)ttl * 1000L));
Element elementExpires =
doc.createElementNS(
WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
);
elementExpires.appendChild(doc.createTextNode(zulu.format(expiresDate)));
element.appendChild(elementExpires);
}
}
/**
* Add the WSU Namespace to this T. The namespace is not added by default for
* efficiency purposes.
*/
public void addWSUNamespace() {
WSSecurityUtil.setNamespace(element, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
}
/**
* Returns the dom element of this Timestamp
object.
*
* @return the wsse:UsernameToken
element
*/
public Element getElement() {
return element;
}
/**
* Returns the string representation of the token.
*
* @return a XML string representation
*/
public String toString() {
return DOM2Writer.nodeToString((Node) element);
}
/**
* Get the time of creation.
*
* @return the "created" time
*/
public Date getCreated() {
return createdDate;
}
/**
* Get the time of expiration.
*
* @return the "expires" time
*/
public Date getExpires() {
return expiresDate;
}
/**
* Creates and adds a custom element to this Timestamp
*/
public void addCustomElement(Document doc, Element customElement) {
customElements.add(customElement);
element.appendChild(customElement);
}
/**
* Get the the custom elements from this Timestamp
*
* @return the list containing the custom elements.
*/
public List getCustomElements() {
return customElements;
}
/**
* Set wsu:Id attribute of this timestamp
* @param id
*/
public void setID(String id) {
element.setAttributeNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":Id", id);
}
/**
* @return the value of the wsu:Id attribute
*/
public String getID() {
return element.getAttributeNS(WSConstants.WSU_NS, "Id");
}
/**
* Return true if the current Timestamp is expired, meaning if the "Expires" value
* is before the current time. It returns false if there is no Expires value.
*/
public boolean isExpired() {
if (expiresDate != null) {
Date rightNow = new Date();
return expiresDate.before(rightNow);
}
return false;
}
/**
* Return true if the "Created" value is before the current time minus the timeToLive
* argument, and if the Created value is not "in the future".
*
* @param timeToLive the value in seconds for the validity of the Created time
* @param futureTimeToLive the value in seconds for the future validity of the Created time
* @return true if the timestamp is before (now-timeToLive), false otherwise
*/
public boolean verifyCreated(
int timeToLive,
int futureTimeToLive
) {
return DateUtil.verifyCreated(createdDate, timeToLive, futureTimeToLive);
}
@Override
public int hashCode() {
int result = 17;
if (createdDate != null) {
result = 31 * result + createdDate.hashCode();
}
if (expiresDate != null) {
result = 31 * result + expiresDate.hashCode();
}
return result;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof Timestamp)) {
return false;
}
Timestamp timestamp = (Timestamp)object;
if (!compare(timestamp.getCreated(), getCreated())) {
return false;
}
if (!compare(timestamp.getExpires(), getExpires())) {
return false;
}
return true;
}
private boolean compare(Date item1, Date item2) {
if (item1 == null && item2 != null) {
return false;
} else if (item1 != null && !item1.equals(item2)) {
return false;
}
return true;
}
}