Details

    • Type: New Feature
    • Status: Closed
    • Priority: Trivial
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: 2.0.4
    • Component/s: Core
    • Labels:
      None

      Description

      When operating ACEGI behind a Load Balancer or Web Server that performs SSL on behalf of the App Server, channel security doesn't work. It would be useful if there was a ChannelProcessor implementation that could review the remote port of a request (which survives even if the LB switches from https to http before landing in the Acegi stack). The idea would be to allow configuration of a SecureChannelProcessor and an InsecureChannelProcessor based on port mapper configuration.

      One possible implementation could be:

      package ...;

      import java.io.IOException;
      import java.util.Iterator;

      import javax.servlet.ServletException;

      import net.sf.acegisecurity.ConfigAttribute;
      import net.sf.acegisecurity.ConfigAttributeDefinition;
      import net.sf.acegisecurity.intercept.web.FilterInvocation;
      import net.sf.acegisecurity.securechannel.ChannelEntryPoint;
      import net.sf.acegisecurity.securechannel.ChannelProcessor;
      import net.sf.acegisecurity.securechannel.RetryWithHttpsEntryPoint;
      import net.sf.acegisecurity.util.PortMapper;
      import net.sf.acegisecurity.util.PortMapperImpl;

      import org.springframework.util.Assert;

      /**

      • A ChannelProcessor that makes decisions based on the requests server port. By
      • default, this processor will look to see if the port is a designated SSL port
      • by using the provided portMapper. If not, it fires the entry point (which
      • should force a redirect).
      • <br/>
      • This processor can also be used to see if the current port is an http port
      • and if not, redirect to it. In essence, it can hancle secure and insecure
      • redirects.
      • <br/>
      • To use as an insecure processor, set the secureMode to false and set a
      • different secureKeyword.
      • The default secureKeyword is "REQUIRES_SECURE_CHANNEL" and the default
      • portMapper is the standard PortMapperImpl which handles 80/443 and 8080/8443
      • by default. The default entryPoint is RetryWithHttpsEntryPoint so be sure to
      • set this if using this processor as an insecure processor.
      • This implementation was borrowed from Acegi's SecureChannelProcessor.
      • @see net.sf.acegisecurity.securechannel.SecureChannelProcessor
        */
        public class PortBasedChannelProcessor implements ChannelProcessor
        {
        private static final String REQUIRES_SECURE_CHANNEL = "REQUIRES_SECURE_CHANNEL";
        private ChannelEntryPoint entryPoint = new RetryWithHttpsEntryPoint();
        private String secureKeyword = REQUIRES_SECURE_CHANNEL;
        private PortMapper portMapper;
        private boolean secureMode = true;

      /**

      • Set this to true if this processor should fire the endpoint if not running
      • on a designated https port. Set to false if the endpoint should fire if
      • not running on a designated http port.
      • @param secureMode
      • The secureMode to set.
        */
        public void setSecureMode(boolean secureMode) { this.secureMode = secureMode; }

      /**

      • The portMapper to use in making decisions about ports.
      • @param portMapper
      • The portMapper to set.
        */
        public void setPortMapper(PortMapper portMapper) { this.portMapper = portMapper; }

      /**

      • The entrypoint to use when a redirect decision is made. Defaults to
      • <code>RetryWithHttpsEntryPoint</code>.
      • @param entryPoint
      • The entryPoint to set.
      • @see RetryWithHttpsEntryPoint
        */
        public void setEntryPoint(ChannelEntryPoint entryPoint) { this.entryPoint = entryPoint; }

      /**

      • The keyword in the configuration to designate this processor should be
      • used. Defaults to "REQUIRES_SECURE_CHANNEL".
      • @param secureKeyword
      • The secureKeyword to set.
        */
        public void setSecureKeyword(String secureKeyword) { this.secureKeyword = secureKeyword; }

      /**

      • @see net.sf.acegisecurity.securechannel.ChannelProcessor#decide(net.sf.acegisecurity.intercept.web.FilterInvocation,
      • net.sf.acegisecurity.ConfigAttributeDefinition)
        */
        public void decide(FilterInvocation invocation, ConfigAttributeDefinition config) throws IOException,
        ServletException
        {
        Assert.isTrue((invocation != null) && (config != null), "Nulls cannot be provided");

      Iterator iter = config.getConfigAttributes();

      while (iter.hasNext()) {
      ConfigAttribute attribute = (ConfigAttribute) iter.next();

      if (supports(attribute)) {
      Integer currentPort = new Integer(invocation.getHttpRequest().getServerPort());
      boolean foundPort = false;
      if (secureMode)

      { foundPort = getPortMapper().lookupHttpPort(currentPort) != null; }

      else

      { foundPort = getPortMapper().lookupHttpsPort(currentPort) != null; }

      if (!foundPort)

      { entryPoint.commence(invocation.getRequest(), invocation.getResponse()); }

      }
      }
      }

      /**

      • @see net.sf.acegisecurity.securechannel.ChannelProcessor#supports(net.sf.acegisecurity.ConfigAttribute)
        */
        public boolean supports(ConfigAttribute attribute) { return (attribute != null) && (attribute.getAttribute() != null) && attribute.getAttribute().equals(secureKeyword); }

      /**

      • Gets the portMapper. Defaults to PortMapperImpl if not set.
      • @return Returns the portMapper.
      • @see PortMapperImpl
        */
        public PortMapper getPortMapper()
        Unknown macro: { if (portMapper == null) { portMapper = new PortMapperImpl(); } return portMapper; }

        }

      The Springbean configs might be:
      <bean id="secureChannelProcessor" class="package.PortBasedChannelProcessor">
      <property name="entryPoint" ref="secureChannelEntryPoint"/>
      <property name="portMapper" ref="portMapper" />
      <property name="secureKeyword" value="REQUIRES_SECURE_CHANNEL"/>
      </bean>

      <bean id="insecureChannelProcessor" class="package.PortBasedChannelProcessor">
      <property name="entryPoint" ref="insecureChannelEntryPoint"/>
      <property name="portMapper" ref="portMapper" />
      <property name="secureKeyword" value="REQUIRES_INSECURE_CHANNEL"/>
      <property name="secureMode" value="false"/>
      </bean>

      These would be wired into the ChannelDecisionManager as needed.

        Attachments

          Activity

            People

            • Assignee:
              luke Luke Taylor
              Reporter:
              dhainlin David Hainlin
            • Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: