Author: sergeyb
Date: Mon Apr 12 17:07:19 2010
New Revision: 933326
URL: http://svn.apache.org/viewvc?rev=933326&view=rev
Log:
CXF-2754,CXF-2755: some refactoring, adding unit tests
Added:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
(with props)
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
(with props)
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
(with props)
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
(with props)
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
(with props)
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
(with props)
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
(with props)
Modified:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
Added:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
(added)
+++
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,91 @@
+/**
+ * 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.common.security;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Simple Group implementation
+ *
+ */
+public class SimpleGroup extends SimplePrincipal implements Group {
+
+ private Set<Principal> members = new HashSet<Principal>();
+
+ public SimpleGroup(String groupName) {
+ super(groupName);
+ }
+
+ public SimpleGroup(String groupName, String memberName) {
+ super(groupName);
+ members.add(new SimplePrincipal(memberName));
+ }
+
+ public SimpleGroup(String groupName, Principal member) {
+ super(groupName);
+ members.add(member);
+ }
+
+ public boolean isMember(Principal p) {
+ return members.contains(p);
+ }
+
+ public boolean addMember(Principal p) {
+ return members.add(p);
+ }
+
+ public Enumeration<? extends Principal> members() {
+
+ final Iterator<Principal> it = members.iterator();
+
+ return new Enumeration<Principal>() {
+
+ public boolean hasMoreElements() {
+ return it.hasNext();
+ }
+
+ public Principal nextElement() {
+ return it.next();
+ }
+
+ };
+ }
+
+ public boolean removeMember(Principal p) {
+ return members.remove(p);
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SimpleGroup)) {
+ return false;
+ }
+ SimpleGroup other = (SimpleGroup)obj;
+ return getName().equals(other.getName()) &&
members.equals(other.members);
+ }
+
+ public int hashCode() {
+ return getName().hashCode() + 37 * members.hashCode();
+ }
+}
+
Propchange:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
(added)
+++
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,57 @@
+/**
+ * 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.common.security;
+
+import java.security.Principal;
+
+/**
+ * Simple Principal implementation
+ *
+ */
+public class SimplePrincipal implements Principal {
+
+ private String name;
+
+ public SimplePrincipal(String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Principal name can not be
null");
+ }
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SimplePrincipal)) {
+ return false;
+ }
+
+ return name.equals(((SimplePrincipal)obj).name);
+ }
+
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ public String toString() {
+ return name;
+ }
+}
Propchange:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
(added)
+++
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,57 @@
+/**
+ * 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.common.security;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SimpleGroupTest extends Assert {
+
+ @Test
+ public void testName() {
+ assertEquals("group", new SimpleGroup("group", "friend").getName());
+ assertEquals("group", new SimpleGroup("group", new
SimplePrincipal("friend")).getName());
+ }
+
+ @Test
+ public void testIsMember() {
+ assertTrue(new SimpleGroup("group", "friend").isMember(new
SimplePrincipal("friend")));
+ assertFalse(new SimpleGroup("group", "friend").isMember(new
SimplePrincipal("frogs")));
+ }
+
+ @Test
+ public void testAddRemoveMembers() {
+
+ Group group = new SimpleGroup("group");
+ assertFalse(group.members().hasMoreElements());
+
+ group.addMember(new SimpleGroup("group", "friend"));
+
+ Enumeration<? extends Principal> members = group.members();
+ assertEquals(new SimpleGroup("group", "friend"),
members.nextElement());
+ assertFalse(members.hasMoreElements());
+
+ group.removeMember(new SimpleGroup("group", "friend"));
+ assertFalse(group.members().hasMoreElements());
+ }
+}
Propchange:
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
(added)
+++
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,39 @@
+/**
+ * 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.common.security;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SimplePrincipalTest extends Assert {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullName() {
+ new SimplePrincipal(null);
+ }
+
+ public void testEquals() {
+ assertEquals(new SimplePrincipal("barry"), new
SimplePrincipal("barry"));
+ }
+
+ public void testNotEquals() {
+ assertFalse(new SimplePrincipal("barry").equals(new
SimplePrincipal("john")));
+ }
+}
Propchange:
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
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=933326&r1=933325&r2=933326&view=diff
==============================================================================
---
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
(original)
+++
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
Mon Apr 12 17:07:19 2010
@@ -19,6 +19,7 @@
package org.apache.cxf.interceptor.security;
import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.List;
import org.apache.cxf.frontend.MethodDispatcher;
@@ -32,6 +33,9 @@ import org.apache.cxf.service.model.Bind
public abstract class AbstractAuthorizingInInterceptor extends
AbstractPhaseInterceptor<Message> {
+ private static final String ALL_ROLES = "*";
+
+
public AbstractAuthorizingInInterceptor() {
super(Phase.PRE_INVOKE);
}
@@ -44,17 +48,10 @@ public abstract class AbstractAuthorizin
Method method = getTargetMethod(message);
- List<String> expectedRoles = getExpectedRoles(method);
- if (expectedRoles == null || expectedRoles.isEmpty()) {
+ if (authorize(sc, method)) {
return;
}
- for (String role : expectedRoles) {
- if (sc.isUserInRole(role)) {
- return;
- }
- }
-
throw new AccessDeniedException("Unauthorized");
}
@@ -65,5 +62,50 @@ public abstract class AbstractAuthorizin
return md.getMethod(bop);
}
+ protected boolean authorize(SecurityContext sc, Method method) {
+ List<String> expectedRoles = getExpectedRoles(method);
+ if (expectedRoles.isEmpty()) {
+
+ List<String> denyRoles = getDenyRoles(method);
+
+ return denyRoles.isEmpty() ? true : isUserInRole(sc, denyRoles,
true);
+ }
+
+ if (isUserInRole(sc, expectedRoles, false)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isUserInRole(SecurityContext sc, List<String> roles,
boolean deny) {
+
+ if (roles.size() == 1 && ALL_ROLES.equals(roles.get(0))) {
+ return !deny;
+ }
+
+ for (String role : roles) {
+ if (sc.isUserInRole(role)) {
+ return !deny;
+ }
+ }
+ return deny;
+ }
+
+ /**
+ * Returns a list of expected roles for a given method.
+ * @param method Method
+ * @return list, empty if no roles are available
+ */
protected abstract List<String> getExpectedRoles(Method method);
+
+
+ /**
+ * Returns a list of roles to be denied for a given method.
+ * @param method Method
+ * @return list, empty if no roles are available
+ */
+ protected List<String> getDenyRoles(Method method) {
+ return Collections.emptyList();
+ }
}
Modified:
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=933326&r1=933325&r2=933326&view=diff
==============================================================================
---
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
(original)
+++
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
Mon Apr 12 17:07:19 2010
@@ -19,23 +19,24 @@
package org.apache.cxf.interceptor.security;
import java.lang.reflect.Method;
+import java.util.Collections;
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;
+ private Map<String, List<String>> methodRolesMap = Collections.emptyMap();
+ private List<String> globalRoles = Collections.emptyList();
@Override
protected List<String> getExpectedRoles(Method method) {
List<String> roles = methodRolesMap.get(method.getName());
- if (roles != null || classRolesMap == null) {
+ if (roles != null) {
return roles;
}
- return methodRolesMap.get(method.getDeclaringClass().getName());
+ return globalRoles;
}
@@ -44,8 +45,8 @@ public class SimpleAuthorizingIntercepto
this.methodRolesMap = rolesMap;
}
- public void setClassRolesMap(Map<String, List<String>> rolesMap) {
- this.classRolesMap = rolesMap;
+ public void setGlobalRoles(List<String> roles) {
+ globalRoles = roles;
}
Added:
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
(added)
+++
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,173 @@
+/**
+ * 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.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cxf.frontend.MethodDispatcher;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.easymock.classextension.EasyMock;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SimpleAuthorizingInterceptorTest extends Assert {
+
+ private Method method;
+ private Message message = new MessageImpl();
+
+ @Before
+ public void setUp() throws Exception {
+ method = TestService.class.getMethod("echo", new Class[]{});
+ message.put(SecurityContext.class, new TestSecurityContext());
+ Exchange ex = new ExchangeImpl();
+ message.setExchange(ex);
+
+ Service service = EasyMock.createMock(Service.class);
+ ex.put(Service.class, service);
+ MethodDispatcher md = EasyMock.createMock(MethodDispatcher.class);
+ service.get(MethodDispatcher.class.getName());
+ EasyMock.expectLastCall().andReturn(md);
+
+ BindingOperationInfo boi =
EasyMock.createMock(BindingOperationInfo.class);
+ ex.put(BindingOperationInfo.class, boi);
+ md.getMethod(boi);
+ EasyMock.expectLastCall().andReturn(method);
+ EasyMock.replay(service, md);
+ }
+
+ @Test
+ public void testPermitWithNoRoles() {
+ new SimpleAuthorizingInterceptor().handleMessage(message);
+ }
+
+ @Test
+ public void testPermitWithMethodRoles() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor();
+ List<String> roles = new ArrayList<String>();
+ roles.add("role1");
+ roles.add("testRole");
+ in.setMethodRolesMap(Collections.singletonMap("echo", roles));
+ in.handleMessage(message);
+ }
+
+ @Test
+ public void testPermitAll() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor();
+ List<String> roles = new ArrayList<String>();
+ roles.add("*");
+ in.setMethodRolesMap(Collections.singletonMap("echo", roles));
+ in.handleMessage(message);
+ }
+
+ @Test
+ public void testPermitWithClassRoles() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor();
+ List<String> roles = new ArrayList<String>();
+ roles.add("role1");
+ roles.add("testRole");
+ in.setGlobalRoles(roles);
+ in.handleMessage(message);
+ }
+
+ @Test(expected = AccessDeniedException.class)
+ public void testDenyWithMethodRoles() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor();
+ List<String> roles = new ArrayList<String>();
+ roles.add("role1");
+ roles.add("role2");
+ in.setMethodRolesMap(Collections.singletonMap("echo", roles));
+ in.handleMessage(message);
+ }
+
+ @Test(expected = AccessDeniedException.class)
+ public void testDenyWithClassRoles() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor();
+ List<String> roles = new ArrayList<String>();
+ roles.add("role1");
+ roles.add("role2");
+ in.setGlobalRoles(roles);
+ in.handleMessage(message);
+ }
+
+ @Test
+ public void testPermitWithDenyRoles() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor() {
+ @Override
+ public List<String> getDenyRoles(Method m) {
+ return Collections.singletonList("frogs");
+ }
+
+ };
+ in.handleMessage(message);
+ }
+
+ @Test(expected = AccessDeniedException.class)
+ public void testDenyWithDenyRoles() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor() {
+ @Override
+ public List<String> getDenyRoles(Method m) {
+ return Collections.singletonList("testRole");
+ }
+
+ };
+ in.handleMessage(message);
+ }
+
+ @Test(expected = AccessDeniedException.class)
+ public void testDenyAll() {
+ SimpleAuthorizingInterceptor in = new SimpleAuthorizingInterceptor() {
+ @Override
+ public List<String> getDenyRoles(Method m) {
+ return Collections.singletonList("*");
+ }
+
+ };
+ in.handleMessage(message);
+ }
+
+ private static class TestService {
+ public void echo() {
+
+ }
+ }
+
+ private static class TestSecurityContext implements SecurityContext {
+
+ public Principal getUserPrincipal() {
+ return null;
+ }
+
+ public boolean isUserInRole(String role) {
+ return "testRole".equals(role);
+ }
+
+ }
+}
Propchange:
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
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=933326&r1=933325&r2=933326&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
(original)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
Mon Apr 12 17:07:19 2010
@@ -20,8 +20,6 @@ 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;
@@ -36,9 +34,9 @@ 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.phase.PhaseInterceptorChain;
import org.apache.cxf.security.SecurityContext;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSDocInfo;
@@ -77,7 +75,6 @@ public abstract class AbstractWSS4JSecur
private static final Logger LOG =
LogUtils.getL7dLogger(AbstractWSS4JSecurityContextProvidingInterceptor.class);
- private ThreadLocal<Message> messages = new ThreadLocal<Message>();
private boolean supportDigestPasswords;
public AbstractWSS4JSecurityContextProvidingInterceptor() {
@@ -92,48 +89,48 @@ public abstract class AbstractWSS4JSecur
supportDigestPasswords = support;
}
- @Override
- public void handleFault(SoapMessage m) {
- messages.remove();
- super.handleFault(m);
- }
+
@Override
protected SecurityContext createSecurityContext(final Principal p) {
- Message msg = messages.get();
+ Message msg = PhaseInterceptorChain.getCurrentMessage();
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;
- }
- };
+ return doCreateSecurityContext(p, msg.get(Subject.class));
+ }
+
+ /**
+ * Creates default SecurityContext which implements isUserInRole using the
+ * following approach : skip the first Subject principal, and then check
optional
+ * Groups the principal is a member of. Subclasses can override this
method and implement
+ * a custom strategy instead
+ *
+ * @param p principal
+ * @param subject subject
+ * @return security context
+ */
+ protected SecurityContext doCreateSecurityContext(final Principal p, final
Subject subject) {
+ return new DefaultSecurityContext(p, subject);
}
+
protected void setSubject(String name,
String password,
boolean isDigest,
String nonce,
String created) throws WSSecurityException {
- Message msg = messages.get();
+ Message msg = PhaseInterceptorChain.getCurrentMessage();
if (msg == null) {
throw new IllegalStateException("Current message is not
available");
}
- Subject subject = createSubject(name, password, isDigest, nonce,
created);
+ Subject subject = null;
+ try {
+ subject = createSubject(name, password, isDigest, nonce, created);
+ } catch (Exception ex) {
+ throw new
WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION,
+ "Subject has not been created",
null, ex);
+ }
if (subject == null || subject.getPrincipals().size() == 0
||
!subject.getPrincipals().iterator().next().getName().equals(name)) {
throw new
WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION, null, null);
@@ -144,20 +141,21 @@ public abstract class AbstractWSS4JSecur
/**
* 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.
+ * and optionally followed by one or more principal Groups this user is a
member of.
+ * It will also be available in doCreateSecurityContext.
* @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
+ * @throws SecurityException
*/
protected abstract Subject createSubject(String name,
String password,
boolean isDigest,
String nonce,
- String created) throws WSSecurityException;
+ String created) throws SecurityException;
/**
@@ -168,20 +166,16 @@ public abstract class AbstractWSS4JSecur
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);
+ if ((doAction & WSConstants.UT) != 0 && !supportDigestPasswords) {
+ CallbackHandler pwdCallback = null;
+ try {
+ pwdCallback = super.getCallback(reqData, doAction);
+ } catch (Exception ex) {
+ // ignore
}
+ return new DelegatingCallbackHandler(pwdCallback);
}
-
return super.getCallback(reqData, doAction);
}
@@ -294,51 +288,4 @@ public abstract class AbstractWSS4JSecur
}
}
- /**
- * 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();
- }
- }
}
Added:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
(added)
+++
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,76 @@
+/**
+ * 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.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+
+import javax.security.auth.Subject;
+
+import org.apache.cxf.security.SecurityContext;
+
+/**
+ * SecurityContext which implements isUserInRole using the
+ * following approach : skip the first Subject principal, and then checks
+ * Groups the principal is a member of
+ *
+ * TODO : consider moving this class into common/security
+ */
+public class DefaultSecurityContext implements SecurityContext {
+
+ private Principal p;
+ private Subject subject;
+
+ public DefaultSecurityContext(Principal p, Subject subject) {
+ this.p = p;
+ this.subject = subject;
+ }
+
+ public Principal getUserPrincipal() {
+ return p;
+ }
+ public boolean isUserInRole(String role) {
+ if (subject == null || subject.getPrincipals().size() <= 1) {
+ return false;
+ }
+ for (Principal principal : subject.getPrincipals()) {
+ if (principal instanceof Group && checkGroup((Group)principal,
role)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean checkGroup(Group group, String role) {
+ if (group.getName().equals(role)) {
+ return true;
+ }
+
+ for (Enumeration<? extends Principal> members = group.members();
members.hasMoreElements();) {
+ // this might be a plain role but could represent a group
consisting of the pther groups/roles
+ Principal member = members.nextElement();
+ if (member.getName().equals(role)
+ || member instanceof Group && checkGroup((Group)member, role))
{
+ return true;
+ }
+ }
+ return false;
+ }
+}
Propchange:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java?rev=933326&view=auto
==============================================================================
---
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
(added)
+++
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
Mon Apr 12 17:07:19 2010
@@ -0,0 +1,75 @@
+/**
+ * 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.security.Principal;
+import java.security.acl.Group;
+
+import javax.security.auth.Subject;
+
+import org.apache.cxf.common.security.SimpleGroup;
+import org.apache.cxf.common.security.SimplePrincipal;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class DefaultSecurityContextTest extends Assert {
+
+ @Test
+ public void testUserNotInRole() {
+ Subject s = new Subject();
+ Principal p = new SimplePrincipal("Barry");
+ s.getPrincipals().add(p);
+ assertFalse(new DefaultSecurityContext(p, s).isUserInRole("friend"));
+ }
+
+ @Test
+ public void testUserInRole() {
+ Subject s = new Subject();
+ Principal p = new SimplePrincipal("Barry");
+ s.getPrincipals().add(p);
+ s.getPrincipals().add(new SimpleGroup("friend", p));
+ assertTrue(new DefaultSecurityContext(p, s).isUserInRole("friend"));
+ }
+
+ @Test
+ public void testUserInRole2() {
+ Subject s = new Subject();
+ Principal p = new SimplePrincipal("Barry");
+ s.getPrincipals().add(p);
+ Group group = new SimpleGroup("Roles", p);
+ group.addMember(new SimpleGroup("friend"));
+ s.getPrincipals().add(group);
+ assertTrue(new DefaultSecurityContext(p, s).isUserInRole("friend"));
+ }
+
+ @Test
+ public void testUserInRole3() {
+ Subject s = new Subject();
+ Principal p = new SimplePrincipal("Barry");
+ s.getPrincipals().add(p);
+ Group group = new SimpleGroup("Roles", p);
+ Group subgroup = new SimpleGroup("subgroup");
+ subgroup.addMember(new SimpleGroup("friend"));
+ group.addMember(subgroup);
+ s.getPrincipals().add(group);
+ assertTrue(new DefaultSecurityContext(p, s).isUserInRole("friend"));
+ }
+
+}
Propchange:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
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=933326&r1=933325&r2=933326&view=diff
==============================================================================
---
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
(original)
+++
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
Mon Apr 12 17:07:19 2010
@@ -20,7 +20,8 @@ package org.apache.cxf.ws.security.wss4j
import javax.security.auth.Subject;
-import org.apache.ws.security.WSSecurityException;
+import org.apache.cxf.common.security.SimpleGroup;
+import org.apache.cxf.common.security.SimplePrincipal;
public class SimpleSubjectCreatingInterceptor extends
AbstractWSS4JSecurityContextProvidingInterceptor {
@@ -29,7 +30,7 @@ public class SimpleSubjectCreatingInterc
String password,
boolean isDigest,
String nonce,
- String created) throws WSSecurityException
{
+ String created) throws SecurityException {
Subject subject = new Subject();
// delegate to the external security system if possible