Author: sergeyb
Date: Mon Apr 12 17:20:11 2010
New Revision: 933329
URL: http://svn.apache.org/viewvc?rev=933329&view=rev
Log:
Merged revisions 933326 via svnmerge from
https://svn.apache.org/repos/asf/cxf/trunk
........
r933326 | sergeyb | 2010-04-12 18:07:19 +0100 (Mon, 12 Apr 2010) | 1 line
CXF-2754,CXF-2755: some refactoring, adding unit tests
........
Added:
cxf/branches/2.2.x-fixes/common/common/src/main/java/org/apache/cxf/common/security/
- copied from r933326,
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/
cxf/branches/2.2.x-fixes/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
- copied unchanged from r933326,
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimpleGroup.java
cxf/branches/2.2.x-fixes/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
- copied unchanged from r933326,
cxf/trunk/common/common/src/main/java/org/apache/cxf/common/security/SimplePrincipal.java
cxf/branches/2.2.x-fixes/common/common/src/test/java/org/apache/cxf/common/security/
- copied from r933326,
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/
cxf/branches/2.2.x-fixes/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
- copied unchanged from r933326,
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimpleGroupTest.java
cxf/branches/2.2.x-fixes/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
- copied unchanged from r933326,
cxf/trunk/common/common/src/test/java/org/apache/cxf/common/security/SimplePrincipalTest.java
cxf/branches/2.2.x-fixes/rt/core/src/test/java/org/apache/cxf/interceptor/security/
- copied from r933326,
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/
cxf/branches/2.2.x-fixes/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
- copied unchanged from r933326,
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
- copied unchanged from r933326,
cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContext.java
cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
- copied unchanged from r933326,
cxf/trunk/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/DefaultSecurityContextTest.java
Modified:
cxf/branches/2.2.x-fixes/ (props changed)
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
Propchange: cxf/branches/2.2.x-fixes/
------------------------------------------------------------------------------
svn:mergeinfo = /cxf/trunk:933326
Propchange: cxf/branches/2.2.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.
Modified:
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff
==============================================================================
---
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
(original)
+++
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
Mon Apr 12 17:20:11 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/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff
==============================================================================
---
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
(original)
+++
cxf/branches/2.2.x-fixes/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
Mon Apr 12 17:20:11 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;
}
Modified:
cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff
==============================================================================
---
cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
(original)
+++
cxf/branches/2.2.x-fixes/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
Mon Apr 12 17:20:11 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();
- }
- }
}
Modified:
cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java?rev=933329&r1=933328&r2=933329&view=diff
==============================================================================
---
cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
(original)
+++
cxf/branches/2.2.x-fixes/rt/ws/security/src/test/java/org/apache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java
Mon Apr 12 17:20:11 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