Author: cschneider
Date: Thu Dec 23 11:59:56 2010
New Revision: 1052233
URL: http://svn.apache.org/viewvc?rev=1052233&view=rev
Log:
CXF-3216 Refactor http authentication to make it more flexible and simpler. Add
spnego kerberos auth support
Added:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DefaultBasicAuthSupplier.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/SpnegoAuthSupplier.java
cxf/trunk/systests/transports/src/test/java/digestauth/
cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/
cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/beans.xml
cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/web.xml
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestAuthTest.java
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestServer.java
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/GreeterImpl.java
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/jetty-realm.properties
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DigestAuthSupplier.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpAuthHeader.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpBasicAuthSupplier.java
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/DigestAuthSupplierTest.java
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
Added:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DefaultBasicAuthSupplier.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DefaultBasicAuthSupplier.java?rev=1052233&view=auto
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DefaultBasicAuthSupplier.java
(added)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DefaultBasicAuthSupplier.java
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,49 @@
+/**
+ * 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.transport.http;
+
+import java.net.URL;
+
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.message.Message;
+
+final class DefaultBasicAuthSupplier extends HttpAuthSupplier {
+ DefaultBasicAuthSupplier() {
+ super();
+ }
+
+ @Override
+ public String getPreemptiveAuthorization(HTTPConduit conduit, URL
currentURL, Message message) {
+ AuthorizationPolicy effectiveAuthPolicy =
conduit.getEffectiveAuthPolicy(message);
+ if (effectiveAuthPolicy.getUserName() != null &&
effectiveAuthPolicy.getPassword() != null) {
+ return
HttpBasicAuthSupplier.getBasicAuthHeader(effectiveAuthPolicy.getUserName(),
+
effectiveAuthPolicy.getPassword());
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getAuthorizationForRealm(HTTPConduit conduit, URL
currentURL, Message message,
+ String realm, String fullHeader) {
+ return getPreemptiveAuthorization(conduit, currentURL, message);
+ }
+
+
+}
\ No newline at end of file
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DigestAuthSupplier.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DigestAuthSupplier.java?rev=1052233&r1=1052232&r2=1052233&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DigestAuthSupplier.java
(original)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/DigestAuthSupplier.java
Thu Dec 23 11:59:56 2010
@@ -64,8 +64,9 @@ public class DigestAuthSupplier extends
public String getAuthorizationForRealm(HTTPConduit conduit, URL currentURL,
Message message,
String realm, String fullHeader) {
+ AuthorizationPolicy authPolicy =
conduit.getEffectiveAuthPolicy(message);
HttpAuthHeader authHeader = new HttpAuthHeader(fullHeader);
- if (authHeader.authTypeIsDigest()) {
+ if (authHeader.authTypeIsDigest() && authPolicy != null) {
Map<String, String> map = authHeader.getParams();
if ("auth".equals(map.get("qop"))
|| !map.containsKey("qop")) {
@@ -85,9 +86,10 @@ public class DigestAuthSupplier extends
di.method = "POST";
}
authInfo.put(currentURL, di);
+
return di.generateAuth(currentURL.getFile(),
- getUsername(conduit, message),
- getPassword(conduit, message));
+ authPolicy.getUserName(),
+ authPolicy.getPassword());
}
}
@@ -96,34 +98,11 @@ public class DigestAuthSupplier extends
@Override
public String getPreemptiveAuthorization(HTTPConduit conduit, URL
currentURL, Message message) {
DigestInfo di = authInfo.get(currentURL);
+ AuthorizationPolicy authPolicy =
conduit.getEffectiveAuthPolicy(message);
if (di != null) {
return di.generateAuth(currentURL.getFile(),
- getUsername(conduit, message),
- getPassword(conduit, message));
- }
- return null;
- }
-
- private String getPassword(HTTPConduit conduit, Message message) {
- AuthorizationPolicy policy = getPolicy(conduit, message);
- return policy != null ? policy.getPassword() : null;
- }
-
- private String getUsername(HTTPConduit conduit, Message message) {
- AuthorizationPolicy policy = getPolicy(conduit, message);
- return policy != null ? policy.getUserName() : null;
- }
-
- private AuthorizationPolicy getPolicy(HTTPConduit conduit, Message
message) {
- AuthorizationPolicy policy
- =
(AuthorizationPolicy)message.getContextualProperty(AuthorizationPolicy.class.getName());
- if (policy == null) {
- policy = conduit.getAuthorization();
- }
- if (policy != null
- && (!policy.isSetAuthorizationType()
- || "Digest".equals(policy.getAuthorizationType()))) {
- return policy;
+ authPolicy.getUserName(),
+ authPolicy.getPassword());
}
return null;
}
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java?rev=1052233&r1=1052232&r2=1052233&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
(original)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
Thu Dec 23 11:59:56 2010
@@ -469,19 +469,18 @@ public class HTTPConduit
boolean isChunking = false;
int chunkThreshold = 0;
- // We must cache the request if we have basic auth supplier
- // without preemptive basic auth.
- if (authSupplier != null) {
- String auth = authSupplier.getPreemptiveAuthorization(
- this, currentURL, message);
- if (auth == null || authSupplier.requiresRequestCaching()) {
- needToCacheRequest = true;
- isChunking = false;
- LOG.log(Level.FINE,
- "Auth Supplier, but no Premeptive User Pass or Digest
auth (nonce may be stale)"
- + " We must cache request.");
- }
- message.put("AUTH_VALUE", auth);
+ final AuthorizationPolicy effectiveAuthPolicy =
getEffectiveAuthPolicy(message);
+ if (this.authSupplier == null) {
+ String authType = effectiveAuthPolicy.getAuthorizationType();
+ this.authSupplier = createAuthSupplier(authType);
+ }
+
+ if (this.authSupplier.requiresRequestCaching()) {
+ needToCacheRequest = true;
+ isChunking = false;
+ LOG.log(Level.FINE,
+ "Auth Supplier, but no Premeptive User Pass or Digest auth
(nonce may be stale)"
+ + " We must cache request.");
}
if (csPolicy.isAutoRedirect()) {
needToCacheRequest = true;
@@ -534,6 +533,16 @@ public class HTTPConduit
// We are now "ready" to "send" the message.
}
+ private HttpAuthSupplier createAuthSupplier(String authType) {
+ if (HttpAuthHeader.AUTH_TYPE_NEGOTIATE.equals(authType)) {
+ return new SpnegoAuthSupplier();
+ } else if (HttpAuthHeader.AUTH_TYPE_DIGEST.equals(authType)) {
+ return new DigestAuthSupplier();
+ } else {
+ return new DefaultBasicAuthSupplier();
+ }
+ }
+
private static int determineReceiveTimeout(Message message,
HTTPClientPolicy csPolicy) {
long rtimeout = csPolicy.getReceiveTimeout();
@@ -718,53 +727,17 @@ public class HTTPConduit
URL url
) {
Headers headers = new Headers(message);
- AuthorizationPolicy authPolicy = getAuthorization();
- AuthorizationPolicy newPolicy = message.get(AuthorizationPolicy.class);
-
- String authString = null;
- if (authSupplier != null
- && (newPolicy == null
- || (!"Basic".equals(newPolicy.getAuthorizationType())
- && newPolicy.getAuthorization() == null))) {
- authString = (String)message.get("AUTH_VALUE");
- if (authString == null) {
- authString = authSupplier.getPreemptiveAuthorization(
- this, url, message);
- } else {
- message.remove("AUTH_VALUE");
- }
- if (authString != null) {
- headers.setAuthorization(authString);
- }
- return;
- }
- String userName = null;
- String passwd = null;
- if (null != newPolicy) {
- userName = newPolicy.getUserName();
- passwd = newPolicy.getPassword();
- }
-
- if (userName == null
- && authPolicy != null && authPolicy.isSetUserName()) {
- userName = authPolicy.getUserName();
- }
- if (userName != null) {
- if (passwd == null
- && authPolicy != null && authPolicy.isSetPassword()) {
- passwd = authPolicy.getPassword();
- }
-
headers.setAuthorization(HttpBasicAuthSupplier.getBasicAuthHeader(userName,
passwd));
- } else if (authPolicy != null
- && authPolicy.isSetAuthorizationType()
- && authPolicy.isSetAuthorization()) {
- headers.setAuthorization(authPolicy.getAuthorizationType() + " " +
authPolicy.getAuthorization());
+ String authString = authSupplier.getPreemptiveAuthorization(this, url,
message);
+ if (authString != null) {
+ headers.setAuthorization(authString);
}
+
+ // TODO Also use an authSupplier for proxy auth
AuthorizationPolicy proxyAuthPolicy = getProxyAuthorization();
if (proxyAuthPolicy != null && proxyAuthPolicy.isSetUserName()) {
- userName = proxyAuthPolicy.getUserName();
+ String userName = proxyAuthPolicy.getUserName();
if (userName != null) {
- passwd = "";
+ String passwd = "";
if (proxyAuthPolicy.isSetPassword()) {
passwd = proxyAuthPolicy.getPassword();
}
@@ -788,6 +761,26 @@ public class HTTPConduit
}
return null;
}
+
+ /**
+ * Determines effective auth policy from message, conduit and empty default
+ * with priority from first to last
+ *
+ * @param message
+ * @return effective AthorizationPolicy
+ */
+ public AuthorizationPolicy getEffectiveAuthPolicy(Message message) {
+ AuthorizationPolicy authPolicy = getAuthorization();
+ AuthorizationPolicy newPolicy = message.get(AuthorizationPolicy.class);
+ AuthorizationPolicy effectivePolicy = newPolicy;
+ if (effectivePolicy == null) {
+ effectivePolicy = authPolicy;
+ }
+ if (effectivePolicy == null) {
+ effectivePolicy = new AuthorizationPolicy();
+ }
+ return effectivePolicy;
+ }
/**
* This method gets the Authorization Policy that was configured or
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpAuthHeader.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpAuthHeader.java?rev=1052233&r1=1052232&r2=1052233&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpAuthHeader.java
(original)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpAuthHeader.java
Thu Dec 23 11:59:56 2010
@@ -35,13 +35,14 @@ public final class HttpAuthHeader {
private Map<String, String> params;
public HttpAuthHeader(String fullHeader) {
- this.fullHeader = fullHeader;
- int spacePos = fullHeader.indexOf(' ');
+ this.fullHeader = (fullHeader == null) ? "" : fullHeader;
+ int spacePos = this.fullHeader.indexOf(' ');
if (spacePos == -1) {
- this.authType = fullHeader;
+ this.authType = this.fullHeader;
+ this.fullContent = "";
} else {
- this.authType = fullHeader.substring(0, spacePos);
- this.fullContent = fullHeader.substring(spacePos + 1);
+ this.authType = this.fullHeader.substring(0, spacePos);
+ this.fullContent = this.fullHeader.substring(spacePos + 1);
}
this.params = parseHeader();
}
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpBasicAuthSupplier.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpBasicAuthSupplier.java?rev=1052233&r1=1052232&r2=1052233&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpBasicAuthSupplier.java
(original)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpBasicAuthSupplier.java
Thu Dec 23 11:59:56 2010
@@ -52,6 +52,7 @@ public abstract class HttpBasicAuthSuppl
*
*/
protected HttpBasicAuthSupplier() {
+ super();
}
/**
Added:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/SpnegoAuthSupplier.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/SpnegoAuthSupplier.java?rev=1052233&view=auto
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/SpnegoAuthSupplier.java
(added)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/SpnegoAuthSupplier.java
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,172 @@
+/**
+ * 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.transport.http;
+
+import java.net.URL;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.message.Message;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+
+public class SpnegoAuthSupplier extends HttpAuthSupplier {
+ private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
+ //private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
+
+ private static final Logger LOG = LogUtils.getL7dLogger(HTTPConduit.class);
+
+ private LoginContext lc;
+
+ @Override
+ public String getPreemptiveAuthorization(HTTPConduit conduit, URL
currentURL, Message message) {
+ AuthorizationPolicy authPolicy =
conduit.getEffectiveAuthPolicy(message);
+ if
(!HttpAuthHeader.AUTH_TYPE_NEGOTIATE.equals(authPolicy.getAuthorizationType()))
{
+ return null;
+ }
+ try {
+ String spn = "HTTP/" + currentURL.getHost();
+ LOG.fine("Adding authorization service ticket for service
principal name: " + spn);
+ byte[] token = getToken(authPolicy, spn);
+ return HttpAuthHeader.AUTH_TYPE_NEGOTIATE + " " +
Base64Utility.encode(token);
+ } catch (LoginException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } catch (GSSException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public String getAuthorizationForRealm(HTTPConduit conduit, URL
currentURL, Message message,
+ String realm, String fullHeader) {
+ return getPreemptiveAuthorization(conduit, currentURL, message);
+ }
+
+ /**
+ * Create and return service ticket token
+ *
+ * @param authPolicy
+ * @param context
+ * @return
+ * @throws GSSException
+ * @throws LoginException
+ */
+ private byte[] getToken(AuthorizationPolicy authPolicy, final GSSContext
context) throws GSSException,
+ LoginException {
+ final byte[] token = new byte[0];
+
+ if (authPolicy.getUserName() == null ||
authPolicy.getUserName().trim().length() == 0) {
+ return context.initSecContext(token, 0, token.length);
+ }
+
+ if (lc == null) {
+ lc = new LoginContext(authPolicy.getAuthorization(),
getUsernamePasswordHandler(
+ authPolicy.getUserName(), authPolicy.getPassword()));
+ lc.login();
+ }
+
+ try {
+ return (byte[]) Subject.doAs(lc.getSubject(), new
CreateServiceTicketAction(context, token));
+ } catch (PrivilegedActionException e) {
+ if (e.getCause() instanceof GSSException) {
+ throw (GSSException) e.getCause();
+ }
+ LOG.log(Level.SEVERE, "initSecContext", e);
+ return null;
+ }
+ }
+
+ /**
+ * Create and return a service ticket token for a given service principal
+ * name
+ *
+ * @param proxyAuthPolicy
+ * @param spn
+ * @return service ticket token
+ * @throws GSSException
+ * @throws LoginException
+ */
+ private byte[] getToken(AuthorizationPolicy proxyAuthPolicy, String spn)
throws GSSException,
+ LoginException {
+ GSSManager manager = GSSManager.getInstance();
+ GSSName serverName = manager.createName(spn, null);
+
+ // TODO Is it correct to use kerberos oid instead of spnego here?
+ Oid oid = new Oid(KERBEROS_OID);
+
+ GSSContext context = manager
+ .createContext(serverName.canonicalize(oid), oid, null,
GSSContext.DEFAULT_LIFETIME);
+ // TODO Do we need mutual auth. Will the code we have really work with
+ // mutual auth?
+ context.requestMutualAuth(true);
+ // TODO Credential delegation could be a security hole if it was not
+ // intended. Both settings should be configurable
+ context.requestCredDeleg(true);
+
+ return getToken(proxyAuthPolicy, context);
+ }
+
+ private final class CreateServiceTicketAction implements
PrivilegedExceptionAction<byte[]> {
+ private final GSSContext context;
+ private final byte[] token;
+
+ private CreateServiceTicketAction(GSSContext context, byte[] token) {
+ this.context = context;
+ this.token = token;
+ }
+
+ public byte[] run() throws GSSException {
+ return context.initSecContext(token, 0, token.length);
+ }
+ }
+
+ public static CallbackHandler getUsernamePasswordHandler(final String
username, final String password) {
+ final CallbackHandler handler = new CallbackHandler() {
+
+ public void handle(final Callback[] callback) {
+ for (int i = 0; i < callback.length; i++) {
+ if (callback[i] instanceof NameCallback) {
+ final NameCallback nameCallback = (NameCallback)
callback[i];
+ nameCallback.setName(username);
+ } else if (callback[i] instanceof PasswordCallback) {
+ final PasswordCallback passCallback =
(PasswordCallback) callback[i];
+ passCallback.setPassword(password.toCharArray());
+ }
+ }
+ }
+ };
+ return handler;
+ }
+}
Modified:
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/DigestAuthSupplierTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/DigestAuthSupplierTest.java?rev=1052233&r1=1052232&r2=1052233&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/DigestAuthSupplierTest.java
(original)
+++
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/DigestAuthSupplierTest.java
Thu Dec 23 11:59:56 2010
@@ -76,7 +76,8 @@ public class DigestAuthSupplierTest {
authorizationPolicy.setUserName("testUser");
authorizationPolicy.setPassword("testPassword");
-
EasyMock.expect(conduit.getAuthorization()).andReturn(authorizationPolicy).atLeastOnce();
+
EasyMock.expect(conduit.getEffectiveAuthPolicy(EasyMock.isA(Message.class)))
+ .andReturn(authorizationPolicy).atLeastOnce();
URL url = new URL("http://myserver");
Message message = new MessageImpl();
control.replay();
Modified:
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java?rev=1052233&r1=1052232&r2=1052233&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
(original)
+++
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
Thu Dec 23 11:59:56 2010
@@ -213,7 +213,9 @@ public class HTTPConduitTest extends Ass
"Basic " + Base64Utility.encode("Gandalf:staff".getBytes()),
headers.get("Authorization").get(0));
- // Setting authorization policy on the message should override all.
+ conduit.setAuthSupplier(null);
+ // Setting authorization policy on the message should override
+ // conduit setting
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setUserName("Hello");
authPolicy.setPassword("world");
Added: cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/beans.xml
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/beans.xml?rev=1052233&view=auto
==============================================================================
--- cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/beans.xml
(added)
+++ cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/beans.xml
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:http="http://cxf.apache.org/transports/http/configuration"
+ xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+ xmlns:jaxws="http://cxf.apache.org/jaxws"
+ xsi:schemaLocation="
+ http://cxf.apache.org/configuration/security
+ http://cxf.apache.org/schemas/configuration/security.xsd
+ http://cxf.apache.org/transports/http/configuration
+ http://cxf.apache.org/schemas/configuration/http-conf.xsd
+ http://cxf.apache.org/transports/http-jetty/configuration
+ http://cxf.apache.org/schemas/configuration/http-jetty.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://cxf.apache.org/jaxws
+ http://cxf.apache.org/schemas/jaxws.xsd">
+
+ <import resource="classpath:META-INF/cxf/cxf.xml"/>
+ <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
+ <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
+
+ <http:destination
name="{http://apache.org/hello_world}Mortimer.http-destination">
+ <!-- Nothing to Configure here for Mortimer -->
+ </http:destination>
+
+ <bean id="greeterImpl" class="org.apache.cxf.systest.http.auth.GreeterImpl">
+ </bean>
+
+ <jaxws:endpoint address="/greeter" implementor="#greeterImpl"
publish="true"/>
+</beans>
Added: cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/web.xml
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/web.xml?rev=1052233&view=auto
==============================================================================
--- cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/web.xml
(added)
+++ cxf/trunk/systests/transports/src/test/java/digestauth/WEB-INF/web.xml Thu
Dec 23 11:59:56 2010
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+<!-- 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. -->
+
+<web-app>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/beans.xml</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>CXFServlet</servlet-name>
+ <display-name>CXF Servlet</display-name>
+
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>CXFServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+
+ </servlet-mapping>
+
+ <security-constraint>
+
+ <web-resource-collection>
+ <web-resource-name>CXFServlet</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+
+ <auth-constraint>
+ <role-name>ROLE_USER</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>DIGEST</auth-method>
+ <realm-name>BookStoreRealm</realm-name>
+ </login-config>
+
+ <security-role>
+ <role-name>ROLE_USER</role-name>
+ </security-role>
+
+</web-app>
Added:
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestAuthTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestAuthTest.java?rev=1052233&view=auto
==============================================================================
---
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestAuthTest.java
(added)
+++
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestAuthTest.java
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,111 @@
+/**
+ * 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.http.auth;
+
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.soap.SOAPFaultException;
+
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.hello_world.Greeter;
+import org.apache.hello_world.services.SOAPService;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+public class DigestAuthTest extends AbstractBusClientServerTestBase {
+
+ private final QName serviceName =
+ new QName("http://apache.org/hello_world", "SOAPService");
+ private final QName mortimerQ =
+ new QName("http://apache.org/hello_world", "Mortimer");
+ public DigestAuthTest() {
+ }
+
+ @BeforeClass
+ public static void startServer() {
+ launchServer(DigestServer.class);
+ }
+
+ @Test
+ public void testDigestAuth() throws Exception {
+ URL wsdl = getClass().getResource("../resources/greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter mortimer = service.getPort(mortimerQ, Greeter.class);
+ assertNotNull("Port is null", mortimer);
+
+ setAddress(mortimer, "http://localhost:9000/digestauth/greeter");
+
+ Client client = ClientProxy.getClient(mortimer);
+
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+ AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+ authPolicy.setAuthorizationType("Digest");
+ authPolicy.setUserName("foo");
+ authPolicy.setPassword("bar");
+ http.setAuthorization(authPolicy);
+
+ String answer = mortimer.sayHi();
+ assertEquals("Unexpected answer: " + answer,
+ "Hi", answer);
+
+ }
+
+ @Test
+ public void testNoAuth() throws Exception {
+ URL wsdl = getClass().getResource("../resources/greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter mortimer = service.getPort(mortimerQ, Greeter.class);
+ assertNotNull("Port is null", mortimer);
+
+ setAddress(mortimer, "http://localhost:9000/digestauth/greeter");
+
+ try {
+ String answer = mortimer.sayHi();
+ Assert.fail("Unexpected reply (" + answer + "). Should throw
exception");
+ } catch (SOAPFaultException e) {
+ // TODO do we really expect Can't find input stream here. I rather
would expect
+ // authorization failed with some infos
+ Throwable cause = e.getCause();
+ Assert.assertEquals(RuntimeException.class, cause.getClass());
+ RuntimeException rte = (RuntimeException)cause;
+ Assert.assertTrue(rte.getMessage().startsWith("Can't find input
stream"));
+ }
+ }
+
+}
+
Added:
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestServer.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestServer.java?rev=1052233&view=auto
==============================================================================
---
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestServer.java
(added)
+++
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/DigestServer.java
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,97 @@
+/**
+ * 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.http.auth;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.eclipse.jetty.security.HashLoginService;
+import org.eclipse.jetty.security.LoginService;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class DigestServer extends AbstractBusTestServerBase {
+ public static final String PORT = allocatePort(DigestServer.class);
+
+ private org.eclipse.jetty.server.Server server;
+
+ public DigestServer() {
+ }
+
+ protected void configureServer() throws Exception {
+ URL resource = getClass()
+ .getResource("jetty-realm.properties");
+ LoginService realm =
+ new HashLoginService("BookStoreRealm", resource.toString());
+ server.addBean(realm);
+ }
+
+ protected void run() {
+ System.out.println("Starting Server");
+
+ server = new org.eclipse.jetty.server.Server();
+
+ SelectChannelConnector connector = new SelectChannelConnector();
+ connector.setPort(Integer.parseInt(PORT));
+ server.setConnectors(new Connector[] {connector});
+
+ WebAppContext webappcontext = new WebAppContext();
+ webappcontext.setContextPath("/digestauth");
+
+ String warPath = null;
+ try {
+ URL res = getClass().getResource("/digestauth");
+ warPath = res.toURI().getPath();
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
+
+ webappcontext.setWar(warPath);
+
+ HandlerCollection handlers = new HandlerCollection();
+ handlers.setHandlers(new Handler[] {webappcontext, new
DefaultHandler()});
+
+ server.setHandler(handlers);
+
+ try {
+ configureServer();
+ server.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String args[]) {
+ try {
+ DigestServer s = new DigestServer();
+ s.start();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(-1);
+ } finally {
+ System.out.println("done!");
+ }
+ }
+
+}
Added:
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/GreeterImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/GreeterImpl.java?rev=1052233&view=auto
==============================================================================
---
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/GreeterImpl.java
(added)
+++
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/GreeterImpl.java
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,40 @@
+/**
+ * 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.http.auth;
+
+import org.apache.hello_world.Greeter;
+import org.apache.hello_world.messages.PingMeFault;
+
+public class GreeterImpl implements Greeter {
+
+ public String sayHi() {
+ return "Hi";
+ }
+
+ public void pingMe() throws PingMeFault {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String greetMe(String requestType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Added:
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/jetty-realm.properties
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/jetty-realm.properties?rev=1052233&view=auto
==============================================================================
---
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/jetty-realm.properties
(added)
+++
cxf/trunk/systests/transports/src/test/java/org/apache/cxf/systest/http/auth/jetty-realm.properties
Thu Dec 23 11:59:56 2010
@@ -0,0 +1,2 @@
+foo: bar,ROLE_USER
+