Spring Security
  1. Spring Security
  2. SEC-1893

Default https 8443 port mappings redirection

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Complete
    • Affects Version/s: 3.1.0
    • Fix Version/s: 3.1.1
    • Component/s: Namespace
    • Environment:

      Description

      Port-mappings does not work properly,

      when it setup in spring xml configuration such as:
      <ss:port-mappings>
      <ss:port-mapping http="8181" https="8080"/>
      </ss:port-mappings>
      with:
      <ss:form-login login-page="/access/login.html"
      username-parameter="username"
      password-parameter="password"
      login-processing-url="/app/loginuser"
      default-target-url="/app/" />

      Spring security redirected me to url (https://localhost:8443/access/login.html must be https://localhost:8080/access/login.html) with 8443 port (by default in the org/springframework/security/web/PortMapperImpl.java) when I try to access protected page.
      I edited PortMapperImpl.java:

      public PortMapperImpl()

      { httpsPortMappings = new HashMap<Integer, Integer>(); httpsPortMappings.put(Integer.valueOf(8080), Integer.valueOf(8080)); }

      and redirection is working now to 8080 https.
      I think that when <ss:port-mappings>...</ss:port-mappings> setted,

      PortMapperImpl.java:
      private final Map<Integer, Integer> httpsPortMappings;

      "httpsPortMappings" not cleaned properly, and previously key value are available.

        Activity

        Hide
        Rob Winch added a comment -

        I'm not able to reproduce this issue in Spring Security 3.1. I do not think the default constructor is a problem because PortMapperImpl.setPortMappings invokes httpsPortMappings.clear(). I'm curious how it even got to the login page then since if it was doing the port mapping incorrectly the request for the protected resource of https would have been the wrong URL meaning that a redirect to the login page would not have worked. I noticed that the URLs in your Spring Security configuration were using /app but the URL you posted did not. Are you by chance using UrlRewriteFilter? If so, this may be the source of the problem. If you still believe this is an issue, can you provide as simple of a project that reproduces the problem and provide instructions on how to reproduce this issue?

        Show
        Rob Winch added a comment - I'm not able to reproduce this issue in Spring Security 3.1. I do not think the default constructor is a problem because PortMapperImpl.setPortMappings invokes httpsPortMappings.clear() . I'm curious how it even got to the login page then since if it was doing the port mapping incorrectly the request for the protected resource of https would have been the wrong URL meaning that a redirect to the login page would not have worked. I noticed that the URLs in your Spring Security configuration were using /app but the URL you posted did not. Are you by chance using UrlRewriteFilter? If so, this may be the source of the problem. If you still believe this is an issue, can you provide as simple of a project that reproduces the problem and provide instructions on how to reproduce this issue?
        Hide
        Luke Woodward added a comment -

        I have been able to reproduce this issue, using Spring Security 3.1.0.RELEASE and Apache Tomcat 6.0.35 on Windows 7 x64. I installed Tomcat using the Windows .msi installer, and the only change I've made to its configuration is the change to conf/server.xml described below.

        I've attached to this issue a small web application that I used to reproduce this issue. This web application has a single login-protected page, and if you get to the login page, the credentials test/test should let you log in.

        To reproduce the issue:

        1. Extract the attached zip file TestSecureApp.zip somewhere.
        2. Edit the extracted build.xml file and set the value of the property tomcat.home to your Tomcat home directory.
        3. Run ant to compile, build and deploy to Tomcat a WAR file for this web application.
        4. Set up SSL in Tomcat, following the instructions at http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html :
          • Run keytool, using the default password changeit.
          • Add the following Connector element to conf/server.xml within Tomcat, and comment out all other Connectors. Change the location of the keystoreFile as appropriate.
                 
                <Connector port="8080" protocol="HTTP/1.1" SSLEnabled="true"
                           maxThreads="150" scheme="https" secure="true"
                           keystoreFile="C:/Users/Luke/.keystore" keystorePass="changeit"
                           clientAuth="false" sslProtocol="TLS" />
            
        5. Start Tomcat, and navigate to https://localhost:8080/. You'll get a warning about an invalid (self-signed) security certificate: ignore/accept it as necessary. This should bring up the Tomcat default page (unless you've replaced it with something else).
        6. Navigate to https://localhost:8080/TestSecureWebApp/. Using Firefox, I get an error "Firefox can't establish a connection to the server at localhost:8443."

        I've done a brief bit of digging into this issue myself. I set a breakpoint in PortMapperImpl.lookupHttpsPort (line 68 of org/springframework/security/web/PortMapperImpl.java by my reckoning) and then attempted to log into my application. I found that this breakpoint was hit three times. The first two times, the port mapper had the mapping I set up in applicationContext-security.xml (8080 -> 8080). However, the third time this breakpoint was hit, it was in a different PortMapperImpl instance, and this instance still had the default 80 -> 443 and 8080 -> 8443 mappings in it.

        Ultimately, it seems that there is more than one PortMapperImpl instance kicking about, and it's the other one (or ones?) that are the problem here.

        Show
        Luke Woodward added a comment - I have been able to reproduce this issue, using Spring Security 3.1.0.RELEASE and Apache Tomcat 6.0.35 on Windows 7 x64. I installed Tomcat using the Windows .msi installer, and the only change I've made to its configuration is the change to conf/server.xml described below. I've attached to this issue a small web application that I used to reproduce this issue. This web application has a single login-protected page, and if you get to the login page, the credentials test/test should let you log in. To reproduce the issue: Extract the attached zip file TestSecureApp.zip somewhere. Edit the extracted build.xml file and set the value of the property tomcat.home to your Tomcat home directory. Run ant to compile, build and deploy to Tomcat a WAR file for this web application. Set up SSL in Tomcat, following the instructions at http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html : Run keytool , using the default password changeit . Add the following Connector element to conf/server.xml within Tomcat, and comment out all other Connectors. Change the location of the keystoreFile as appropriate. <Connector port="8080" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="C:/Users/Luke/.keystore" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" /> Start Tomcat, and navigate to https://localhost:8080/ . You'll get a warning about an invalid (self-signed) security certificate: ignore/accept it as necessary. This should bring up the Tomcat default page (unless you've replaced it with something else). Navigate to https://localhost:8080/TestSecureWebApp/ . Using Firefox, I get an error "Firefox can't establish a connection to the server at localhost:8443." I've done a brief bit of digging into this issue myself. I set a breakpoint in PortMapperImpl.lookupHttpsPort (line 68 of org/springframework/security/web/PortMapperImpl.java by my reckoning) and then attempted to log into my application. I found that this breakpoint was hit three times. The first two times, the port mapper had the mapping I set up in applicationContext-security.xml (8080 -> 8080). However, the third time this breakpoint was hit, it was in a different PortMapperImpl instance, and this instance still had the default 80 -> 443 and 8080 -> 8443 mappings in it. Ultimately, it seems that there is more than one PortMapperImpl instance kicking about, and it's the other one (or ones?) that are the problem here.
        Hide
        Rob Winch added a comment -

        The problem is that the PortResolver in the LoginUrlAuthenticationEntryPoint uses a PortMapper that is not configured by the namespace (AuthenticationConfigBuilder). This would only impact instances where the http port is using a common https port or vice versa. In the meantime, you can configure the LoginUrlAuthenticationEntryPoint explicitly. Something like the following should work:

        <sec:http auto-config="true" entry-point-ref="entryPoint">
            ...
            <sec:port-mappings >
                <sec:port-mapping http="8080" https="8080" />
            </sec:port-mappings>
        </sec:http>
        
        <bean id="entryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <constructor-arg value="/login.html"/>
            <property name="portResolver">
                <bean class="org.springframework.security.web.PortResolverImpl">
                    <property name="portMapper" ref="portMapper"/>
                </bean>
            </property>
            <!-- this also doesn't get set but is only necessary if you were using forceHttps=true -->
            <property name="portMapper" ref="portMapper"/>
        </bean>
        <bean id="portMapper" class="org.springframework.security.web.PortMapperImpl">
            <property name="portMappings">
                <map>
                    <entry key="8080" value="8080"/>
                </map>
            </property>
        </bean>
        

        PS: Any reason the attached example application maps the http port 8080 to https port 8080?

        Show
        Rob Winch added a comment - The problem is that the PortResolver in the LoginUrlAuthenticationEntryPoint uses a PortMapper that is not configured by the namespace (AuthenticationConfigBuilder). This would only impact instances where the http port is using a common https port or vice versa. In the meantime, you can configure the LoginUrlAuthenticationEntryPoint explicitly. Something like the following should work: <sec:http auto-config= " true " entry-point-ref= "entryPoint" > ... <sec:port-mappings > <sec:port-mapping http= "8080" https= "8080" /> </sec:port-mappings> </sec:http> <bean id= "entryPoint" class= "org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint" > <constructor-arg value= "/login.html" /> <property name= "portResolver" > <bean class= "org.springframework.security.web.PortResolverImpl" > <property name= "portMapper" ref= "portMapper" /> </bean> </property> <!-- this also doesn't get set but is only necessary if you were using forceHttps= true --> <property name= "portMapper" ref= "portMapper" /> </bean> <bean id= "portMapper" class= "org.springframework.security.web.PortMapperImpl" > <property name= "portMappings" > <map> <entry key= "8080" value= "8080" /> </map> </property> </bean> PS: Any reason the attached example application maps the http port 8080 to https port 8080?
        Hide
        Luke Woodward added a comment -

        The application I submitted runs entirely in HTTPS - there's no HTTP part, and so (as far as I understand) there isn't really any need for HTTP to HTTPS port mappings. The one mapping I provided was a dummy mapping: I would have used an empty set of port-mappings if I could, but that doesn't validate against the schema.

        Show
        Luke Woodward added a comment - The application I submitted runs entirely in HTTPS - there's no HTTP part, and so (as far as I understand) there isn't really any need for HTTP to HTTPS port mappings. The one mapping I provided was a dummy mapping: I would have used an empty set of port-mappings if I could, but that doesn't validate against the schema.
        Hide
        Rob Winch added a comment -

        In reply to comment #4:
        > The application I submitted runs entirely in HTTPS - there's no HTTP part, and
        > so (as far as I understand) there isn't really any need for HTTP to HTTPS port
        > mappings. The one mapping I provided was a dummy mapping: I would have used an
        > empty set of port-mappings if I could, but that doesn't validate against the
        > schema.

        Ok so this was just an attempt to work around the bug then. I ask because it can be useful to know what others are doing and why they are doing it.

        Show
        Rob Winch added a comment - In reply to comment #4: > The application I submitted runs entirely in HTTPS - there's no HTTP part, and > so (as far as I understand) there isn't really any need for HTTP to HTTPS port > mappings. The one mapping I provided was a dummy mapping: I would have used an > empty set of port-mappings if I could, but that doesn't validate against the > schema. Ok so this was just an attempt to work around the bug then. I ask because it can be useful to know what others are doing and why they are doing it.
        Hide
        Rob Winch added a comment -

        I have pushed a fix into master.

        Show
        Rob Winch added a comment - I have pushed a fix into master.
        Hide
        Luke Woodward added a comment -

        I've now tested the fix (sorry for the delay in doing so) and I can confirm that it works. Thanks.

        Show
        Luke Woodward added a comment - I've now tested the fix (sorry for the delay in doing so) and I can confirm that it works. Thanks.

          People

          • Assignee:
            Rob Winch
            Reporter:
            Alexander Sedelnikov
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: