You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2011/10/04 14:00:43 UTC
svn commit: r1178763 - in
/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security:
SecurityConstants.java
policy/interceptors/IssuedTokenInterceptorProvider.java
trust/STSClient.java trust/delegation/WSSUsernameCallbackHandler.java
Author: coheigea
Date: Tue Oct 4 12:00:43 2011
New Revision: 1178763
URL: http://svn.apache.org/viewvc?rev=1178763&view=rev
Log:
Added the ability to use the STSClient in an intermediary.
- There is a new configuration property to disable storing issued tokens per exchange
- Caching is enabled for OnBehalfOf or ActAs tokens
Conflicts:
rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java
Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java?rev=1178763&r1=1178762&r2=1178763&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java Tue Oct 4 12:00:43 2011
@@ -112,6 +112,14 @@ public final class SecurityConstants {
public static final String KERBEROS_CLIENT = "ws-security.kerberos.client";
+ /**
+ * Set this to "false" to not cache a SecurityToken per proxy object in the
+ * IssuedTokenInterceptorProvider. This should be done if a token is being retrieved
+ * from an STS in an intermediary. The default value is "true".
+ */
+ public static final String CACHE_ISSUED_TOKEN_IN_ENDPOINT =
+ "ws-security.cache.issued.token.in.endpoint";
+
public static final Set<String> ALL_PROPERTIES;
static {
@@ -125,7 +133,7 @@ public final class SecurityConstants {
SAML1_TOKEN_VALIDATOR, SAML2_TOKEN_VALIDATOR, TIMESTAMP_TOKEN_VALIDATOR,
SIGNATURE_TOKEN_VALIDATOR, IS_BSP_COMPLIANT, TIMESTAMP_FUTURE_TTL,
BST_TOKEN_VALIDATOR, SAML_CALLBACK_HANDLER, STS_TOKEN_ON_BEHALF_OF,
- KERBEROS_CLIENT, SCT_TOKEN_VALIDATOR
+ KERBEROS_CLIENT, SCT_TOKEN_VALIDATOR, CACHE_ISSUED_TOKEN_IN_ENDPOINT
}));
ALL_PROPERTIES = Collections.unmodifiableSet(s);
}
Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java?rev=1178763&r1=1178762&r2=1178763&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java Tue Oct 4 12:00:43 2011
@@ -25,11 +25,15 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
+
+import org.w3c.dom.Element;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.EndpointInfo;
@@ -65,6 +69,9 @@ import org.apache.ws.security.util.WSSec
*
*/
public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorProvider {
+
+ private static final String ASSOCIATED_TOKEN =
+ IssuedTokenInterceptorProvider.class.getName() + "-" + "Associated_Token";
public IssuedTokenInterceptorProvider() {
super(Arrays.asList(SP11Constants.ISSUED_TOKEN, SP12Constants.ISSUED_TOKEN));
@@ -124,13 +131,7 @@ public class IssuedTokenInterceptorProvi
if (isRequestor(message)) {
IssuedToken itok = (IssuedToken)ais.iterator().next().getAssertion();
- SecurityToken tok = (SecurityToken)message.getContextualProperty(SecurityConstants.TOKEN);
- if (tok == null) {
- String tokId = (String)message.getContextualProperty(SecurityConstants.TOKEN_ID);
- if (tokId != null) {
- tok = getTokenStore(message).getToken(tokId);
- }
- }
+ SecurityToken tok = retrieveCachedToken(message);
if (tok == null) {
STSClient client = STSUtils.getClient(message, "sts", itok);
AddressingProperties maps =
@@ -156,22 +157,28 @@ public class IssuedTokenInterceptorProvi
Map<String, Object> ctx = client.getRequestContext();
mapSecurityProps(message, ctx);
+ Object o = message.getContextualProperty(SecurityConstants.STS_APPLIES_TO);
+ String appliesTo = o == null ? null : o.toString();
+ appliesTo = appliesTo == null
+ ? message.getContextualProperty(Message.ENDPOINT_ADDRESS).toString()
+ : appliesTo;
+ boolean enableAppliesTo = client.isEnableAppliesTo();
+
client.setMessage(message);
- client.setTrust(getTrust10(aim));
- client.setTrust(getTrust13(aim));
- client.setTemplate(itok.getRstTemplate());
- if (maps == null) {
- tok = client.requestSecurityToken();
- } else {
- Object o = message
- .getContextualProperty(SecurityConstants.STS_APPLIES_TO);
- String s = o == null ? null : o.toString();
- s = s == null
- ? message.getContextualProperty(Message.ENDPOINT_ADDRESS).toString()
- : s;
- client.setAddressingNamespace(maps.getNamespaceURI());
- tok = client.requestSecurityToken(s);
+ Element onBehalfOfToken = client.getOnBehalfOfToken();
+ Element actAsToken = client.getActAsToken();
+
+ SecurityToken secToken =
+ handleDelegation(
+ message, onBehalfOfToken, actAsToken, appliesTo, enableAppliesTo
+ );
+ if (secToken == null) {
+ secToken = getTokenFromSTS(message, client, aim, maps, itok, appliesTo);
}
+ tok = secToken;
+ storeDelegationTokens(
+ message, tok, onBehalfOfToken, actAsToken, appliesTo, enableAppliesTo
+ );
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
@@ -190,10 +197,17 @@ public class IssuedTokenInterceptorProvi
for (AssertionInfo ai : ais) {
ai.setAsserted(true);
}
- message.getExchange().get(Endpoint.class).put(SecurityConstants.TOKEN_ID,
- tok.getId());
- message.getExchange().put(SecurityConstants.TOKEN_ID,
- tok.getId());
+ boolean cacheIssuedToken =
+ MessageUtils.getContextualBoolean(
+ message, SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, true
+ );
+ if (cacheIssuedToken) {
+ message.getExchange().get(Endpoint.class).put(SecurityConstants.TOKEN_ID,
+ tok.getId());
+ message.getExchange().put(SecurityConstants.TOKEN_ID, tok.getId());
+ } else {
+ message.put(SecurityConstants.TOKEN_ID, tok.getId());
+ }
getTokenStore(message).add(tok);
}
} else {
@@ -219,6 +233,156 @@ public class IssuedTokenInterceptorProvi
return (Trust13)ais.iterator().next().getAssertion();
}
+ private SecurityToken retrieveCachedToken(Message message) {
+ boolean cacheIssuedToken =
+ MessageUtils.getContextualBoolean(
+ message, SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, true
+ );
+ SecurityToken tok = null;
+ if (cacheIssuedToken) {
+ tok = (SecurityToken)message.getContextualProperty(SecurityConstants.TOKEN);
+ if (tok == null) {
+ String tokId = (String)message.getContextualProperty(SecurityConstants.TOKEN_ID);
+ if (tokId != null) {
+ tok = getTokenStore(message).getToken(tokId);
+ }
+ }
+ }
+ return tok;
+ }
+
+ /**
+ * Parse ActAs/OnBehalfOf appropriately. See if the required token is stored in the cache.
+ */
+ private SecurityToken handleDelegation(
+ Message message,
+ Element onBehalfOfToken,
+ Element actAsToken,
+ String appliesTo,
+ boolean enableAppliesTo
+ ) throws Exception {
+ TokenStore tokenStore = getTokenStore(message);
+ String key = appliesTo;
+ if (!enableAppliesTo || key == null || "".equals(key)) {
+ key = ASSOCIATED_TOKEN;
+ }
+ // See if the token corresponding to the OnBehalfOf Token is stored in the cache
+ // and if it points to an issued token
+ if (onBehalfOfToken != null) {
+ String id = getIdFromToken(onBehalfOfToken);
+ SecurityToken cachedToken = tokenStore.getToken(id);
+ if (cachedToken != null) {
+ Properties properties = cachedToken.getProperties();
+ if (properties != null && properties.containsKey(key)) {
+ String associatedToken = properties.getProperty(key);
+ SecurityToken issuedToken = tokenStore.getToken(associatedToken);
+ if (issuedToken != null) {
+ return issuedToken;
+ }
+ }
+ }
+ }
+
+ // See if the token corresponding to the ActAs Token is stored in the cache
+ // and if it points to an issued token
+ if (actAsToken != null) {
+ String id = getIdFromToken(actAsToken);
+ SecurityToken cachedToken = tokenStore.getToken(id);
+ if (cachedToken != null) {
+ Properties properties = cachedToken.getProperties();
+ if (properties != null && properties.containsKey(key)) {
+ String associatedToken = properties.getProperty(key);
+ SecurityToken issuedToken = tokenStore.getToken(associatedToken);
+ if (issuedToken != null) {
+ return issuedToken;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private String getIdFromToken(Element token) {
+ if (token != null) {
+ // Try to find the "Id" on the token.
+ if (token.hasAttributeNS(WSConstants.WSU_NS, "Id")) {
+ return token.getAttributeNS(WSConstants.WSU_NS, "Id");
+ } else if (token.hasAttributeNS(null, "ID")) {
+ return token.getAttributeNS(null, "ID");
+ } else if (token.hasAttributeNS(null, "AssertionID")) {
+ return token.getAttributeNS(null, "AssertionID");
+ }
+ }
+ return "";
+ }
+
+ private void storeDelegationTokens(
+ Message message,
+ SecurityToken issuedToken,
+ Element onBehalfOfToken,
+ Element actAsToken,
+ String appliesTo,
+ boolean enableAppliesTo
+ ) throws Exception {
+ if (issuedToken == null) {
+ return;
+ }
+ TokenStore tokenStore = getTokenStore(message);
+ String key = appliesTo;
+ if (!enableAppliesTo || key == null || "".equals(key)) {
+ key = ASSOCIATED_TOKEN;
+ }
+ if (onBehalfOfToken != null) {
+ String id = getIdFromToken(onBehalfOfToken);
+ SecurityToken cachedToken = tokenStore.getToken(id);
+ if (cachedToken == null) {
+ cachedToken = new SecurityToken(id);
+ cachedToken.setToken(onBehalfOfToken);
+ }
+ Properties properties = cachedToken.getProperties();
+ if (properties == null) {
+ properties = new Properties();
+ cachedToken.setProperties(properties);
+ }
+ properties.put(key, issuedToken.getId());
+ tokenStore.add(cachedToken);
+ }
+ if (actAsToken != null) {
+ String id = getIdFromToken(actAsToken);
+ SecurityToken cachedToken = tokenStore.getToken(id);
+ if (cachedToken == null) {
+ cachedToken = new SecurityToken(id);
+ cachedToken.setToken(actAsToken);
+ }
+ Properties properties = cachedToken.getProperties();
+ if (properties == null) {
+ properties = new Properties();
+ cachedToken.setProperties(properties);
+ }
+ properties.put(key, issuedToken.getId());
+ tokenStore.add(cachedToken);
+ }
+ }
+
+ private SecurityToken getTokenFromSTS(
+ Message message,
+ STSClient client,
+ AssertionInfoMap aim,
+ AddressingProperties maps,
+ IssuedToken itok,
+ String appliesTo
+ ) throws Exception {
+ client.setTrust(getTrust10(aim));
+ client.setTrust(getTrust13(aim));
+ client.setTemplate(itok.getRstTemplate());
+ if (maps == null) {
+ return client.requestSecurityToken();
+ } else {
+ client.setAddressingNamespace(maps.getNamespaceURI());
+ return client.requestSecurityToken(appliesTo);
+ }
+ }
+
}
static class IssuedTokenInInterceptor extends AbstractPhaseInterceptor<Message> {
Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java?rev=1178763&r1=1178762&r2=1178763&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSClient.java Tue Oct 4 12:00:43 2011
@@ -616,7 +616,12 @@ public class STSClient implements Config
if (enableAppliesTo) {
addAppliesTo(writer, appliesTo);
}
- addOnBehalfOf(writer);
+ Element onBehalfOfToken = getOnBehalfOfToken();
+ if (onBehalfOfToken != null) {
+ writer.writeStartElement("wst", "OnBehalfOf", namespace);
+ StaxUtils.copy(onBehalfOfToken, writer);
+ writer.writeEndElement();
+ }
if (sptt == null) {
addTokenType(writer);
}
@@ -651,8 +656,13 @@ public class STSClient implements Config
StaxUtils.copy(el, writer);
writer.writeEndElement();
}
-
- addActAs(writer);
+
+ Element actAsSecurityToken = getActAsToken();
+ if (actAsSecurityToken != null) {
+ writer.writeStartElement(STSUtils.WST_NS_08_02, "ActAs");
+ StaxUtils.copy(actAsSecurityToken, writer);
+ writer.writeEndElement();
+ }
writer.writeEndElement();
@@ -672,6 +682,42 @@ public class STSClient implements Config
return token;
}
+ /**
+ * Get the "OnBehalfOf" element to be sent to the STS.
+ */
+ public Element getOnBehalfOfToken() throws Exception {
+ return getDelegationSecurityToken(this.onBehalfOf);
+ }
+
+ /**
+ * Get the "ActAs" element to be sent to the STS.
+ */
+ public Element getActAsToken() throws Exception {
+ return getDelegationSecurityToken(this.actAs);
+ }
+
+ private Element getDelegationSecurityToken(Object delegationObject) throws Exception {
+ if (delegationObject != null) {
+ final boolean isString = delegationObject instanceof String;
+ final boolean isElement = delegationObject instanceof Element;
+ final boolean isCallbackHandler = delegationObject instanceof CallbackHandler;
+ if (isString || isElement || isCallbackHandler) {
+ if (isString) {
+ final Document doc =
+ DOMUtils.readXml(new StringReader((String) delegationObject));
+ return doc.getDocumentElement();
+ } else if (isElement) {
+ return (Element) delegationObject;
+ } else {
+ DelegationCallback callback = new DelegationCallback(message);
+ ((CallbackHandler)delegationObject).handle(new Callback[]{callback});
+ return callback.getToken();
+ }
+ }
+ }
+ return null;
+ }
+
private byte[] writeElementsForRSTSymmetricKey(W3CDOMStreamWriter writer,
boolean wroteKeySize) throws Exception {
byte[] requestorEntropy = null;
@@ -743,35 +789,6 @@ public class STSClient implements Config
writer.writeEndElement();
}
- private void addOnBehalfOf(W3CDOMStreamWriter writer) throws Exception {
- if (this.onBehalfOf != null) {
- final boolean isString = this.onBehalfOf instanceof String;
- final boolean isElement = this.onBehalfOf instanceof Element;
- final boolean isCallbackHandler = this.onBehalfOf instanceof CallbackHandler;
- if (isString || isElement || isCallbackHandler) {
- final Element tokenElement;
-
- if (isString) {
- final Document acAsDoc =
- DOMUtils.readXml(new StringReader((String) this.onBehalfOf));
- tokenElement = acAsDoc.getDocumentElement();
- } else if (isElement) {
- tokenElement = (Element)this.onBehalfOf;
- } else {
- DelegationCallback callback = new DelegationCallback(message);
- ((CallbackHandler)onBehalfOf).handle(new Callback[]{callback});
- tokenElement = callback.getToken();
- }
-
- if (tokenElement != null) {
- writer.writeStartElement("wst", "OnBehalfOf", namespace);
- StaxUtils.copy(tokenElement, writer);
- writer.writeEndElement();
- }
- }
- }
- }
-
private Element getDocumentElement(DOMSource ds) {
Node nd = ds.getNode();
if (nd instanceof Document) {
@@ -1081,35 +1098,6 @@ public class STSClient implements Config
}
}
- private void addActAs(W3CDOMStreamWriter writer) throws Exception {
- if (this.actAs != null) {
- final boolean isString = this.actAs instanceof String;
- final boolean isElement = this.actAs instanceof Element;
- final boolean isCallbackHandler = this.actAs instanceof CallbackHandler;
- if (isString || isElement || isCallbackHandler) {
- final Element tokenElement;
-
- if (isString) {
- final Document acAsDoc =
- DOMUtils.readXml(new StringReader((String) this.actAs));
- tokenElement = acAsDoc.getDocumentElement();
- } else if (isElement) {
- tokenElement = (Element) this.actAs;
- } else {
- DelegationCallback callback = new DelegationCallback(message);
- ((CallbackHandler)actAs).handle(new Callback[]{callback});
- tokenElement = callback.getToken();
- }
-
- if (tokenElement != null) {
- writer.writeStartElement(STSUtils.WST_NS_08_02, "ActAs");
- StaxUtils.copy(tokenElement, writer);
- writer.writeEndElement();
- }
- }
- }
- }
-
private SecurityToken createSecurityToken(Element el, byte[] requestorEntropy)
throws WSSecurityException {
Modified: cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java?rev=1178763&r1=1178762&r2=1178763&view=diff
==============================================================================
--- cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java (original)
+++ cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/delegation/WSSUsernameCallbackHandler.java Tue Oct 4 12:00:43 2011
@@ -26,13 +26,12 @@ import javax.security.auth.callback.Call
import javax.security.auth.callback.UnsupportedCallbackException;
import org.w3c.dom.Document;
-import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.message.Message;
import org.apache.cxf.ws.security.SecurityConstants;
-import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.token.UsernameToken;
/**
* This CallbackHandler implementation obtains a username via the jaxws property
@@ -58,8 +57,8 @@ public class WSSUsernameCallbackHandler
} else {
doc = DOMUtils.createDocument();
}
- Element token = createWSSEUsernameToken(username, doc);
- callback.setToken(token);
+ UsernameToken usernameToken = createWSSEUsernameToken(username, doc);
+ callback.setToken(usernameToken.getElement());
}
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
@@ -67,12 +66,14 @@ public class WSSUsernameCallbackHandler
}
}
- private Element createWSSEUsernameToken(String username, Document doc) {
- WSSecUsernameToken builder = new WSSecUsernameToken();
- builder.setPasswordType(null);
- builder.setUserInfo(username, null);
- builder.prepare(doc);
- return builder.getUsernameTokenElement();
+ private UsernameToken createWSSEUsernameToken(String username, Document doc) {
+ UsernameToken usernameToken = new UsernameToken(true, doc, null);
+ usernameToken.setName(username);
+ usernameToken.addWSUNamespace();
+ usernameToken.addWSSENamespace();
+ usernameToken.setID("id-" + username);
+
+ return usernameToken;
}
}