Author: sergeyb
Date: Tue Dec 7 22:55:18 2010
New Revision: 1043225
URL: http://svn.apache.org/viewvc?rev=1043225&view=rev
Log:
[CXF-3172] Adding SecureAnnotationsInterceptor
Added:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java
(with props)
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptorTest.java
(with props)
Modified:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
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=1043225&r1=1043224&r2=1043225&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
Tue Dec 7 22:55:18 2010
@@ -55,11 +55,18 @@ public abstract class AbstractAuthorizin
throw new AccessDeniedException("Unauthorized");
}
- private Method getTargetMethod(Message m) {
+ protected 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);
+ if (bop != null) {
+ MethodDispatcher md = (MethodDispatcher)
+
m.getExchange().get(Service.class).get(MethodDispatcher.class.getName());
+ return md.getMethod(bop);
+ }
+ Method method = (Method)m.get("org.apache.cxf.resource.method");
+ if (method != null) {
+ return method;
+ }
+ throw new AccessDeniedException("Method is not available :
Unauthorized");
}
protected boolean authorize(SecurityContext sc, Method method) {
Added:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java?rev=1043225&view=auto
==============================================================================
---
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java
(added)
+++
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java
Tue Dec 7 22:55:18 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.interceptor.security;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+
+
+public class SecureAnnotationsInterceptor extends SimpleAuthorizingInterceptor
{
+
+ private static final String DEFAULT_ANNOTATION_CLASS_NAME =
"javax.annotation.security.RolesAllowed";
+
+ private static final Set<String> SKIP_METHODS;
+ static {
+ SKIP_METHODS = new HashSet<String>();
+ SKIP_METHODS.addAll(Arrays.asList(
+ new String[] {"wait", "notify", "notifyAll",
+ "equals", "toString", "hashCode"}));
+ }
+
+ private String annotationClassName = DEFAULT_ANNOTATION_CLASS_NAME;
+
+ public void setAnnotationClassName(String name) {
+ try {
+ ClassLoaderUtils.loadClass(name,
SecureAnnotationsInterceptor.class);
+ annotationClassName = name;
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ throw new IllegalArgumentException("Annotation class " + name + "
is not available");
+ }
+ }
+
+ public void setSecuredObject(Object object) {
+ Class<?> cls = object.getClass();
+ String classRolesAllowed = getRoles(cls.getAnnotations(),
annotationClassName);
+
+ Map<String, String> rolesMap = new HashMap<String, String>();
+ for (Method m : cls.getMethods()) {
+ if (SKIP_METHODS.contains(m.getName())) {
+ continue;
+ }
+ String methodRolesAllowed = getRoles(m.getAnnotations(),
annotationClassName);
+ String theRoles = methodRolesAllowed != null ? methodRolesAllowed
: classRolesAllowed;
+ if (theRoles != null) {
+ rolesMap.put(m.getName(), theRoles);
+ }
+ }
+ super.setMethodRolesMap(rolesMap);
+
+ }
+
+ private String getRoles(Annotation[] anns, String annName) {
+ for (Annotation ann : anns) {
+ if (ann.annotationType().getName().equals(annName)) {
+ try {
+ Method valueMethod =
ann.annotationType().getMethod("value", new Class[]{});
+ String[] roles = (String[])valueMethod.invoke(ann, new
Object[]{});
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < roles.length; i++) {
+ sb.append(roles[i]);
+ if (i + 1 < roles.length) {
+ sb.append(" ");
+ }
+ }
+ return sb.toString();
+ } catch (Exception ex) {
+ // ignore
+ }
+ break;
+ }
+ }
+ return null;
+ }
+}
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptorTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptorTest.java?rev=1043225&view=auto
==============================================================================
---
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptorTest.java
(added)
+++
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptorTest.java
Tue Dec 7 22:55:18 2010
@@ -0,0 +1,122 @@
+/**
+ * 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.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import java.lang.reflect.Method;
+import java.security.Principal;
+
+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 SecureAnnotationsInterceptorTest 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 SecureAnnotationsInterceptor().handleMessage(message);
+ }
+
+ @Test
+ public void testPermitWithMethodRoles() {
+ SecureAnnotationsInterceptor in = new SecureAnnotationsInterceptor();
+ in.setAnnotationClassName(SecureRolesAllowed.class.getName());
+ in.setSecuredObject(new TestService());
+ in.handleMessage(message);
+ }
+
+ @Test(expected = AccessDeniedException.class)
+ public void testAccessDeniedMethodRoles() {
+ SecureAnnotationsInterceptor in = new SecureAnnotationsInterceptor();
+ in.setAnnotationClassName(SecureRolesAllowed.class.getName());
+ in.setSecuredObject(new TestService2());
+ in.handleMessage(message);
+ }
+
+
+ @Retention (RetentionPolicy.RUNTIME)
+ @Target({ElementType.TYPE, ElementType.METHOD })
+ public @interface SecureRolesAllowed {
+ String[] value();
+ }
+
+ private static class TestService {
+ @SuppressWarnings("unused")
+ @SecureRolesAllowed("testRole")
+ public void echo() {
+ }
+ }
+
+ private static class TestService2 {
+ @SuppressWarnings("unused")
+ @SecureRolesAllowed("baz")
+ 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/SecureAnnotationsInterceptorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/core/src/test/java/org/apache/cxf/interceptor/security/SecureAnnotationsInterceptorTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date