Author: coheigea
Date: Fri Sep 30 09:28:25 2011
New Revision: 1177564
URL: http://svn.apache.org/viewvc?rev=1177564&view=rev
Log:
[CXF-3835] - SAML and Username tokens should be cached in the STS service
- Patch applied, thanks
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/DefaultInMemoryTokenStore.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/HazelCastTokenStore.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/DefaultInMemoryTokenStore.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/DefaultInMemoryTokenStore.java?rev=1177564&r1=1177563&r2=1177564&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/DefaultInMemoryTokenStore.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/DefaultInMemoryTokenStore.java
Fri Sep 30 09:28:25 2011
@@ -20,6 +20,7 @@
package org.apache.cxf.sts.cache;
import java.util.Collection;
+import java.util.Iterator;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
@@ -102,7 +103,14 @@ public class DefaultInMemoryTokenStore i
}
public SecurityToken getTokenByAssociatedHash(int hashCode) {
- // TODO Auto-generated method stub
+ @SuppressWarnings("unchecked")
+ Iterator<String> ids = cache.getKeys().iterator();
+ while (ids.hasNext()) {
+ SecurityToken securityToken = getToken(ids.next());
+ if (hashCode == securityToken.getAssociatedHash()) {
+ return securityToken;
+ }
+ }
return null;
}
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/HazelCastTokenStore.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/HazelCastTokenStore.java?rev=1177564&r1=1177563&r2=1177564&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/HazelCastTokenStore.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/cache/HazelCastTokenStore.java
Fri Sep 30 09:28:25 2011
@@ -20,6 +20,7 @@
package org.apache.cxf.sts.cache;
import java.util.Collection;
+import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import com.hazelcast.core.Hazelcast;
@@ -90,7 +91,13 @@ public class HazelCastTokenStore impleme
}
public SecurityToken getTokenByAssociatedHash(int hashCode) {
- // TODO Auto-generated method stub
+ Iterator<Object> ids = cacheMap.keySet().iterator();
+ while (ids.hasNext()) {
+ SecurityToken securityToken = getToken((String)ids.next());
+ if (hashCode == securityToken.getAssociatedHash()) {
+ return securityToken;
+ }
+ }
return null;
}
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java?rev=1177564&r1=1177563&r2=1177564&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/SAMLTokenProvider.java
Fri Sep 30 09:28:25 2011
@@ -20,6 +20,7 @@
package org.apache.cxf.sts.token.provider;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -37,6 +38,7 @@ import org.apache.cxf.sts.request.KeyReq
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.sts.token.realm.SAMLRealm;
import org.apache.cxf.ws.security.sts.provider.STSException;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
@@ -114,6 +116,20 @@ public class SAMLTokenProvider implement
AssertionWrapper assertion = createSamlToken(tokenParameters,
secret, doc);
Element token = assertion.toDOM(doc);
+ // set the token in cache
+ if (tokenParameters.getTokenStore() != null) {
+ SecurityToken securityToken = new
SecurityToken(assertion.getId());
+ securityToken.setToken(token);
+ int hash = 0;
+ byte[] signatureValue = assertion.getSignatureValue();
+ if (signatureValue != null && signatureValue.length > 0) {
+ hash = Arrays.hashCode(signatureValue);
+ securityToken.setAssociatedHash(hash);
+ }
+ Integer timeToLive = (int)(conditionsProvider.getLifetime() *
1000);
+ tokenParameters.getTokenStore().add(securityToken, timeToLive);
+ }
+
TokenProviderResponse response = new TokenProviderResponse();
response.setToken(token);
String tokenType = tokenRequirements.getTokenType();
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java?rev=1177564&r1=1177563&r2=1177564&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
Fri Sep 30 09:28:25 2011
@@ -18,6 +18,7 @@
*/
package org.apache.cxf.sts.token.validator;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
@@ -32,6 +33,7 @@ import org.apache.cxf.sts.STSPropertiesM
import org.apache.cxf.sts.request.ReceivedToken;
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.sts.token.realm.SAMLRealm;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.ws.security.SAMLTokenPrincipal;
import org.apache.ws.security.WSConstants;
@@ -105,13 +107,7 @@ public class SAMLTokenValidator implemen
STSPropertiesMBean stsProperties = tokenParameters.getStsProperties();
Crypto sigCrypto = stsProperties.getSignatureCrypto();
CallbackHandler callbackHandler = stsProperties.getCallbackHandler();
-
- RequestData requestData = new RequestData();
- requestData.setSigCrypto(sigCrypto);
- WSSConfig wssConfig = WSSConfig.getNewInstance();
- requestData.setWssConfig(wssConfig);
- requestData.setCallbackHandler(callbackHandler);
-
+
TokenValidatorResponse response = new TokenValidatorResponse();
response.setValid(false);
@@ -122,41 +118,65 @@ public class SAMLTokenValidator implemen
try {
Element validateTargetElement = (Element)validateTarget.getToken();
AssertionWrapper assertion = new
AssertionWrapper(validateTargetElement);
- if (!assertion.isSigned()) {
- LOG.log(Level.WARNING, "The received assertion is not signed,
and therefore not trusted");
- return response;
- }
- // Verify the signature
- assertion.verifySignature(
- requestData, new
WSDocInfo(validateTargetElement.getOwnerDocument())
- );
-
- // Now verify trust on the signature
- Credential trustCredential = new Credential();
- SAMLKeyInfo samlKeyInfo = assertion.getSignatureKeyInfo();
- trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
- trustCredential.setCertificates(samlKeyInfo.getCerts());
-
- validator.validate(trustCredential, requestData);
-
- // Finally check that the issuer is trusted
- String trustedIssuer = null;
- String assertionIssuer = assertion.getIssuerString();
- for (String realm : realmMap.keySet()) {
- SAMLRealm samlRealm = realmMap.get(realm);
- if (samlRealm.getIssuer().equals(assertionIssuer)) {
- trustedIssuer = realm;
- break;
+
+ SecurityToken secToken = null;
+ if (tokenParameters.getTokenStore() != null) {
+ int hash = 0;
+ byte[] signatureValue = assertion.getSignatureValue();
+ if (signatureValue != null && signatureValue.length > 0) {
+ hash = Arrays.hashCode(signatureValue);
+ secToken =
tokenParameters.getTokenStore().getTokenByAssociatedHash(hash);
}
}
- if (trustedIssuer == null &&
assertionIssuer.equals(stsProperties.getIssuer())) {
- trustedIssuer = stsProperties.getIssuer();
- }
- if (trustedIssuer != null) {
+ if (secToken == null) {
+ if (!assertion.isSigned()) {
+ LOG.log(Level.WARNING, "The received assertion is not
signed, and therefore not trusted");
+ return response;
+ }
+
+ RequestData requestData = new RequestData();
+ requestData.setSigCrypto(sigCrypto);
+ WSSConfig wssConfig = WSSConfig.getNewInstance();
+ requestData.setWssConfig(wssConfig);
+ requestData.setCallbackHandler(callbackHandler);
+
+ // Verify the signature
+ assertion.verifySignature(
+ requestData, new
WSDocInfo(validateTargetElement.getOwnerDocument())
+ );
+
+ // Now verify trust on the signature
+ Credential trustCredential = new Credential();
+ SAMLKeyInfo samlKeyInfo = assertion.getSignatureKeyInfo();
+ trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
+ trustCredential.setCertificates(samlKeyInfo.getCerts());
+
+ validator.validate(trustCredential, requestData);
+
+ // Finally check that the issuer is trusted
+ String trustedIssuer = null;
+ String assertionIssuer = assertion.getIssuerString();
+ for (String realm : realmMap.keySet()) {
+ SAMLRealm samlRealm = realmMap.get(realm);
+ if (samlRealm.getIssuer().equals(assertionIssuer)) {
+ trustedIssuer = realm;
+ break;
+ }
+ }
+ if (trustedIssuer == null &&
assertionIssuer.equals(stsProperties.getIssuer())) {
+ trustedIssuer = stsProperties.getIssuer();
+ }
+ if (trustedIssuer != null) {
+ response.setValid(true);
+ SAMLTokenPrincipal samlPrincipal = new
SAMLTokenPrincipal(assertion);
+ response.setPrincipal(samlPrincipal);
+ response.setTokenRealm(trustedIssuer);
+ }
+ } else {
response.setValid(true);
SAMLTokenPrincipal samlPrincipal = new
SAMLTokenPrincipal(assertion);
response.setPrincipal(samlPrincipal);
- response.setTokenRealm(trustedIssuer);
+ response.setTokenRealm(assertion.getIssuerString());
}
} catch (WSSecurityException ex) {
LOG.log(Level.WARNING, "", ex);
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java?rev=1177564&r1=1177563&r2=1177564&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
Fri Sep 30 09:28:25 2011
@@ -39,6 +39,7 @@ import org.apache.cxf.sts.request.Receiv
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSConfig;
@@ -114,23 +115,33 @@ public class UsernameTokenValidator impl
// Turn the JAXB UsernameTokenType into a DOM Element for validation
//
UsernameTokenType usernameTokenType =
(UsernameTokenType)validateTarget.getToken();
- Element rootElement = null;
- try {
- JAXBContext jaxbContext =
-
JAXBContext.newInstance("org.apache.cxf.ws.security.sts.provider.model");
- Marshaller marshaller = jaxbContext.createMarshaller();
- Document doc = DOMUtils.createDocument();
- rootElement = doc.createElement("root-element");
- JAXBElement<UsernameTokenType> tokenType =
- new JAXBElement<UsernameTokenType>(
- QNameConstants.USERNAME_TOKEN, UsernameTokenType.class,
usernameTokenType
- );
- marshaller.marshal(tokenType, rootElement);
- } catch (JAXBException ex) {
- LOG.log(Level.WARNING, "", ex);
- return response;
+ SecurityToken secToken = null;
+ if (tokenParameters.getTokenStore() != null) {
+ secToken =
tokenParameters.getTokenStore().getToken(usernameTokenType.getId());
}
+ Element rootElement = null;
+ Element usernameTokenElement = null;
+ if (secToken == null) {
+ try {
+ JAXBContext jaxbContext =
+
JAXBContext.newInstance("org.apache.cxf.ws.security.sts.provider.model");
+ Marshaller marshaller = jaxbContext.createMarshaller();
+ Document doc = DOMUtils.createDocument();
+ rootElement = doc.createElement("root-element");
+ JAXBElement<UsernameTokenType> tokenType =
+ new JAXBElement<UsernameTokenType>(
+ QNameConstants.USERNAME_TOKEN,
UsernameTokenType.class, usernameTokenType
+ );
+ marshaller.marshal(tokenType, rootElement);
+ } catch (JAXBException ex) {
+ LOG.log(Level.WARNING, "", ex);
+ return response;
+ }
+ usernameTokenElement = (Element)rootElement.getFirstChild();
+ } else {
+ usernameTokenElement = secToken.getToken();
+ }
//
// Validate the token
//
@@ -138,17 +149,17 @@ public class UsernameTokenValidator impl
boolean allowNamespaceQualifiedPasswordTypes =
wssConfig.getAllowNamespaceQualifiedPasswordTypes();
boolean bspCompliant = wssConfig.isWsiBSPCompliant();
- Element usernameTokenElement =
(Element)rootElement.getFirstChild();
-
UsernameToken ut =
new UsernameToken(usernameTokenElement,
allowNamespaceQualifiedPasswordTypes, bspCompliant);
if (ut.getPassword() == null) {
return response;
}
- Credential credential = new Credential();
- credential.setUsernametoken(ut);
- validator.validate(credential, requestData);
+ if (secToken == null || (secToken.getAssociatedHash() !=
ut.hashCode())) {
+ Credential credential = new Credential();
+ credential.setUsernametoken(ut);
+ validator.validate(credential, requestData);
+ }
Principal principal =
createPrincipal(
ut.getName(), ut.getPassword(), ut.getPasswordType(),
ut.getNonce(), ut.getCreated()
Modified:
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java?rev=1177564&r1=1177563&r2=1177564&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/validator/SAMLTokenValidatorTest.java
Fri Sep 30 09:28:25 2011
@@ -34,6 +34,8 @@ import org.apache.cxf.jaxws.context.Wrap
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.sts.STSConstants;
import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.cache.DefaultInMemoryTokenStore;
+import org.apache.cxf.sts.cache.STSTokenStore;
import org.apache.cxf.sts.common.PasswordCallbackHandler;
import org.apache.cxf.sts.request.KeyRequirements;
import org.apache.cxf.sts.request.ReceivedToken;
@@ -49,6 +51,7 @@ import org.apache.ws.security.WSPassword
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.junit.BeforeClass;
/**
@@ -56,6 +59,13 @@ import org.apache.ws.security.components
*/
public class SAMLTokenValidatorTest extends org.junit.Assert {
+ private static STSTokenStore tokenStore;
+
+ @BeforeClass
+ public static void init() {
+ tokenStore = new DefaultInMemoryTokenStore();
+ }
+
/**
* Test a valid SAML 1.1 Assertion
*/
@@ -140,6 +150,9 @@ public class SAMLTokenValidatorTest exte
assertTrue(samlTokenValidator.canHandleToken(validateTarget));
+ // Set tokenstore to null so that issued token is not found in the
cache
+ validatorParameters.setTokenStore(null);
+
// Change the issuer and so validation should fail
validatorParameters.getStsProperties().setIssuer("NewSTS");
@@ -170,7 +183,10 @@ public class SAMLTokenValidatorTest exte
tokenRequirements.setValidateTarget(validateTarget);
assertTrue(samlTokenValidator.canHandleToken(validateTarget));
-
+
+ // Set tokenstore to null so that issued token is not found in the
cache
+ validatorParameters.setTokenStore(null);
+
// Change the issuer and so validation should fail
validatorParameters.getStsProperties().setIssuer("NewSTS");
@@ -202,6 +218,9 @@ public class SAMLTokenValidatorTest exte
assertTrue(samlTokenValidator.canHandleToken(validateTarget));
+ // Set tokenstore to null so that issued token is not found in the
cache
+ validatorParameters.setTokenStore(null);
+
TokenValidatorResponse validatorResponse =
samlTokenValidator.validateToken(validatorParameters);
assertTrue(validatorResponse != null);
@@ -230,6 +249,9 @@ public class SAMLTokenValidatorTest exte
assertTrue(samlTokenValidator.canHandleToken(validateTarget));
+ // Set tokenstore to null so that issued token is not found in the
cache
+ validatorParameters.setTokenStore(null);
+
TokenValidatorResponse validatorResponse =
samlTokenValidator.validateToken(validatorParameters);
assertTrue(validatorResponse != null);
@@ -263,6 +285,7 @@ public class SAMLTokenValidatorTest exte
stsProperties.setCallbackHandler(new PasswordCallbackHandler());
stsProperties.setIssuer("STS");
parameters.setStsProperties(stsProperties);
+ parameters.setTokenStore(tokenStore);
return parameters;
}
@@ -314,7 +337,8 @@ public class SAMLTokenValidatorTest exte
parameters.setStsProperties(stsProperties);
parameters.setEncryptionProperties(new EncryptionProperties());
-
+ parameters.setTokenStore(tokenStore);
+
return parameters;
}