You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by rw...@apache.org on 2014/12/23 16:30:16 UTC
svn commit: r1647594 - in
/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src:
main/java/org/apache/jetspeed/pipeline/valve/
main/java/org/apache/jetspeed/pipeline/valve/impl/
test/java/org/apache/jetspeed/container/state/ test/java/org/apa...
Author: rwatler
Date: Tue Dec 23 15:30:15 2014
New Revision: 1647594
URL: http://svn.apache.org/r1647594
Log:
JS2-1309: New request filtering and security utility valves.
Added:
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/RequestFilterValve.java
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/AbstractFilterValveImpl.java
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/RequestFilterValveImpl.java
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/SimpleSecurityValveImpl.java
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestRequestFilterValve.java
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestSimpleSecurityValve.java
Modified:
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/RequestFilterValve.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/RequestFilterValve.java?rev=1647594&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/RequestFilterValve.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/RequestFilterValve.java Tue Dec 23 15:30:15 2014
@@ -0,0 +1,28 @@
+/*
+ * 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.jetspeed.pipeline.valve;
+
+/**
+ * This valve filters incoming requests, sending a NOT_FOUND response
+ * to requests that are filtered.
+ *
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id:$
+ */
+public interface RequestFilterValve extends Valve {
+}
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/AbstractFilterValveImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/AbstractFilterValveImpl.java?rev=1647594&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/AbstractFilterValveImpl.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/AbstractFilterValveImpl.java Tue Dec 23 15:30:15 2014
@@ -0,0 +1,117 @@
+/*
+ * 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.jetspeed.pipeline.valve.impl;
+
+import org.apache.jetspeed.pipeline.valve.AbstractValve;
+import org.springframework.util.AntPathMatcher;
+
+import java.util.List;
+
+/**
+ * Abstract valve implementation supporting request path includes
+ * and excludes.
+ *
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id:$
+ */
+public abstract class AbstractFilterValveImpl extends AbstractValve {
+
+ private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
+
+ /** List of Ant style expression include request path patterns. */
+ private List<String> includes;
+
+ /** List of Ant style expression exclude request path patterns. */
+ private List<String> excludes;
+
+ /**
+ * Test request path against includes.
+ *
+ * @param requestPath request path
+ * @return included result
+ */
+ protected boolean includesRequestPath(String requestPath) {
+ // assume request included if no includes are specified
+ if ((includes == null) || includes.isEmpty()) {
+ return true;
+ }
+ // test includes
+ for (String include : includes) {
+ if (PATH_MATCHER.match(include, requestPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test request path against excludes.
+ *
+ * @param requestPath request path
+ * @return excluded result
+ */
+ protected boolean excludesRequestPath(String requestPath) {
+ // assume request not excluded if no excludes are specified
+ if ((excludes == null) || excludes.isEmpty()) {
+ return false;
+ }
+ // test excludes
+ for (String exclude : excludes) {
+ if (PATH_MATCHER.match(exclude, requestPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get list of include request path patterns.
+ *
+ * @return list of Ant style expression include patterns
+ */
+ public List<String> getIncludes() {
+ return includes;
+ }
+
+ /**
+ * Set list of include request path patterns.
+ *
+ * @param includes list of Ant style expression include patterns
+ */
+ public void setIncludes(List<String> includes) {
+ this.includes = includes;
+ }
+
+ /**
+ * Get list of exclude request path patterns.
+ *
+ * @return list of Ant style expression exclude patterns
+ */
+ public List<String> getExcludes() {
+ return excludes;
+ }
+
+ /**
+ * Set list of exclude request path patterns.
+ *
+ * @param excludes list of Ant style expression exclude patterns
+ */
+ public void setExcludes(List<String> excludes) {
+ this.excludes = excludes;
+ }
+}
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/RequestFilterValveImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/RequestFilterValveImpl.java?rev=1647594&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/RequestFilterValveImpl.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/RequestFilterValveImpl.java Tue Dec 23 15:30:15 2014
@@ -0,0 +1,86 @@
+/*
+ * 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.jetspeed.pipeline.valve.impl;
+
+import org.apache.jetspeed.pipeline.PipelineException;
+import org.apache.jetspeed.pipeline.valve.RequestFilterValve;
+import org.apache.jetspeed.pipeline.valve.ValveContext;
+import org.apache.jetspeed.request.RequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * This valve implementation filters incoming requests, sending a NOT_FOUND
+ * response to requests that are filtered.
+ *
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id:$
+ */
+public class RequestFilterValveImpl extends AbstractFilterValveImpl implements RequestFilterValve {
+
+ private static final Logger log = LoggerFactory.getLogger(RequestFilterValveImpl.class);
+
+ /** Valve name. */
+ private String name;
+
+ /**
+ * Named valve constructor.
+ *
+ * @param name name of valve
+ */
+ public RequestFilterValveImpl(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void invoke(RequestContext request, ValveContext context) throws PipelineException {
+
+ // get request path relative to pipeline/servlet path
+ String requestPath = request.getRequest().getPathInfo();
+
+ // test request path includes and excludes
+ if (!includesRequestPath(requestPath) || excludesRequestPath(requestPath)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Request filtered by " + request.getPipeline().getName() + "." + name + " request path: " + requestPath);
+ }
+ try {
+ request.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND);
+ } catch (IOException ioe) {
+ if (log.isDebugEnabled()) {
+ log.error("Unexpected exception sending error for filtered request, (" + requestPath + "): " + ioe, ioe);
+ }
+ }
+ return;
+ }
+
+ // continue valve execution on pipeline
+ context.invokeNext(request);
+ }
+
+ /**
+ * Get valve name.
+ *
+ * @return valve name
+ */
+ public String getName() {
+ return name;
+ }
+}
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/SimpleSecurityValveImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/SimpleSecurityValveImpl.java?rev=1647594&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/SimpleSecurityValveImpl.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/pipeline/valve/impl/SimpleSecurityValveImpl.java Tue Dec 23 15:30:15 2014
@@ -0,0 +1,305 @@
+/*
+ * 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.jetspeed.pipeline.valve.impl;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.jetspeed.pipeline.PipelineException;
+import org.apache.jetspeed.pipeline.valve.SecurityValve;
+import org.apache.jetspeed.pipeline.valve.ValveContext;
+import org.apache.jetspeed.request.RequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This valve implementation filters incoming requests based on simple HTTP Basic
+ * Authentication and/or Remote IP Address.
+ *
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id:$
+ */
+public class SimpleSecurityValveImpl extends AbstractFilterValveImpl implements SecurityValve {
+
+ private static final Logger log = LoggerFactory.getLogger(SimpleSecurityValveImpl.class);
+
+ public static final String HTTP_AUTHORIZATION_HEADER = "Authorization";
+ public static final String HTTP_WWW_AUTHENTICATE_HEADER = "WWW-Authenticate";
+
+ private static final String DEFAULT_AUTHENTICATION_REALM = "Jetspeed Portal";
+
+ /** Valve name. */
+ private String name;
+
+ /** HTTP Basic Authentication realm. */
+ private String authenticationRealm;
+
+ /** HTTP Basic Authentication username. */
+ private String authenticationUser;
+
+ /** HTTP Basic Authentication password MD5 HEX hash. */
+ private String authenticationPasswordHash;
+
+ /** Valid IP addresses and/or subnets. */
+ private List<String> validIPAddresses;
+
+ /** Parsed valid IP addresses. */
+ private List<ValidIPAddress> parsedValidIPAddresses = new ArrayList<ValidIPAddress>();
+
+ /**
+ * Named valve constructor.
+ *
+ * @param name name of valve
+ */
+ public SimpleSecurityValveImpl(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void invoke(RequestContext request, ValveContext context) throws PipelineException {
+
+ // get request path relative to pipeline/servlet path
+ String requestPath = request.getRequest().getPathInfo();
+
+ // test request path includes and excludes
+ if (includesRequestPath(requestPath) && !excludesRequestPath(requestPath)) {
+
+ // check HTTP Basic Authentication
+ if (authenticationRealm != null) {
+ boolean authorized = false;
+ String authorizationHeader = request.getRequest().getHeader(HTTP_AUTHORIZATION_HEADER);
+ if ((authorizationHeader != null) && (authorizationHeader.startsWith("Basic "))) {
+ authorizationHeader = authorizationHeader.substring(6);
+ try {
+ authorizationHeader = new String(Base64.decodeBase64(authorizationHeader), "UTF-8");
+ } catch (Exception e) {
+ authorizationHeader = null;
+ }
+ if ((authorizationHeader != null) && !authorizationHeader.isEmpty()) {
+ String[] authorizationCredentials = authorizationHeader.split(":");
+ if ((authorizationCredentials.length == 2) && authenticationUser.equals(authorizationCredentials[0])) {
+ String authorizationCredentialsPasswordHash = DigestUtils.md5Hex(authorizationCredentials[1]);
+ authorized = authorizationCredentialsPasswordHash.equalsIgnoreCase(authenticationPasswordHash);
+ }
+ }
+ }
+ if (!authorized) {
+ if (log.isDebugEnabled()) {
+ log.debug("Request filtered by " + request.getPipeline().getName() + "." + name + " authorization: " + authorizationHeader);
+ }
+ try {
+ request.getResponse().setHeader(HTTP_WWW_AUTHENTICATE_HEADER, "Basic realm=\"" + authenticationRealm + "\"");
+ request.getResponse().sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ } catch (IOException ioe) {
+ if (log.isDebugEnabled()) {
+ log.error("Unexpected exception sending error for filtered request, (" + request.getRequest().getPathInfo() + "): " + ioe, ioe);
+ }
+ }
+ return;
+ }
+ }
+
+ // check valid remote IP address
+ if (!parsedValidIPAddresses.isEmpty()) {
+ String remoteIPAddress = request.getRequest().getRemoteAddr();
+ boolean valid = false;
+ try {
+ int remoteIP = getIP(remoteIPAddress);
+ for (ValidIPAddress validIPAddress : parsedValidIPAddresses) {
+ if (validIPAddress.matchIP(remoteIP)) {
+ valid = true;
+ break;
+ }
+ }
+ } catch (Exception e) {
+ }
+ if (!valid) {
+ if (log.isDebugEnabled()) {
+ log.debug("Request filtered by " + request.getPipeline().getName() + "." + name + " IP address: " + remoteIPAddress);
+ }
+ try {
+ request.getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
+ } catch (IOException ioe) {
+ if (log.isDebugEnabled()) {
+ log.error("Unexpected exception sending error for filtered request, (" + request.getRequest().getPathInfo() + "): " + ioe, ioe);
+ }
+ }
+ return;
+ }
+ }
+ }
+
+ // continue valve execution on pipeline
+ context.invokeNext(request);
+ }
+
+ @Override
+ public void initialize() throws PipelineException {
+
+ // validate HTTP Basic Authentication configuration
+ if ((authenticationUser != null) && !authenticationUser.isEmpty() && (authenticationPasswordHash != null) && !authenticationPasswordHash.isEmpty()) {
+ if ((authenticationRealm == null) || authenticationRealm.isEmpty()) {
+ authenticationRealm = DEFAULT_AUTHENTICATION_REALM;
+ }
+ } else {
+ authenticationRealm = null;
+ authenticationUser = null;
+ authenticationPasswordHash = null;
+ }
+
+ // setup valid IP addresses configuration
+ if ((validIPAddresses != null) && !validIPAddresses.isEmpty()) {
+ for (String validIPAddress : validIPAddresses) {
+ try {
+ parsedValidIPAddresses.add(new ValidIPAddress(validIPAddress));
+ } catch (Exception e) {
+ log.error("SimpleSecurityValve: unable to parse valid IP address '"+validIPAddress+"': " + e, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get valve name.
+ *
+ * @return valve name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get HTTP Basic Authentication realm.
+ *
+ * @return HTTP Basic Authentication realm
+ */
+ public String getAuthenticationRealm() {
+ return authenticationRealm;
+ }
+
+ /**
+ * Set HTTP Basic Authentication realm.
+ *
+ * @param authenticationRealm HTTP Basic Authentication realm
+ */
+ public void setAuthenticationRealm(String authenticationRealm) {
+ this.authenticationRealm = authenticationRealm;
+ }
+
+ /**
+ * Get HTTP Basic Authentication username.
+ *
+ * @return HTTP Basic Authentication username
+ */
+ public String getAuthenticationUser() {
+ return authenticationUser;
+ }
+
+ /**
+ * Set HTTP Basic Authentication username.
+ *
+ * @param authenticationUser HTTP Basic Authentication username
+ */
+ public void setAuthenticationUser(String authenticationUser) {
+ this.authenticationUser = authenticationUser;
+ }
+
+ /**
+ * Get HTTP Basic Authentication password MD5 HEX hash.
+ *
+ * @return HTTP Basic Authentication password MD5 HEX hash
+ */
+ public String getAuthenticationPasswordHash() {
+ return authenticationPasswordHash;
+ }
+
+ /**
+ * Set HTTP Basic Authentication password MD5 HEX hash.
+ *
+ * @param authenticationPasswordHash HTTP Basic Authentication password MD5 HEX hash
+ */
+ public void setAuthenticationPasswordHash(String authenticationPasswordHash) {
+ this.authenticationPasswordHash = authenticationPasswordHash;
+ }
+
+ /**
+ * Get valid IP addresses and/or subnets.
+ *
+ * @return list of valid IP addresses and/or subnets
+ */
+ public List<String> getValidIPAddresses() {
+ return validIPAddresses;
+ }
+
+ /**
+ * Set valid IP addresses and/or subnets.
+ *
+ * @param validIPAddresses list of valid IP addresses and/or subnets
+ */
+ public void setValidIPAddresses(List<String> validIPAddresses) {
+ this.validIPAddresses = validIPAddresses;
+ }
+
+ /**
+ * Class used to capture IPV4 addresses and subnets for matching tests.
+ */
+ private static class ValidIPAddress {
+ private int mask;
+ private int ip;
+
+ private ValidIPAddress(String validIPAddress) throws UnknownHostException {
+ int bitsIndex = validIPAddress.indexOf("/");
+ if (bitsIndex != -1) {
+ int bits = Integer.parseInt(validIPAddress.substring(bitsIndex+1));
+ this.mask = -1 << (32 - bits);
+ validIPAddress = validIPAddress.substring(0, bitsIndex);
+ } else {
+ this.mask = -1;
+ }
+ this.ip = getIP(validIPAddress) & this.mask;
+ }
+
+ private boolean matchIP(int testIP) {
+ return ((testIP & mask) == ip);
+ }
+ }
+
+ /**
+ * Convert string IPV4 address to int representation which is easier to mask.
+ *
+ * @param ipAddress String IPV4 address
+ * @return int address
+ * @throws UnknownHostException
+ */
+ private static int getIP(String ipAddress) throws UnknownHostException {
+ InetAddress inetAddress = InetAddress.getByName(ipAddress);
+ if (inetAddress instanceof Inet4Address) {
+ byte [] bytes = ((Inet4Address)inetAddress).getAddress();
+ return ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) | ((bytes[2] & 0xFF) << 8) | ((bytes[3] & 0xFF) << 0);
+ } else {
+ throw new UnknownHostException(ipAddress);
+ }
+ }
+}
Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java?rev=1647594&r1=1647593&r2=1647594&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java Tue Dec 23 15:30:15 2014
@@ -17,18 +17,6 @@
package org.apache.jetspeed.container.state;
-import java.security.Principal;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.servlet.ServletConfig;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import org.apache.jetspeed.capabilities.CapabilityMap;
import org.apache.jetspeed.container.PortletWindow;
import org.apache.jetspeed.container.url.PortalURL;
@@ -44,6 +32,17 @@ import org.apache.jetspeed.request.Reque
import org.apache.jetspeed.util.KeyValue;
import org.apache.jetspeed.window.MockPortletWindow;
+import javax.security.auth.Subject;
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
/**
* @version $Id$
*
@@ -52,6 +51,7 @@ public class MockRequestContext implemen
{
private HttpServletRequest request;
+ private HttpServletResponse response;
private final Map<String, PortletWindow> portletWindows = new HashMap<String, PortletWindow>();
public void addPortletWindow(PortletWindow window)
@@ -269,8 +269,7 @@ public class MockRequestContext implemen
*/
public HttpServletResponse getResponse()
{
- // TODO Auto-generated method stub
- return null;
+ return response;
}
/* (non-Javadoc)
@@ -453,7 +452,7 @@ public class MockRequestContext implemen
*/
public void setResponse(HttpServletResponse response)
{
- // TODO Auto-generated method stub
+ this.response = response;
}
/* (non-Javadoc)
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestRequestFilterValve.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestRequestFilterValve.java?rev=1647594&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestRequestFilterValve.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestRequestFilterValve.java Tue Dec 23 15:30:15 2014
@@ -0,0 +1,121 @@
+/*
+ * 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.jetspeed.pipeline.valve;
+
+import com.mockrunner.mock.web.MockHttpServletRequest;
+import com.mockrunner.mock.web.MockHttpServletResponse;
+import junit.framework.TestCase;
+import org.apache.jetspeed.container.state.MockRequestContext;
+import org.apache.jetspeed.pipeline.PipelineException;
+import org.apache.jetspeed.pipeline.valve.impl.RequestFilterValveImpl;
+import org.apache.jetspeed.request.RequestContext;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+
+/**
+ * Test for RequestFilterValve implementation.
+ *
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id:$
+ */
+public class TestRequestFilterValve extends TestCase {
+
+ /**
+ * Test RequestFilterValveImpl implementation.
+ *
+ * @throws Exception on unexpected exception
+ */
+ public void testRequestFilterValve() throws Exception {
+
+ // test default filtering
+ RequestFilterValve valve = new RequestFilterValveImpl("test-valve");
+ RequestContext requestContext = createRequestContext("/include");
+ StubValveContext valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+
+ // test include/exclude filtering
+ valve = new RequestFilterValveImpl("test-valve");
+ ((RequestFilterValveImpl)valve).setIncludes(Arrays.asList(new String[]{"/include/**"}));
+ ((RequestFilterValveImpl)valve).setExcludes(Arrays.asList(new String[]{"/include/exclude/**"}));
+ requestContext = createRequestContext("/include/include");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+ requestContext = createRequestContext("/exclude");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertTrue(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertEquals(HttpServletResponse.SC_NOT_FOUND, ((MockHttpServletResponse) requestContext.getResponse()).getErrorCode());
+ assertFalse(valveContext.nextInvoked);
+ requestContext = createRequestContext("/include/exclude/exclude");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertTrue(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertEquals(HttpServletResponse.SC_NOT_FOUND, ((MockHttpServletResponse) requestContext.getResponse()).getErrorCode());
+ assertFalse(valveContext.nextInvoked);
+
+ // test exclude filtering
+ valve = new RequestFilterValveImpl("test-valve");
+ ((RequestFilterValveImpl)valve).setIncludes(null);
+ ((RequestFilterValveImpl)valve).setExcludes(Arrays.asList(new String[]{"/exclude/**"}));
+ requestContext = createRequestContext("/include");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+ requestContext = createRequestContext("/exclude");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertTrue(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertEquals(HttpServletResponse.SC_NOT_FOUND, ((MockHttpServletResponse) requestContext.getResponse()).getErrorCode());
+ assertFalse(valveContext.nextInvoked);
+ }
+
+ /**
+ * Create mock RequestContext with the specified HttpServletRequest pathInfo.
+ *
+ * @param pathInfo request pathInfo
+ * @return mock RequestContext
+ */
+ private RequestContext createRequestContext(String pathInfo) {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setPathInfo(pathInfo);
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+ RequestContext requestContext = new MockRequestContext();
+ requestContext.setRequest(servletRequest);
+ requestContext.setResponse(servletResponse);
+ return requestContext;
+ }
+
+ /**
+ * Stub ValveContext implementation that tracks ValveContext.invokeNext() invocations.
+ */
+ private class StubValveContext implements ValveContext {
+
+ private boolean nextInvoked;
+
+ @Override
+ public void invokeNext(RequestContext request) throws PipelineException {
+ nextInvoked = true;
+ }
+ }
+}
Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestSimpleSecurityValve.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestSimpleSecurityValve.java?rev=1647594&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestSimpleSecurityValve.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/pipeline/valve/TestSimpleSecurityValve.java Tue Dec 23 15:30:15 2014
@@ -0,0 +1,170 @@
+/*
+ * 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.jetspeed.pipeline.valve;
+
+import com.mockrunner.mock.web.MockHttpServletRequest;
+import com.mockrunner.mock.web.MockHttpServletResponse;
+import junit.framework.TestCase;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.jetspeed.container.state.MockRequestContext;
+import org.apache.jetspeed.pipeline.PipelineException;
+import org.apache.jetspeed.pipeline.valve.impl.SimpleSecurityValveImpl;
+import org.apache.jetspeed.request.RequestContext;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+/**
+ * Test for simple SecurityValve implementation.
+ *
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id:$
+ */
+public class TestSimpleSecurityValve extends TestCase {
+
+ /**
+ * Test SimpleSecurityValveImpl implementation.
+ *
+ * @throws Exception on unexpected exception
+ */
+ public void testRequestFilterValve() throws Exception {
+
+ // test default configuration
+ SecurityValve valve = new SimpleSecurityValveImpl("test-valve");
+ valve.initialize();
+ RequestContext requestContext = createRequestContext("/test", "127.0.0.1", null, null);
+ StubValveContext valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+
+ // test HTTP Basic Authentication configuration
+ valve = new SimpleSecurityValveImpl("test-valve");
+ ((SimpleSecurityValveImpl)valve).setIncludes(Arrays.asList(new String[]{"/include/**"}));
+ ((SimpleSecurityValveImpl)valve).setAuthenticationRealm("test-realm");
+ ((SimpleSecurityValveImpl)valve).setAuthenticationUser("test-user");
+ ((SimpleSecurityValveImpl)valve).setAuthenticationPasswordHash(DigestUtils.md5Hex("test-password"));
+ valve.initialize();
+ requestContext = createRequestContext("/include/test", "127.0.0.1", "test-user", "test-password");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+ requestContext = createRequestContext("/include/test", "127.0.0.1", null, null);
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertEquals("Basic realm=\"test-realm\"", ((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertTrue(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertEquals(HttpServletResponse.SC_UNAUTHORIZED, ((MockHttpServletResponse) requestContext.getResponse()).getErrorCode());
+ assertFalse(valveContext.nextInvoked);
+ requestContext = createRequestContext("/include/test", "127.0.0.1", "not-test-user", "not-test-password");
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertEquals("Basic realm=\"test-realm\"", ((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertTrue(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertEquals(HttpServletResponse.SC_UNAUTHORIZED, ((MockHttpServletResponse) requestContext.getResponse()).getErrorCode());
+ assertFalse(valveContext.nextInvoked);
+ requestContext = createRequestContext("/exclude/test", "127.0.0.1", null, null);
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+
+ // test valid IP Address configuration
+ valve = new SimpleSecurityValveImpl("test-valve");
+ ((SimpleSecurityValveImpl)valve).setIncludes(Arrays.asList(new String[]{"/include/**"}));
+ ((SimpleSecurityValveImpl)valve).setExcludes(Arrays.asList(new String[]{"/include/exclude/**"}));
+ ((SimpleSecurityValveImpl)valve).setValidIPAddresses(Arrays.asList(new String[]{"127.0.0.1", "10.0.0.0/8"}));
+ valve.initialize();
+ requestContext = createRequestContext("/include/test", "127.0.0.1", null, null);
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+ requestContext = createRequestContext("/include/test", "10.0.0.23", null, null);
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+ requestContext = createRequestContext("/include/test", "173.194.79.105", null, null);
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertTrue(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertEquals(HttpServletResponse.SC_FORBIDDEN, ((MockHttpServletResponse) requestContext.getResponse()).getErrorCode());
+ assertFalse(valveContext.nextInvoked);
+ requestContext = createRequestContext("/include/exclude/test", "173.194.79.105", null, null);
+ valveContext = new StubValveContext();
+ valve.invoke(requestContext, valveContext);
+ assertNull(((MockHttpServletResponse) requestContext.getResponse()).getHeader(SimpleSecurityValveImpl.HTTP_WWW_AUTHENTICATE_HEADER));
+ assertFalse(((MockHttpServletResponse) requestContext.getResponse()).wasErrorSent());
+ assertTrue(valveContext.nextInvoked);
+ }
+
+
+
+ /**
+ * Create mock RequestContext with the specified HttpServletRequest pathInfo,
+ * remoteAddr, and HTTP Basic Authorization header.
+ *
+ * @param pathInfo request pathInfo
+ * @param remoteAddr request remoteAddr
+ * @param user request HTTP Basic Authentication user or null
+ * @param password request HTTP Basic Authentication password or null
+ * @return mock RequestContext
+ */
+ private RequestContext createRequestContext(String pathInfo, String remoteAddr, String user, String password) {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setPathInfo(pathInfo);
+ servletRequest.setRemoteAddr(remoteAddr);
+ if ((user != null) && (password != null)) {
+ String authorization = user+":"+password;
+ try {
+ authorization = "Basic " + Base64.encodeBase64String(authorization.getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException uee) {
+ }
+ servletRequest.setHeader(SimpleSecurityValveImpl.HTTP_AUTHORIZATION_HEADER, authorization);
+ }
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+ RequestContext requestContext = new MockRequestContext();
+ requestContext.setRequest(servletRequest);
+ requestContext.setResponse(servletResponse);
+ return requestContext;
+ }
+
+ /**
+ * Stub ValveContext implementation that tracks ValveContext.invokeNext() invocations.
+ */
+ private class StubValveContext implements ValveContext {
+
+ private boolean nextInvoked;
+
+ @Override
+ public void invokeNext(RequestContext request) throws PipelineException {
+ nextInvoked = true;
+ }
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org