You are viewing a plain text version of this content. The canonical link for it is here.
Posted to portalapps-dev@portals.apache.org by wo...@apache.org on 2009/09/25 16:07:55 UTC
svn commit: r818855 - in /portals/applications/webcontent/trunk:
webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/
webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/
webcontent-jar/src/test/...
Author: woonsan
Date: Fri Sep 25 14:07:54 2009
New Revision: 818855
URL: http://svn.apache.org/viewvc?rev=818855&view=rev
Log:
APA-17: Adding configuration auto-refresh feature. Also, generalizing the way of sso auth info retrieval.
Added:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java (with props)
portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java (with props)
Modified:
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties
portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml
Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java?rev=818855&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java Fri Sep 25 14:07:54 2009
@@ -0,0 +1,43 @@
+/*
+ * 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.portals.applications.webcontent.proxy;
+
+import org.apache.http.auth.AuthScope;
+
+/**
+ * Authentication Scope and Credentials holder interface to be used in reverse proxy component.
+ *
+ * @version $Id$
+ */
+public interface AuthScopeCredentials
+{
+
+ public String getSiteURL();
+
+ public AuthScope getAuthScope();
+
+ public String getUsername();
+
+ public String getPassword();
+
+ public boolean isFormAuthentication();
+
+ public String getFormUserField();
+
+ public String getFormPasswordField();
+
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/AuthScopeCredentials.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/HttpReverseProxyConstants.java Fri Sep 25 14:07:54 2009
@@ -21,8 +21,8 @@
String HTTP_HEADER_LOCATION = "Location";
- String REVERSE_PROXY_PATH_MAPPER_ATTRIBUTE = "org.apache.portals.applications.webcontent.proxy.reverseProxyPathMapper";
+ String PATH_MAPPER = "org.apache.portals.applications.webcontent.proxy.reverseProxyPathMapper";
- String REVERSE_PROXY_AUTH_CREDS_MAP_ATTRIBUTE = "org.apache.portals.applications.webcontent.proxy.reverseProxyAuthCredsMap";
+ String USER_AUTH_SCOPE_CREDS = "org.apache.portals.applications.webcontent.proxy.reverseProxyUserAuthScopeCreds";
}
Added: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java?rev=818855&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java Fri Sep 25 14:07:54 2009
@@ -0,0 +1,174 @@
+/*
+ * 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.portals.applications.webcontent.proxy.impl;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.auth.AuthScope;
+import org.apache.portals.applications.webcontent.proxy.AuthScopeCredentials;
+
+/**
+ * Authentication Scope and Credentials holder class to be used in reverse proxy component.
+ *
+ * @version $Id$
+ */
+public class DefaultAuthScopeCredentialsImpl implements AuthScopeCredentials, Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ private URI authCredsInURI;
+ private String siteURL;
+ private transient AuthScope authScope;
+ private String username;
+ private String password;
+ private String formUserField;
+ private String formPasswordField;
+
+ public DefaultAuthScopeCredentialsImpl(URI authCredsInURI) throws URISyntaxException
+ {
+ this.authCredsInURI = authCredsInURI;
+
+ String rawUserInfo = this.authCredsInURI.getRawUserInfo();
+
+ if (rawUserInfo == null)
+ {
+ throw new URISyntaxException(authCredsInURI.toString(), "Userinfo is not defined in the uri.");
+ }
+
+ String [] usernameAndPassword = StringUtils.split(rawUserInfo, ":");
+
+ if (usernameAndPassword.length != 2)
+ {
+ throw new URISyntaxException(authCredsInURI.toString(), "Userinfo is not well-formed in the uri.");
+ }
+
+ username = usernameAndPassword[0];
+ password = usernameAndPassword[1];
+
+ int offset = username.indexOf('=');
+
+ try
+ {
+ if (offset == -1)
+ {
+ username = URLDecoder.decode(username, "UTF-8");
+ password = URLDecoder.decode(password, "UTF-8");
+ }
+ else
+ {
+ formUserField = URLDecoder.decode(username.substring(0, offset), "UTF-8");
+ username = URLDecoder.decode(username.substring(offset + 1), "UTF-8");
+
+ offset = password.indexOf('=');
+
+ formPasswordField = URLDecoder.decode(password.substring(0, offset), "UTF-8");
+ password = URLDecoder.decode(password.substring(offset + 1), "UTF-8");
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new URISyntaxException(authCredsInURI.toString(), "Userinfo is not correctly encoded.");
+ }
+ }
+
+ public String getSiteURL()
+ {
+ if (siteURL == null && authCredsInURI != null)
+ {
+ String scheme = authCredsInURI.getScheme();
+ String host = authCredsInURI.getHost();
+ int port = authCredsInURI.getPort();
+ String path = authCredsInURI.getPath();
+ String query = authCredsInURI.getQuery();
+
+ StringBuilder sb = new StringBuilder(100);
+ sb.append(scheme).append("://");
+ sb.append(host);
+
+ if (port != -1)
+ {
+ sb.append(':').append(port);
+ }
+
+ if (path != null)
+ {
+ sb.append(path);
+ }
+
+ if (query != null)
+ {
+ sb.append('?').append(query);
+ }
+
+ siteURL = sb.toString();
+ }
+
+ return siteURL;
+ }
+
+ public AuthScope getAuthScope()
+ {
+ if (authScope == null && authCredsInURI != null)
+ {
+ String host = authCredsInURI.getHost();
+ int port = authCredsInURI.getPort();
+ String realm = authCredsInURI.getFragment();
+
+ if (StringUtils.isBlank(realm))
+ {
+ authScope = new AuthScope(host, port);
+ }
+ else
+ {
+ authScope = new AuthScope(host, port, realm);
+ }
+ }
+
+ return authScope;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public boolean isFormAuthentication()
+ {
+ return (formUserField != null && formPasswordField != null);
+ }
+
+ public String getFormPasswordField()
+ {
+ return formPasswordField;
+ }
+
+ public String getFormUserField()
+ {
+ return formUserField;
+ }
+
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultAuthScopeCredentialsImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/DefaultHttpReverseProxyServlet.java Fri Sep 25 14:07:54 2009
@@ -16,6 +16,7 @@
*/
package org.apache.portals.applications.webcontent.proxy.impl;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
@@ -36,9 +37,11 @@
import org.apache.commons.collections.keyvalue.DefaultKeyValue;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.NumberUtils;
import org.apache.http.HttpHost;
import org.apache.http.client.params.ClientParamBean;
import org.apache.http.conn.params.ConnManagerParamBean;
@@ -67,15 +70,65 @@
private static Logger log = LoggerFactory.getLogger(DefaultHttpReverseProxyServlet.class);
- protected HttpReverseProxyPathMapperProvider proxyPathMapperProvider;
protected HttpReverseProxyService proxyService;
- private Configuration configuration;
+ private PropertiesConfiguration configuration;
+
+ private long configurationRefreshDelay;
+
+ private FileChangedReloadingStrategy configReloadingStrategy;
@Override
public void init(ServletConfig config) throws ServletException
{
- loadConfiguration(config);
+ super.init(config);
+
+ configurationRefreshDelay = NumberUtils.toLong(getServletConfig().getInitParameter("reverseproxy.configuration.refresh.delay"), 0L);
+
+ if (configurationRefreshDelay > 0L)
+ {
+ configReloadingStrategy = new FileChangedReloadingStrategy()
+ {
+ @Override
+ public void reloadingPerformed()
+ {
+ super.reloadingPerformed();
+
+ try
+ {
+ if (proxyService != null)
+ {
+ recreateHttpReverseProxyService();
+ }
+ }
+ catch (Exception e)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.error("Failed to recreate reverse proxy service.", e);
+ }
+ else
+ {
+ log.error("Failed to recreate reverse proxy service. {}", e.toString());
+ }
+ }
+ }
+ };
+
+ configReloadingStrategy.setRefreshDelay(Math.max(configurationRefreshDelay, 2000));
+ }
+
+ loadConfiguration();
+
+ recreateHttpReverseProxyService();
+ }
+
+ private void recreateHttpReverseProxyService() throws ServletException
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("DefaultHttpReverseProxyServlet is to initialize reverse proxy service component...");
+ }
List<HttpReverseProxyPathMapper> proxyPathMappers = new ArrayList<HttpReverseProxyPathMapper>();
@@ -102,12 +155,12 @@
if (ArrayUtils.getLength(rewriterRuleConfs) == 2)
{
- RewriterController rewriterController = createRewriterController(config, rewriterRuleConfs[0], rewriterClassNames, adaptorClassNames);
+ RewriterController rewriterController = createRewriterController(rewriterRuleConfs[0], rewriterClassNames, adaptorClassNames);
if (rewriterController != null)
{
rewriterControllerPairs.add(new DefaultKeyValue(localBasePath, rewriterController));
- Rewriter rewriter = createRewriter(config, rewriterController, rewriterRuleConfs[1]);
+ Rewriter rewriter = createRewriter(rewriterController, rewriterRuleConfs[1]);
rewriterPairs.add(new DefaultKeyValue(localBasePath, rewriter));
}
}
@@ -118,19 +171,19 @@
throw new ServletException("Failed to initialize url mappings. " + e);
}
- proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerPairs, rewriterPairs);
- proxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
+ HttpReverseProxyPathMapperProvider proxyPathMapperProvider = new DefaultHttpReverseProxyPathMapperProviderImpl(proxyPathMappers, rewriterControllerPairs, rewriterPairs);
+ HttpReverseProxyService tempProxyService = new RewritableHttpReverseProxyServiceImpl(proxyPathMapperProvider);
Configuration serverConf = configuration.subset("proxy.server");
if (!StringUtils.isBlank(serverConf.getString("hostname")))
{
- ((RewritableHttpReverseProxyServiceImpl) proxyService).setHostHeaderValue(serverConf.getString("hostname"));
+ ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setHostHeaderValue(serverConf.getString("hostname"));
}
if (!StringUtils.isBlank(serverConf.getString("baseurl")))
{
- ((RewritableHttpReverseProxyServiceImpl) proxyService).setLocalBaseURL(serverConf.getString("baseurl"));
+ ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setLocalBaseURL(serverConf.getString("baseurl"));
}
Configuration clientParamsConf = configuration.subset("proxy.http.client.param");
@@ -139,7 +192,7 @@
{
HttpParams clientParams = new BasicHttpParams();
setBeanPropertiesByConfiguration(new ClientParamBean(clientParams), clientParamsConf);
- ((RewritableHttpReverseProxyServiceImpl) proxyService).setClientParams(clientParams);
+ ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setClientParams(clientParams);
}
Configuration connManagerParamsConf = configuration.subset("proxy.http.connManager.param");
@@ -184,10 +237,41 @@
connManagerParamBean.setConnectionsPerRoute(connPerRouteBean);
}
- ((RewritableHttpReverseProxyServiceImpl) proxyService).setConnectionManagerParams(connManagerParams);
+ ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setConnectionManagerParams(connManagerParams);
}
- proxyService.initialize();
+ Configuration ssoUserConf = configuration.subset("proxy.sso.user");
+
+ try
+ {
+ ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setUserAuthScopeCredentialsPropertyPath(ssoUserConf.getString("userAuthScopeCredentialsPropertyPath"));
+ }
+ catch (Exception e)
+ {
+ }
+
+ try
+ {
+ ((RewritableHttpReverseProxyServiceImpl) tempProxyService).setKeepAuthScopeCredentialsInSession(ssoUserConf.getBoolean("keepAuthScopeCredentialsInSession", true));
+ }
+ catch (Exception e)
+ {
+ }
+
+ tempProxyService.initialize();
+
+ HttpReverseProxyService oldProxyService = proxyService;
+ proxyService = tempProxyService;
+
+ if (log.isInfoEnabled())
+ {
+ log.info("DefaultHttpReverseProxyServlet has (re)initialized reverse proxy service component...");
+ }
+
+ if (oldProxyService != null)
+ {
+ oldProxyService.destroy();
+ }
}
public void destroy()
@@ -203,6 +287,15 @@
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
proxyService.invoke(request, response);
+
+ try
+ {
+ // dummy read for refreshing...
+ configuration.getString("proxy.reverse.pass");
+ }
+ catch (Exception e)
+ {
+ }
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
@@ -210,19 +303,19 @@
doGet(request, response);
}
- private RewriterController createRewriterController(ServletConfig config, String rulesMappingResourcePath, String [] rewriterClassNames, String [] adaptorClassNames) throws Exception
+ private RewriterController createRewriterController(String rulesMappingResourcePath, String [] rewriterClassNames, String [] adaptorClassNames) throws Exception
{
- return new MappingRewriterController(config.getServletContext().getRealPath(rulesMappingResourcePath), buildClassList(rewriterClassNames), buildClassList(adaptorClassNames));
+ return new MappingRewriterController(getServletContext().getRealPath(rulesMappingResourcePath), buildClassList(rewriterClassNames), buildClassList(adaptorClassNames));
}
- private Rewriter createRewriter(ServletConfig config, RewriterController rwc, String rewriterRulesResourcePath) throws Exception
+ private Rewriter createRewriter(RewriterController rwc, String rewriterRulesResourcePath) throws Exception
{
Rewriter rewriter = null;
InputStream rewriterRulesInput = null;
try
{
- rewriterRulesInput = config.getServletContext().getResourceAsStream(rewriterRulesResourcePath);
+ rewriterRulesInput = getServletContext().getResourceAsStream(rewriterRulesResourcePath);
rewriter = rwc.createRewriter(rwc.loadRuleset(rewriterRulesInput));
}
finally
@@ -286,7 +379,13 @@
}
}
- secure = routeConf.getBoolean("secure", false);
+ try
+ {
+ secure = routeConf.getBoolean("secure", false);
+ }
+ catch (Exception e)
+ {
+ }
try
{
@@ -339,7 +438,15 @@
String scheme = null;
hostname = hostConf.getString("hostname");
- port = hostConf.getInt("port", 0);
+
+ try
+ {
+ port = hostConf.getInt("port", 0);
+ }
+ catch (Exception e)
+ {
+ }
+
scheme = hostConf.getString("scheme");
if (StringUtils.isBlank(hostname))
@@ -394,22 +501,40 @@
return null;
}
- private void loadConfiguration(ServletConfig servletConfig) throws ServletException
+ private void loadConfiguration() throws ServletException
{
- String configResourcePath = servletConfig.getInitParameter("reverseproxy.configuration");
+ String configResourcePath = getServletConfig().getInitParameter("reverseproxy.configuration");
if (configResourcePath == null)
{
configResourcePath = "/WEB-INF/conf/reverseproxy.properties";
}
+ File configResourceFile = null;
+
+ try
+ {
+ configResourceFile = new File(getServletContext().getRealPath(configResourcePath));
+ }
+ catch (Exception e)
+ {
+ }
+
InputStream configInput = null;
try
{
- configInput = servletConfig.getServletContext().getResourceAsStream(configResourcePath);
- configuration = new PropertiesConfiguration();
- ((PropertiesConfiguration) configuration).load(configInput);
+ if (configResourceFile != null && configResourceFile.isFile() && configReloadingStrategy != null)
+ {
+ configuration = new PropertiesConfiguration(configResourceFile);
+ configuration.setReloadingStrategy(configReloadingStrategy);
+ }
+ else
+ {
+ configInput = getServletContext().getResourceAsStream(configResourcePath);
+ configuration = new PropertiesConfiguration();
+ ((PropertiesConfiguration) configuration).load(configInput);
+ }
}
catch (Exception e)
{
Modified: portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java (original)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/main/java/org/apache/portals/applications/webcontent/proxy/impl/RewritableHttpReverseProxyServiceImpl.java Fri Sep 25 14:07:54 2009
@@ -23,19 +23,23 @@
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
+import java.net.URI;
+import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.Map;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
-import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
@@ -52,6 +56,7 @@
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
+import org.apache.portals.applications.webcontent.proxy.AuthScopeCredentials;
import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyConstants;
import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapper;
import org.apache.portals.applications.webcontent.proxy.HttpReverseProxyPathMapperProvider;
@@ -103,6 +108,15 @@
*/
private HttpParams clientParams;
+ /**
+ * Property Path to find User AuthScope-Credentials for SSO.
+ * <P>The property path value will be evaluated from {@link HttpServletRequest} object.
+ * The property path syntax conforms Apache Commons BeanUtils {@link PropertyUtils#getProperty(Object, String)}.</P>
+ */
+ private String userAuthScopeCredentialsPropertyPath;
+
+ private boolean keepAuthScopeCredentialsInSession = true;
+
public RewritableHttpReverseProxyServiceImpl(HttpReverseProxyPathMapperProvider proxyPathMapperProvider)
{
this.proxyPathMapperProvider = proxyPathMapperProvider;
@@ -128,6 +142,16 @@
this.connectionManagerParams = connectionManagerParams;
}
+ public void setUserAuthScopeCredentialsPropertyPath(String userAuthScopeCredentialsPropertyPath)
+ {
+ this.userAuthScopeCredentialsPropertyPath = userAuthScopeCredentialsPropertyPath;
+ }
+
+ public void setKeepAuthScopeCredentialsInSession(boolean keepAuthScopeCredentialsInSession)
+ {
+ this.keepAuthScopeCredentialsInSession = keepAuthScopeCredentialsInSession;
+ }
+
public void initialize()
{
if (clientParams == null)
@@ -158,7 +182,7 @@
public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException
{
// proxyPathMapper can be injected by using request attribute.
- HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) request.getAttribute(HttpReverseProxyConstants.REVERSE_PROXY_PATH_MAPPER_ATTRIBUTE);
+ HttpReverseProxyPathMapper proxyPathMapper = (HttpReverseProxyPathMapper) request.getAttribute(HttpReverseProxyConstants.PATH_MAPPER);
String pathInfo = request.getPathInfo();
@@ -208,7 +232,7 @@
// redirection should be adjusted with local host header...
httpClient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
// set credentials for this user if available
- retrieveCredentialsInfos(httpClient, request);
+ setUserCredentialsInfos(httpClient, request);
String method = request.getMethod();
boolean isGetMethod = "GET".equals(method);
@@ -486,25 +510,56 @@
}
}
- private void retrieveCredentialsInfos(DefaultHttpClient httpClient, HttpServletRequest request)
+ private void setUserCredentialsInfos(DefaultHttpClient httpClient, HttpServletRequest request)
{
- Map<AuthScope, Credentials> authScopeCredentialsMap = (Map<AuthScope, Credentials>) request.getAttribute(HttpReverseProxyConstants.REVERSE_PROXY_AUTH_CREDS_MAP_ATTRIBUTE);
+ List<AuthScopeCredentials> userAuthScopeCredentials = (List<AuthScopeCredentials>) request.getAttribute(HttpReverseProxyConstants.USER_AUTH_SCOPE_CREDS);
- if (authScopeCredentialsMap == null)
+ if (userAuthScopeCredentials == null)
{
HttpSession session = request.getSession(false);
if (session != null)
{
- authScopeCredentialsMap = (Map<AuthScope, Credentials>) session.getAttribute(HttpReverseProxyConstants.REVERSE_PROXY_AUTH_CREDS_MAP_ATTRIBUTE);
+ userAuthScopeCredentials = (List<AuthScopeCredentials>) session.getAttribute(HttpReverseProxyConstants.USER_AUTH_SCOPE_CREDS);
+ }
+ }
+
+ if (userAuthScopeCredentials == null && userAuthScopeCredentialsPropertyPath != null)
+ {
+ try
+ {
+ List<URI> authCredsURIs = (List<URI>) PropertyUtils.getProperty(request, StringUtils.removeStart(userAuthScopeCredentialsPropertyPath, "request."));
+
+ if (authCredsURIs != null)
+ {
+ userAuthScopeCredentials = new ArrayList<AuthScopeCredentials>();
+
+ for (URI authCredsURI : authCredsURIs)
+ {
+ userAuthScopeCredentials.add(new DefaultAuthScopeCredentialsImpl(authCredsURI));
+ }
+
+ if (keepAuthScopeCredentialsInSession)
+ {
+ request.getSession().setAttribute(HttpReverseProxyConstants.USER_AUTH_SCOPE_CREDS, userAuthScopeCredentials);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (log.isWarnEnabled())
+ {
+ log.warn("Cannot access the authScopeCredentials list object by the path, {}. {}", userAuthScopeCredentialsPropertyPath, e);
+ }
}
}
- if (authScopeCredentialsMap != null && !authScopeCredentialsMap.isEmpty())
+ if (userAuthScopeCredentials != null && !userAuthScopeCredentials.isEmpty())
{
- for (Map.Entry<AuthScope, Credentials> entry : authScopeCredentialsMap.entrySet())
+ for (AuthScopeCredentials authScopeCreds : userAuthScopeCredentials)
{
- httpClient.getCredentialsProvider().setCredentials(entry.getKey(), entry.getValue());
+ Credentials creds = new UsernamePasswordCredentials(authScopeCreds.getUsername(), authScopeCreds.getPassword());
+ httpClient.getCredentialsProvider().setCredentials(authScopeCreds.getAuthScope(), creds);
}
}
}
Added: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java?rev=818855&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java (added)
+++ portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java Fri Sep 25 14:07:54 2009
@@ -0,0 +1,156 @@
+/*
+ * 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.portals.applications.webcontent.proxy;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.portals.applications.webcontent.proxy.impl.DefaultAuthScopeCredentialsImpl;
+
+/**
+ * Test case for AuthScopeCredentials with various URIs.
+ *
+ * @version $Id$
+ */
+public class TestAuthScopeCredentials extends TestCase
+{
+ public void testAuthURIs() throws URISyntaxException
+ {
+ URI uri = URI.create("http://manager:mngpwd@www.localhost.com:8080/manager/list?a=1&b=2");
+ AuthScopeCredentials asc = new DefaultAuthScopeCredentialsImpl(uri);
+ assertEquals("http://www.localhost.com:8080/manager/list?a=1&b=2", asc.getSiteURL());
+ assertEquals("manager", asc.getUsername());
+ assertEquals("mngpwd", asc.getPassword());
+ assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+ assertEquals(8080, asc.getAuthScope().getPort());
+ assertNull(asc.getAuthScope().getRealm());
+ assertFalse(asc.isFormAuthentication());
+
+ uri = URI.create("http://formuser=manager:formpwd=mngpwd@www.localhost.com:8080/manager/list?a=1&b=2");
+ asc = new DefaultAuthScopeCredentialsImpl(uri);
+ assertEquals("http://www.localhost.com:8080/manager/list?a=1&b=2", asc.getSiteURL());
+ assertEquals("manager", asc.getUsername());
+ assertEquals("mngpwd", asc.getPassword());
+ assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+ assertEquals(8080, asc.getAuthScope().getPort());
+ assertNull(asc.getAuthScope().getRealm());
+ assertTrue(asc.isFormAuthentication());
+ assertEquals("formuser", asc.getFormUserField());
+ assertEquals("formpwd", asc.getFormPasswordField());
+
+ uri = URI.create("http://formuser=manager:formpwd=mng%3Dpwd@www.localhost.com:8080/manager/list?a=1&b=2");
+ asc = new DefaultAuthScopeCredentialsImpl(uri);
+ assertEquals("http://www.localhost.com:8080/manager/list?a=1&b=2", asc.getSiteURL());
+ assertEquals("manager", asc.getUsername());
+ assertEquals("mng=pwd", asc.getPassword());
+ assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+ assertEquals(8080, asc.getAuthScope().getPort());
+ assertNull(asc.getAuthScope().getRealm());
+ assertTrue(asc.isFormAuthentication());
+ assertEquals("formuser", asc.getFormUserField());
+ assertEquals("formpwd", asc.getFormPasswordField());
+
+ uri = URI.create("http://manager:mngpwd@www.localhost.com:8080/manager/list#Tomcat%20Manager%20Application");
+ asc = new DefaultAuthScopeCredentialsImpl(uri);
+ assertEquals("http://www.localhost.com:8080/manager/list", asc.getSiteURL());
+ assertEquals("manager", asc.getUsername());
+ assertEquals("mngpwd", asc.getPassword());
+ assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+ assertEquals(8080, asc.getAuthScope().getPort());
+ assertEquals("Tomcat Manager Application", asc.getAuthScope().getRealm());
+ assertFalse(asc.isFormAuthentication());
+ }
+
+ public void testUseAuthScopeCredsBeanPathRetrieval() throws URISyntaxException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
+ {
+ Request request = new Request();
+ AppRequestContext arc = new AppRequestContext();
+ arc.getObjects().put("org.examples.provider", new UserAuthScopeCredentialsProvider());
+ request.setAttribute("org.examples.request.context", arc);
+
+ final String propertyPath = "request.attribute(org.examples.request.context).objects(org.examples.provider).userAuthScopeCredentials";
+
+ List<AuthScopeCredentials> authScopeCreds = (List<AuthScopeCredentials>) PropertyUtils.getProperty(request, StringUtils.removeStart(propertyPath, "request."));
+ assertNotNull(authScopeCreds);
+ assertTrue(authScopeCreds.size() == 2);
+
+ AuthScopeCredentials asc = authScopeCreds.get(0);
+ assertEquals("manager", asc.getUsername());
+ assertEquals("manager", asc.getPassword());
+ assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+ assertEquals(8080, asc.getAuthScope().getPort());
+
+ asc = authScopeCreds.get(1);
+ assertEquals("devmgr", asc.getUsername());
+ assertEquals("devmgr", asc.getPassword());
+ assertEquals("www.localhost.com", asc.getAuthScope().getHost());
+ assertEquals(8080, asc.getAuthScope().getPort());
+ }
+
+ public static class Request
+ {
+ private Map<String, Object> attrs = new HashMap<String, Object>();
+
+ public void setAttribute(String attrName, Object attrValue)
+ {
+ attrs.put(attrName, attrValue);
+ }
+
+ public Object getAttribute(String attrName)
+ {
+ return attrs.get(attrName);
+ }
+ }
+
+ public static class AppRequestContext
+ {
+ private Map<String, Object> objects = new HashMap<String, Object>();
+
+ public Map<String, Object> getObjects()
+ {
+ return objects;
+ }
+ }
+
+ public static class UserAuthScopeCredentialsProvider
+ {
+ public List<AuthScopeCredentials> getUserAuthScopeCredentials()
+ {
+ List<AuthScopeCredentials> userAuthScopeCredentials = new ArrayList<AuthScopeCredentials>();
+
+ try
+ {
+ userAuthScopeCredentials.add(new DefaultAuthScopeCredentialsImpl(URI.create("http://manager:manager@www.localhost.com:8080")));
+ userAuthScopeCredentials.add(new DefaultAuthScopeCredentialsImpl(URI.create("http://devmgr:devmgr@www.localhost.com:8080")));
+ }
+ catch (Exception e)
+ {
+ }
+
+ return userAuthScopeCredentials;
+ }
+ }
+}
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: portals/applications/webcontent/trunk/webcontent-jar/src/test/java/org/apache/portals/applications/webcontent/proxy/TestAuthScopeCredentials.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties (original)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/conf/reverseproxy.properties Fri Sep 25 14:07:54 2009
@@ -42,6 +42,12 @@
proxy.http.client.param.allowCircularRedirects = false
+# Reverse Proxy Single Sign On configurations
+# ... Sets property path from request object to retrieve user's authScopeCredential list object.
+# ... The property path should conform Apache Commons BeanUtils PropUtils.getProperty(Object, String).
+proxy.sso.user.userAuthScopeCredentialsPropertyPath = request.attribute(org.apache.jetspeed.request.RequestContext).objects(org.apache.portals.applications.webcontent.proxy.authCredsProvider).authCredsURIs
+proxy.sso.user.keepAuthScopeCredentialsInSession
+
# Global HTTP ClientConnectionManager parameters
# ... You can set various http client connection manager parameters with prefix, 'proxy.http.connManager.param.'.
# ... Refer to the javadoc of org.apache.http.conn.params.ConnManagerParamBean.
@@ -64,6 +70,7 @@
# ... 'somewhere' is just an example to show the full configurable items...
proxy.http.route.somewhere.target.hostname = somewhere.localhost.com
+proxy.http.route.somewhere.target.port = 8080
proxy.http.route.somewhere.maxConnections = 5
proxy.http.route.somewhere.local = 111.111.111.111
proxy.http.route.somewhere.secure = false
@@ -91,6 +98,6 @@
# ... 'somewhere' is just an example to show the full configurable items...
proxy.reverse.pass.somewhere.local = /somewhere/
proxy.reverse.pass.somewhere.remote = http://somewhere.localhost.com/
-#proxy.reverse.pass.somewhere.rewriters = ${defaults.htmlRewriter}, ${defaults.xmlRewriter}
-#proxy.reverse.pass.somewhere.adaptors = ${defaults.htmlAdaptor}, ${defaults.xmlAdaptor}
-#proxy.reverse.pass.somewhere.rules = ${defaults.ruleMappings}, ${defaults.rewriterRules}
+proxy.reverse.pass.somewhere.rewriters = ${defaults.htmlRewriter}, ${defaults.xmlRewriter}
+proxy.reverse.pass.somewhere.adaptors = ${defaults.htmlAdaptor}, ${defaults.xmlAdaptor}
+proxy.reverse.pass.somewhere.rules = ${defaults.ruleMappings}, ${defaults.rewriterRules}
Modified: portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml?rev=818855&r1=818854&r2=818855&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml (original)
+++ portals/applications/webcontent/trunk/webcontent-war/src/main/webapp/WEB-INF/web.xml Fri Sep 25 14:07:54 2009
@@ -55,6 +55,10 @@
<param-name>reverseproxy.configuration</param-name>
<param-value>/WEB-INF/conf/reverseproxy.properties</param-value>
</init-param>
+ <init-param>
+ <param-name>reverseproxy.configuration.refresh.delay</param-name>
+ <param-value>60000</param-value>
+ </init-param>
<load-on-startup>11</load-on-startup>
</servlet>