Adds new http interceptor to allow block access based on method type

Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/84a7cc3d
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/84a7cc3d
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/84a7cc3d

Branch: refs/heads/feature/http-interceptor
Commit: 84a7cc3da00cf84fdd67aef1cd2071840b687249
Parents: 2ae020c
Author: Lukasz Lenart <[email protected]>
Authored: Sat Apr 19 17:50:32 2014 +0200
Committer: Lukasz Lenart <[email protected]>
Committed: Sat Apr 19 17:50:32 2014 +0200

----------------------------------------------------------------------
 .../httpmethod/HttpMethodInterceptor.java       | 97 ++++++++++++++++++++
 1 file changed, 97 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/84a7cc3d/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java
 
b/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java
new file mode 100644
index 0000000..36efb52
--- /dev/null
+++ 
b/core/src/main/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptor.java
@@ -0,0 +1,97 @@
+package org.apache.struts2.interceptor.httpmethod;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import com.opensymphony.xwork2.util.AnnotationUtils;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.ServletActionContext;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class HttpMethodInterceptor extends AbstractInterceptor {
+
+    public static final Class[] HTTP_METHOD_ANNOTATIONS = { 
AllowedMethod.class, PostOnly.class, GetOnly.class, GetPostOnly.class };
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(HttpMethodInterceptor.class);
+
+    private String badRequestResultName = "bad-request";
+
+    @Override
+    public String intercept(ActionInvocation invocation) throws Exception {
+        Object action = invocation.getAction();
+        HttpServletRequest request = ServletActionContext.getRequest();
+        if (action instanceof HttpMethodAware) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Action #0 implements #1, setting request method #3",
+                        action, HttpMethodAware.class.getSimpleName(), 
request.getMethod());
+            }
+            ((HttpMethodAware) 
(action)).setMethod(HttpMethod.valueOf(request.getMethod()));
+        }
+        if (AnnotationUtils.isAnnotatedBy(action.getClass(), 
HTTP_METHOD_ANNOTATIONS)) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Action #0 annotated with #1, checking if request #2 
meets allowed methods!",
+                        action, AllowedMethod.class.getSimpleName(), 
request.getMethod());
+            }
+            return doIntercept(invocation);
+        }
+        return invocation.invoke();
+    }
+
+    protected String doIntercept(ActionInvocation invocation) throws Exception 
{
+        List<HttpMethod> allowedMethods = 
readAllowedMethods(invocation.getAction().getClass());
+        HttpServletRequest request = ServletActionContext.getRequest();
+        HttpMethod requestedMethod = HttpMethod.valueOf(request.getMethod());
+        if (allowedMethods.contains(requestedMethod)) {
+            if(LOG.isTraceEnabled()) {
+                LOG.trace("Request method #0 matches allowed methods #1, 
continuing invocation!", requestedMethod, allowedMethods);
+            }
+            return invocation.invoke();
+        } else {
+            if(LOG.isTraceEnabled()) {
+                LOG.trace("Request method #0 doesn't match allowed methods #1, 
continuing invocation!", requestedMethod, allowedMethods);
+            }
+            return getBadRequestResultName(invocation);
+        }
+    }
+
+    protected List<HttpMethod> readAllowedMethods(Class<? extends Object> 
klass) {
+        List<HttpMethod> allowedMethods = Collections.emptyList();
+        if (AnnotationUtils.isAnnotatedBy(klass, AllowedMethod.class)) {
+            allowedMethods = 
Arrays.asList(klass.getAnnotation(AllowedMethod.class).value());
+        }
+        if (AnnotationUtils.isAnnotatedBy(klass, GetOnly.class)) {
+            allowedMethods = 
Arrays.asList(klass.getAnnotation(GetOnly.class).value());
+        }
+        if (AnnotationUtils.isAnnotatedBy(klass, PostOnly.class)) {
+            allowedMethods = 
Arrays.asList(klass.getAnnotation(PostOnly.class).value());
+        }
+        if (AnnotationUtils.isAnnotatedBy(klass, GetPostOnly.class)) {
+            allowedMethods = 
Arrays.asList(klass.getAnnotation(GetPostOnly.class).value());
+        }
+        return Collections.unmodifiableList(allowedMethods);
+    }
+
+    protected String getBadRequestResultName(ActionInvocation invocation) {
+        Object action = invocation.getAction();
+        String resultName = badRequestResultName;
+        if (action instanceof HttpMethodAware) {
+            String actionResultName = ((HttpMethodAware) 
action).getBadRequestResultName();
+            if (actionResultName != null) {
+                resultName = actionResultName;
+            }
+        }
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Bad request result name is #0", resultName);
+        }
+        return resultName;
+    }
+
+    public void setBadRequestResultName(String badRequestResultName) {
+        this.badRequestResultName = badRequestResultName;
+    }
+
+}

Reply via email to