Author: sergeyb
Date: Tue Apr 6 17:07:15 2010
New Revision: 931228
URL: http://svn.apache.org/viewvc?rev=931228&view=rev
Log:
CXF-2754,CXF-2755 : extending WSS4JInInterceptor, adding utility Authorizing
interceptors
Added:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
(with props)
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java
(with props)
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
(with props)
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
(with props)
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
(with props)
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java
(with props)
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
Added:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java?rev=931228&view=auto
==============================================================================
---
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
(added)
+++
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
Tue Apr 6 17:07:15 2010
@@ -0,0 +1,69 @@
+/**
+ * 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.interceptor.security;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.cxf.frontend.MethodDispatcher;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.service.model.BindingOperationInfo;
+
+public abstract class AbstractAuthorizingInInterceptor extends
AbstractPhaseInterceptor<Message> {
+
+ public AbstractAuthorizingInInterceptor() {
+ super(Phase.PRE_INVOKE);
+ }
+
+ public void handleMessage(Message message) throws Fault {
+ SecurityContext sc = message.get(SecurityContext.class);
+ if (sc == null) {
+ return;
+ }
+
+ Method method = getTargetMethod(message);
+
+ List<String> expectedRoles = getExpectedRoles(method);
+ if (expectedRoles == null || expectedRoles.isEmpty()) {
+ return;
+ }
+
+ for (String role : expectedRoles) {
+ if (sc.isUserInRole(role)) {
+ return;
+ }
+ }
+
+ throw new AccessDeniedException("Unauthorized");
+ }
+
+ private Method getTargetMethod(Message m) {
+ BindingOperationInfo bop =
m.getExchange().get(BindingOperationInfo.class);
+ MethodDispatcher md = (MethodDispatcher)
+
m.getExchange().get(Service.class).get(MethodDispatcher.class.getName());
+ return md.getMethod(bop);
+ }
+
+ protected abstract List<String> getExpectedRoles(Method method);
+}
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java?rev=931228&view=auto
==============================================================================
---
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java
(added)
+++
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java
Tue Apr 6 17:07:15 2010
@@ -0,0 +1,25 @@
+/**
+ * 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.interceptor.security;
+
+public class AccessDeniedException extends RuntimeException {
+ public AccessDeniedException(String reason) {
+ super(reason);
+ }
+}
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AccessDeniedException.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java?rev=931228&view=auto
==============================================================================
---
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
(added)
+++
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
Tue Apr 6 17:07:15 2010
@@ -0,0 +1,55 @@
+/**
+ * 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.interceptor.security;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+
+public class SimpleAuthorizingInterceptor extends
AbstractAuthorizingInInterceptor {
+
+ private Map<String, List<String>> methodRolesMap;
+ private Map<String, List<String>> classRolesMap;
+
+
+ @Override
+ protected List<String> getExpectedRoles(Method method) {
+ List<String> roles = methodRolesMap.get(method.getName());
+ if (roles != null || classRolesMap == null) {
+ return roles;
+ }
+ return methodRolesMap.get(method.getDeclaringClass().getName());
+ }
+
+
+
+ public void setMethodRolesMap(Map<String, List<String>> rolesMap) {
+ this.methodRolesMap = rolesMap;
+ }
+
+ public void setClassRolesMap(Map<String, List<String>> rolesMap) {
+ this.classRolesMap = rolesMap;
+ }
+
+
+
+
+
+}
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java?rev=931228&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
Tue Apr 6 17:07:15 2010
@@ -0,0 +1,336 @@
+/**
+ * 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.ws.security.wss4j;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+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.UnsupportedCallbackException;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSUsernameTokenPrincipal;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.processor.Processor;
+
+
+/**
+ * Base class providing an extensibility point for populating
+ * javax.security.auth.Subject from a current UsernameToken.
+ *
+ * WSS4J requires a password for validating digests which may not be available
+ * when external security systems provide for the authentication. This class
+ * implements WSS4J Processor interface so that it can delegate a UsernameToken
+ * validation to an external system.
+ *
+ * In order to handle digests, this class currently creates a new WSS4J
Security Engine for
+ * every request. If clear text passwords are expected then a
supportDigestPasswords boolean
+ * property with a false value can be used to disable creating security
engines.
+ *
+ * Note that if a UsernameToken containing a clear text password has been
encrypted then
+ * an application is expected to provide a password callback handler for
decrypting the token only.
+ *
+ */
+public abstract class AbstractWSS4JSecurityContextProvidingInterceptor extends
WSS4JInInterceptor
+ implements Processor {
+
+ private static final Logger LOG =
+
LogUtils.getL7dLogger(AbstractWSS4JSecurityContextProvidingInterceptor.class);
+
+ private ThreadLocal<Message> messages = new ThreadLocal<Message>();
+ private boolean supportDigestPasswords;
+
+ public void setSupportDigestPasswords(boolean support) {
+ supportDigestPasswords = support;
+ }
+
+ @Override
+ public void handleFault(SoapMessage m) {
+ messages.remove();
+ super.handleFault(m);
+ }
+
+ @Override
+ protected SecurityContext createSecurityContext(final Principal p) {
+ Message msg = messages.get();
+ if (msg == null) {
+ throw new IllegalStateException("Current message is not
available");
+ }
+ messages.remove();
+ final Subject subject = msg.get(Subject.class);
+ return new SecurityContext() {
+ public Principal getUserPrincipal() {
+ return p;
+ }
+ public boolean isUserInRole(String role) {
+ if (subject == null || subject.getPrincipals().size() <= 1) {
+ return false;
+ }
+ for (Principal p : subject.getPrincipals()) {
+ if (p instanceof Group &&
((Group)p).getName().equals(role)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ }
+
+ protected void setSubject(String name,
+ String password,
+ boolean isDigest,
+ String nonce,
+ String created) throws WSSecurityException {
+ Message msg = messages.get();
+ if (msg == null) {
+ throw new IllegalStateException("Current message is not
available");
+ }
+ Subject subject = createSubject(name, password, isDigest, nonce,
created);
+ if (subject == null || subject.getPrincipals().size() == 0
+ ||
!subject.getPrincipals().iterator().next().getName().equals(name)) {
+ throw new
WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION, null, null);
+ }
+ msg.put(Subject.class, subject);
+ }
+
+ /**
+ * Create a Subject representing a current user and its roles.
+ * This Subject is expected to contain at least one Principal representing
a user
+ * and optionally followed by one or more principal Groups this user is a
member of.
+ * @param name username
+ * @param password password
+ * @param isDigest true if a password digest is used
+ * @param nonce optional nonce
+ * @param created optional timestamp
+ * @return subject
+ * @throws WSSecurityException
+ */
+ protected abstract Subject createSubject(String name,
+ String password,
+ boolean isDigest,
+ String nonce,
+ String created) throws WSSecurityException;
+
+
+ /**
+ * {...@inheritdoc}
+ *
+ */
+ @Override
+ protected CallbackHandler getCallback(RequestData reqData, int doAction)
+ throws WSSecurityException {
+
+ if ((doAction & WSConstants.UT) != 0) {
+ messages.set((Message)reqData.getMsgContext());
+ if (!supportDigestPasswords) {
+ CallbackHandler pwdCallback = null;
+ try {
+ pwdCallback = super.getCallback(reqData, doAction);
+ } catch (Exception ex) {
+ // ignore
+ }
+ return new DelegatingCallbackHandler(pwdCallback);
+ }
+ }
+
+
+ return super.getCallback(reqData, doAction);
+ }
+
+ @Override
+ protected WSSecurityEngine getSecurityEngine() {
+ if (!supportDigestPasswords) {
+ return super.getSecurityEngine();
+ }
+ Map<QName, Object> profiles = new HashMap<QName, Object>(3);
+ profiles.put(new QName(WSConstants.USERNAMETOKEN_NS,
WSConstants.USERNAME_TOKEN_LN), this);
+ profiles.put(new QName(WSConstants.WSSE_NS,
WSConstants.USERNAME_TOKEN_LN), this);
+ profiles.put(new QName(WSConstants.WSSE11_NS,
WSConstants.USERNAME_TOKEN_LN), this);
+ return createSecurityEngine(profiles);
+ }
+
+ public void handleToken(Element elem,
+ Crypto crypto,
+ Crypto decCrypto,
+ CallbackHandler cb,
+ WSDocInfo wsDocInfo,
+ Vector returnResults,
+ WSSConfig config) throws WSSecurityException {
+ new CustomUsernameTokenProcessor().handleToken(elem, crypto,
decCrypto, cb, wsDocInfo,
+ returnResults, config);
+ }
+
+
+ private class DelegatingCallbackHandler implements CallbackHandler {
+
+ private CallbackHandler pwdHandler;
+
+ public DelegatingCallbackHandler(CallbackHandler pwdHandler) {
+ this.pwdHandler = pwdHandler;
+ }
+
+ public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
+ for (Callback c : callbacks) {
+ if (c instanceof WSPasswordCallback) {
+ WSPasswordCallback pc = (WSPasswordCallback)c;
+ if (WSConstants.PASSWORD_TEXT.equals(pc.getPasswordType())
+ && pc.getUsage() ==
WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
+
AbstractWSS4JSecurityContextProvidingInterceptor.this.setSubject(
+ pc.getIdentifier(), pc.getPassword(), false, null,
null);
+ } else if (pwdHandler != null) {
+ pwdHandler.handle(callbacks);
+ }
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Custom UsernameTokenProcessor
+ * Unfortunately, WSS4J UsernameTokenProcessor makes it impossible to
+ * override its handleUsernameToken only.
+ *
+ */
+ private class CustomUsernameTokenProcessor implements Processor {
+
+ private String utId;
+ private UsernameToken ut;
+
+ @SuppressWarnings("unchecked")
+ public void handleToken(Element elem, Crypto crypto, Crypto decCrypto,
CallbackHandler cb,
+ WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws
WSSecurityException {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Found UsernameToken list element");
+ }
+
+ Principal principal = handleUsernameToken((Element) elem, cb);
+ returnResults.add(
+ 0,
+ new WSSecurityEngineResult(WSConstants.UT, principal, null,
null, null)
+ );
+ utId = ut.getID();
+ }
+
+ private WSUsernameTokenPrincipal handleUsernameToken(
+ Element token, CallbackHandler cb) throws WSSecurityException {
+ //
+ // Parse the UsernameToken element
+ //
+ ut = new UsernameToken(token, false);
+ String user = ut.getName();
+ String password = ut.getPassword();
+ String nonce = ut.getNonce();
+ String createdTime = ut.getCreated();
+ String pwType = ut.getPasswordType();
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("UsernameToken user " + user);
+ LOG.fine("UsernameToken password " + password);
+ }
+
+ AbstractWSS4JSecurityContextProvidingInterceptor.this.setSubject(
+ user, password, ut.isHashed(), nonce, createdTime);
+
+ WSUsernameTokenPrincipal principal = new
WSUsernameTokenPrincipal(user, ut.isHashed());
+ principal.setNonce(nonce);
+ principal.setPassword(password);
+ principal.setCreatedTime(createdTime);
+ principal.setPasswordType(pwType);
+
+ return principal;
+ }
+
+ public String getId() {
+ return utId;
+ }
+ }
+
+ /**
+ * Simple Principal implementation
+ *
+ */
+ protected static class SimplePrincipal implements Principal {
+
+ private String name;
+
+ public SimplePrincipal(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ }
+
+ /**
+ * Simple Group implementation
+ *
+ */
+ protected static class SimpleGroup extends SimplePrincipal implements
Group {
+
+ private String memberName;
+
+ public SimpleGroup(String roleName, String memberName) {
+ super(roleName);
+ this.memberName = memberName;
+ }
+
+ public boolean isMember(Principal p) {
+ return memberName.equals(p.getName());
+ }
+
+ public boolean addMember(Principal p) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Enumeration<? extends Principal> members() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeMember(Principal arg0) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
Propchange:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java?rev=931228&r1=931227&r2=931228&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java
Tue Apr 6 17:07:15 2010
@@ -396,21 +396,25 @@ public class WSS4JInInterceptor extends
msg.put(PRINCIPAL_RESULT, p);
SecurityContext sc = msg.get(SecurityContext.class);
if (sc == null || sc.getUserPrincipal() == null) {
- SecurityContext c = new SecurityContext() {
- public Principal getUserPrincipal() {
- return p;
- }
- public boolean isUserInRole(String role) {
- return false;
- }
- };
- msg.put(SecurityContext.class, c);
+ msg.put(SecurityContext.class, createSecurityContext(p));
break;
}
}
}
}
+
+ protected SecurityContext createSecurityContext(final Principal p) {
+ return new SecurityContext() {
+ public Principal getUserPrincipal() {
+ return p;
+ }
+ public boolean isUserInRole(String role) {
+ return false;
+ }
+ };
+ }
+
private String getAction(SoapMessage msg, SoapVersion version) {
String action = (String)getOption(WSHandlerConstants.ACTION);
if (action == null) {
@@ -461,7 +465,7 @@ public class WSS4JInInterceptor extends
}
- private CallbackHandler getCallback(RequestData reqData, int doAction)
throws WSSecurityException {
+ protected CallbackHandler getCallback(RequestData reqData, int doAction)
throws WSSecurityException {
/*
* To check a UsernameToken or to decrypt an encrypted message we need
a
* password.
@@ -519,7 +523,7 @@ public class WSS4JInInterceptor extends
* TODO the WSHandler base class defines secEngine to be static, which
* is really bad, because the engine has mutable state on it.
*/
- private WSSecurityEngine
+ protected WSSecurityEngine
getSecurityEngine() {
if (secEngineOverride != null) {
return secEngineOverride;
@@ -535,7 +539,7 @@ public class WSS4JInInterceptor extends
* TODO The WSS4J APIs leave something to be desired here, but hopefully
* we'll clean all this up in WSS4J-2.0
*/
- private static WSSecurityEngine
+ protected static WSSecurityEngine
createSecurityEngine(
final Map<QName, Object> map
) {
Added:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java?rev=931228&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
(added)
+++
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
Tue Apr 6 17:07:15 2010
@@ -0,0 +1,43 @@
+/**
+ * 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.ws.security.wss4j;
+
+import javax.security.auth.Subject;
+
+import org.apache.ws.security.WSSecurityException;
+
+public class SimpleSubjectCreatingInterceptor extends
AbstractWSS4JSecurityContextProvidingInterceptor {
+
+ @Override
+ protected Subject createSubject(String name,
+ String password,
+ boolean isDigest,
+ String nonce,
+ String created) throws WSSecurityException
{
+ Subject subject = new Subject();
+
+ // delegate to the external security system if possible
+
+ subject.getPrincipals().add(new SimplePrincipal(name));
+ subject.getPrincipals().add(new SimpleGroup("developers", name));
+ subject.setReadOnly();
+ return subject;
+ }
+
+}
Propchange:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java?rev=931228&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java
(added)
+++
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java
Tue Apr 6 17:07:15 2010
@@ -0,0 +1,183 @@
+/**
+ * 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.ws.security.wss4j;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.ws.BindingProvider;
+
+import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
+import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.interceptor.LoggingInInterceptor;
+import org.apache.cxf.interceptor.LoggingOutInterceptor;
+import org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor;
+import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
+import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.transport.local.LocalConduit;
+import org.apache.cxf.transport.local.LocalTransportFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.handler.WSHandlerConstants;
+
+import org.junit.Test;
+
+public class UserNameTokenAuthorizationTest extends AbstractSecurityTest {
+ private SimpleSubjectCreatingInterceptor wsIn;
+ private WSS4JOutInterceptor wsOut;
+ private Echo echo;
+ private Client client;
+
+ public void setUpService(List<String> expectedRoles,
+ boolean digest,
+ boolean encryptUsernameTokenOnly) throws
Exception {
+ JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
+ factory.setServiceBean(new EchoImpl());
+ factory.setAddress("local://Echo");
+ factory.setTransportId(LocalTransportFactory.TRANSPORT_ID);
+ Server server = factory.create();
+ Service service = server.getEndpoint().getService();
+
+ service.getInInterceptors().add(new SAAJInInterceptor());
+ service.getInInterceptors().add(new LoggingInInterceptor());
+ service.getOutInterceptors().add(new SAAJOutInterceptor());
+ service.getOutInterceptors().add(new LoggingOutInterceptor());
+
+ wsIn = new SimpleSubjectCreatingInterceptor();
+ wsIn.setSupportDigestPasswords(digest);
+ wsIn.setProperty(WSHandlerConstants.SIG_PROP_FILE,
"META-INF/cxf/insecurity.properties");
+ wsIn.setProperty(WSHandlerConstants.DEC_PROP_FILE,
"META-INF/cxf/insecurity.properties");
+ wsIn.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,
TestPwdCallback.class.getName());
+
+ service.getInInterceptors().add(wsIn);
+
+ SimpleAuthorizingInterceptor sai = new SimpleAuthorizingInterceptor();
+ sai.setMethodRolesMap(Collections.singletonMap("echo", expectedRoles));
+ service.getInInterceptors().add(sai);
+
+
+ wsOut = new WSS4JOutInterceptor();
+ wsOut.setProperty(WSHandlerConstants.SIG_PROP_FILE,
"META-INF/cxf/outsecurity.properties");
+ wsOut.setProperty(WSHandlerConstants.ENC_PROP_FILE,
"META-INF/cxf/outsecurity.properties");
+ wsOut.setProperty(WSHandlerConstants.USER, "myalias");
+ if (digest) {
+ wsOut.setProperty("password", "myAliasPassword");
+ } else {
+ wsOut.setProperty(WSHandlerConstants.PASSWORD_TYPE,
WSConstants.PW_TEXT);
+ }
+
+ if (encryptUsernameTokenOnly) {
+ wsOut.setProperty(WSHandlerConstants.ENCRYPTION_USER, "myalias");
+ wsOut.setProperty(
+ WSHandlerConstants.ENCRYPTION_PARTS,
+ "{Content}{" + WSConstants.WSSE_NS + "}UsernameToken"
+ );
+ }
+ wsOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,
TestPwdCallback.class.getName());
+ service.getOutInterceptors().add(wsOut);
+
+ // Create the client
+ JaxWsProxyFactoryBean proxyFac = new JaxWsProxyFactoryBean();
+ proxyFac.setServiceClass(Echo.class);
+ proxyFac.setAddress("local://Echo");
+
proxyFac.getClientFactoryBean().setTransportId(LocalTransportFactory.TRANSPORT_ID);
+
+ echo = (Echo)proxyFac.create();
+
+
((BindingProvider)echo).getRequestContext().put(LocalConduit.DIRECT_DISPATCH,
Boolean.TRUE);
+
+
+ client = ClientProxy.getClient(echo);
+
+ client.getInInterceptors().add(new LoggingInInterceptor());
+ client.getInInterceptors().add(wsIn);
+ client.getInInterceptors().add(new SAAJInInterceptor());
+ client.getOutInterceptors().add(new LoggingOutInterceptor());
+ client.getOutInterceptors().add(wsOut);
+ client.getOutInterceptors().add(new SAAJOutInterceptor());
+ }
+
+
+ @Test
+ public void testDigestPasswordAuthorized() throws Exception {
+ setUpService(Collections.singletonList("developers"), true, false);
+ String actions = WSHandlerConstants.ENCRYPT + " " +
WSHandlerConstants.SIGNATURE + " "
+ + WSHandlerConstants.TIMESTAMP + " " +
WSHandlerConstants.USERNAME_TOKEN;
+
+ wsIn.setProperty(WSHandlerConstants.ACTION, actions);
+
+ wsOut.setProperty(WSHandlerConstants.ACTION, actions);
+
+ assertEquals("test", echo.echo("test"));
+ }
+
+ @Test
+ public void testDigestPasswordUnauthorized() throws Exception {
+ setUpService(Collections.singletonList("managers"), true, false);
+ String actions = WSHandlerConstants.ENCRYPT + " " +
WSHandlerConstants.SIGNATURE + " "
+ + WSHandlerConstants.TIMESTAMP + " " +
WSHandlerConstants.USERNAME_TOKEN;
+
+ wsIn.setProperty(WSHandlerConstants.ACTION, actions);
+
+ wsOut.setProperty(WSHandlerConstants.ACTION, actions);
+
+ try {
+ echo.echo("test");
+ fail("Exception expected");
+ } catch (Exception ex) {
+ assertEquals("Unauthorized", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testEncryptedDigestPasswordAuthorized() throws Exception {
+ setUpService(Collections.singletonList("developers"), true, true);
+ String actions = WSHandlerConstants.USERNAME_TOKEN + " " +
WSHandlerConstants.ENCRYPT;
+
+ wsIn.setProperty(WSHandlerConstants.ACTION, actions);
+ wsOut.setProperty(WSHandlerConstants.ACTION, actions);
+
+ assertEquals("test", echo.echo("test"));
+ }
+
+ @Test
+ public void testClearPasswordAuthorized() throws Exception {
+ setUpService(Collections.singletonList("developers"), false, false);
+ String actions = WSHandlerConstants.USERNAME_TOKEN;
+
+ wsIn.setProperty(WSHandlerConstants.ACTION, actions);
+ wsOut.setProperty(WSHandlerConstants.ACTION, actions);
+
+ assertEquals("test", echo.echo("test"));
+ }
+
+ @Test
+ public void testEncyptedClearPasswordAuthorized() throws Exception {
+ setUpService(Collections.singletonList("developers"), false, true);
+ String actions = WSHandlerConstants.USERNAME_TOKEN + " " +
WSHandlerConstants.ENCRYPT;
+
+ wsIn.setProperty(WSHandlerConstants.ACTION, actions);
+ wsOut.setProperty(WSHandlerConstants.ACTION, actions);
+
+ assertEquals("test", echo.echo("test"));
+ }
+}
Propchange:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/UserNameTokenAuthorizationTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date