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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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;
+ }
+ }
+
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.