Author: sergeyb
Date: Wed Jul 13 14:07:18 2011
New Revision: 1146045
URL: http://svn.apache.org/viewvc?rev=1146045&view=rev
Log:
[CXF-3588] Some refactoring of plain SAML interceptors
Added:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java
(with props)
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java
(with props)
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java
(with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderInHandler.java
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderOutInterceptor.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java?rev=1146045&r1=1146044&r2=1146045&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
Wed Jul 13 14:07:18 2011
@@ -62,6 +62,12 @@ public class FormEncodingProvider implem
private String attachmentDir;
private String attachmentThreshold;
+ private boolean expectEncoded;
+
+ public void setExpectedEncoded(boolean expect) {
+ this.expectEncoded = expect;
+ }
+
public void setAttachmentDirectory(String dir) {
attachmentDir = dir;
}
@@ -94,8 +100,7 @@ public class FormEncodingProvider implem
}
MultivaluedMap<String, String> params = createMap(clazz);
- populateMap(params, is, mt,
- AnnotationUtils.getAnnotation(annotations,
Encoded.class) == null);
+ populateMap(params, is, mt, !keepEncoded(annotations));
validateMap(params);
persistParamsOnMessage(params);
@@ -108,6 +113,11 @@ public class FormEncodingProvider implem
}
}
+ protected boolean keepEncoded(Annotation[] anns) {
+ return AnnotationUtils.getAnnotation(anns, Encoded.class) != null
+ || expectEncoded;
+ }
+
protected void persistParamsOnMessage(MultivaluedMap<String, String>
params) {
Message message = PhaseInterceptorChain.getCurrentMessage();
if (message != null) {
@@ -180,7 +190,7 @@ public class FormEncodingProvider implem
MultivaluedMap<String, String> map =
(MultivaluedMap<String, String>)(obj instanceof Form ?
((Form)obj).getData() : obj);
- boolean encoded = AnnotationUtils.getAnnotation(anns, Encoded.class)
!= null;
+ boolean encoded = keepEncoded(anns);
String encoding = HttpUtils.getSetEncoding(mt, headers, "UTF-8");
Added:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java?rev=1146045&view=auto
==============================================================================
---
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java
(added)
+++
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java
Wed Jul 13 14:07:18 2011
@@ -0,0 +1,60 @@
+/**
+ * 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.cxf.systest.jaxrs.security.saml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.zip.DataFormatException;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.message.Message;
+
+public abstract class AbstractSamlBase64InHandler extends
AbstractSamlInHandler {
+
+ private boolean useDeflateEncoding = true;
+
+ public void setUseDeflateEncoding(boolean deflate) {
+ useDeflateEncoding = deflate;
+ }
+ public boolean useDeflateEncoding() {
+ return useDeflateEncoding;
+ }
+
+ protected void handleToken(Message message, String assertion) {
+ // the assumption here is that saml:Assertion is directly available,
however, it
+ // may be contained inside saml:Response or
saml:ArtifactResponse/saml:Response
+ if (assertion == null) {
+ throwFault("SAML assertion is not available", null);
+ }
+
+ try {
+ byte[] deflatedToken = Base64Utility.decode(assertion);
+ InputStream is = useDeflateEncoding()
+ ? new DeflateEncoderDecoder().inflateToken(deflatedToken)
+ : new ByteArrayInputStream(deflatedToken);
+ validateToken(message, is);
+ } catch (Base64Exception ex) {
+ throwFault("Base64 decoding has failed", ex);
+ } catch (DataFormatException ex) {
+ throwFault("Encoded assertion can not be inflated", ex);
+ }
+ }
+}
Propchange:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/AbstractSamlBase64InHandler.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java?rev=1146045&view=auto
==============================================================================
---
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java
(added)
+++
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java
Wed Jul 13 14:07:18 2011
@@ -0,0 +1,68 @@
+/**
+ * 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.cxf.systest.jaxrs.security.saml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+public class DeflateEncoderDecoder {
+ public InputStream inflateToken(byte[] deflatedToken)
+ throws DataFormatException {
+ Inflater inflater = new Inflater();
+ inflater.setInput(deflatedToken);
+
+ byte[] input = new byte[deflatedToken.length * 2];
+
+ int inflatedLen = 0;
+ int inputLen = 0;
+ byte[] inflatedToken = input;
+ while (!inflater.finished()) {
+ inputLen = inflater.inflate(input);
+ if (!inflater.finished()) {
+ inflatedToken = new byte[input.length + inflatedLen];
+ System.arraycopy(input, 0, inflatedToken, inflatedLen,
inputLen);
+ inflatedLen += inputLen;
+ }
+ }
+ InputStream is = new ByteArrayInputStream(input, 0, inputLen);
+ if (inflatedToken != input) {
+ is = new SequenceInputStream(new
ByteArrayInputStream(inflatedToken, 0, inflatedLen),
+ is);
+ }
+ return is;
+ }
+
+ public byte[] deflateToken(byte[] tokenBytes) {
+ Deflater compresser = new Deflater();
+
+ compresser.setInput(tokenBytes);
+ compresser.finish();
+
+ byte[] output = new byte[tokenBytes.length];
+
+ int compressedDataLength = compresser.deflate(output);
+ byte[] result = new byte[compressedDataLength];
+ System.arraycopy(output, 0, result, 0, compressedDataLength);
+ return result;
+ }
+}
Propchange:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/DeflateEncoderDecoder.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java?rev=1146045&view=auto
==============================================================================
---
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java
(added)
+++
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java
Wed Jul 13 14:07:18 2011
@@ -0,0 +1,92 @@
+/**
+ * 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.cxf.systest.jaxrs.security.saml;
+
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.io.CachedOutputStream;
+import org.apache.cxf.jaxrs.ext.form.Form;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.impl.UriInfoImpl;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.provider.FormEncodingProvider;
+import org.apache.cxf.message.Message;
+
+public class SamlFormInHandler extends AbstractSamlBase64InHandler {
+
+ private static final String SAML_ELEMENT = "SAMLToken";
+ private static final String SAML_RELAY_STATE = "RelayState";
+
+ private FormEncodingProvider provider = new FormEncodingProvider();
+
+ public SamlFormInHandler() {
+ provider.setExpectedEncoded(true);
+ }
+
+ public Response handleRequest(Message message, ClassResourceInfo
resourceClass) {
+
+ Form form = readFormData(message);
+ String assertion = form.getData().getFirst(SAML_ELEMENT);
+
+ handleToken(message, assertion);
+
+ // redirect if needed
+ String samlRequestURI = form.getData().getFirst(SAML_RELAY_STATE);
+ if (samlRequestURI != null) {
+ // RelayState may actually represent a reference to a transient
local state
+ // containing the actual REQUEST URI client was using before being
redirected
+ // back to IDP - at the moment assume it's URI
+ UriInfoImpl ui = new UriInfoImpl(message);
+ if (!samlRequestURI.startsWith(ui.getBaseUri().toString())) {
+ return
Response.status(302).location(URI.create(samlRequestURI)).build();
+ }
+ }
+ // restore input stream
+ CachedOutputStream os = new CachedOutputStream();
+ form.getData().remove(SAML_ELEMENT);
+ form.getData().remove(SAML_RELAY_STATE);
+ try {
+ provider.writeTo(form, Form.class, Form.class, new Annotation[]{},
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE, new
MetadataMap<String, Object>(), os);
+ message.setContent(InputStream.class, os.getInputStream());
+ } catch (Exception ex) {
+ throwFault(ex.getMessage(), ex);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Form readFormData(Message message) {
+ try {
+ return (Form)provider.readFrom((Class)Form.class, Form.class,
+ new Annotation[]{},
MediaType.APPLICATION_FORM_URLENCODED_TYPE,
+ new MetadataMap<String, String>(),
+ message.getContent(InputStream.class));
+ } catch (Exception ex) {
+ throwFault("Error reading the form", ex);
+ }
+ return null;
+ }
+}
Propchange:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlFormInHandler.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderInHandler.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderInHandler.java?rev=1146045&r1=1146044&r2=1146045&view=diff
==============================================================================
---
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderInHandler.java
(original)
+++
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderInHandler.java
Wed Jul 13 14:07:18 2011
@@ -19,23 +19,16 @@
package org.apache.cxf.systest.jaxrs.security.saml;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.SequenceInputStream;
import java.util.List;
-import java.util.zip.DataFormatException;
-import java.util.zip.Inflater;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
-import org.apache.cxf.common.util.Base64Exception;
-import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.message.Message;
-public class SamlHeaderInHandler extends AbstractSamlInHandler {
+public class SamlHeaderInHandler extends AbstractSamlBase64InHandler {
private static final String SAML_AUTH = "SAML";
@@ -54,41 +47,10 @@ public class SamlHeaderInHandler extends
throwFault("Authorization header is malformed", null);
}
- try {
- validateToken(message, decodeAndInflateToken(parts[1]));
- } catch (Base64Exception ex) {
- throwFault("Base64 decoding has failed", ex);
- } catch (DataFormatException ex) {
- throwFault("Encoded assertion can not be inflated", ex);
- }
+ handleToken(message, parts[1]);
return null;
}
- private InputStream decodeAndInflateToken(String encodedToken)
- throws DataFormatException, Base64Exception {
- byte[] deflatedToken = Base64Utility.decode(encodedToken);
- Inflater inflater = new Inflater();
- inflater.setInput(deflatedToken);
-
- byte[] input = new byte[deflatedToken.length * 2];
-
- int inflatedLen = 0;
- int inputLen = 0;
- byte[] inflatedToken = input;
- while (!inflater.finished()) {
- inputLen = inflater.inflate(input);
- if (!inflater.finished()) {
- inflatedToken = new byte[input.length + inflatedLen];
- System.arraycopy(input, 0, inflatedToken, inflatedLen,
inputLen);
- inflatedLen += inputLen;
- }
- }
- InputStream is = new ByteArrayInputStream(input, 0, inputLen);
- if (inflatedToken != input) {
- is = new SequenceInputStream(new
ByteArrayInputStream(inflatedToken, 0, inflatedLen),
- is);
- }
- return is;
- }
+
}
Modified:
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderOutInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderOutInterceptor.java?rev=1146045&r1=1146044&r2=1146045&view=diff
==============================================================================
---
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderOutInterceptor.java
(original)
+++
cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlHeaderOutInterceptor.java
Wed Jul 13 14:07:18 2011
@@ -26,7 +26,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
-import java.util.zip.Deflater;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.Base64Exception;
@@ -40,13 +39,20 @@ public class SamlHeaderOutInterceptor ex
private static final Logger LOG =
LogUtils.getL7dLogger(SamlHeaderOutInterceptor.class);
+ private boolean useDeflateEncoding = true;
+
public SamlHeaderOutInterceptor() {
}
+ public void setUseDeflateEncoding(boolean deflate) {
+ useDeflateEncoding = deflate;
+ }
+
public void handleMessage(Message message) throws Fault {
- AssertionWrapper assertion = createAssertion(message);
+ AssertionWrapper assertionWrapper = createAssertion(message);
try {
- String encodedToken =
deflateAndEncodeToken(assertion.assertionToString());
+
+ String encodedToken =
encodeToken(assertionWrapper.assertionToString());
Map<String, List<String>> headers =
CastUtils.cast((Map)message.get(Message.PROTOCOL_HEADERS));
@@ -68,25 +74,18 @@ public class SamlHeaderOutInterceptor ex
}
-
- private String deflateAndEncodeToken(String token) throws Base64Exception {
- Deflater compresser = new Deflater();
+ private String encodeToken(String assertion) throws Base64Exception {
byte[] tokenBytes = null;
try {
- tokenBytes = token.getBytes("UTF-8");
- compresser.setInput(tokenBytes);
+ tokenBytes = assertion.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
// won't happen
}
- compresser.finish();
-
- byte[] output = new byte[tokenBytes.length];
-
- int compressedDataLength = compresser.deflate(output);
-
+ if (useDeflateEncoding) {
+ tokenBytes = new DeflateEncoderDecoder().deflateToken(tokenBytes);
+ }
StringWriter writer = new StringWriter();
- Base64Utility.encode(output, 0, compressedDataLength, writer);
+ Base64Utility.encode(tokenBytes, 0, tokenBytes.length, writer);
return writer.toString();
}
-
}