Announcement Announcement Module
Collapse
No announcement yet.
HTTPS to HTTP switch Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HTTPS to HTTP switch

    Hello -
    I am using Spring Security 2.0.3 and j_spring_security_check for forms authentication running on Tomcat 6.0.x. I am able to configure https successfully using channel security. But after login via https I am unable to redirect to a target URL that has requires-channel set to "http".
    Is this a Tomcat issue? If not is there a work around in Spring to enable HTTPS only during user authentication and allow HTTP after user authentication.
    my channel-security configuration is as below. In the below configuration if I substitute "any" with "https" it works as https is enabled for the entire application:
    <http auto-config="true">
    <form-login login-page="/login.jsp" />
    <port-mappings>
    <port-mapping http="8080" https="8443"/>
    </port-mappings>

    <intercept-url pattern="/login**" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
    <intercept-url pattern="/j_spring_security_check" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
    <intercept-url pattern="/*.do" requires-channel="any" access="ROLE_USER"/>

    <logout />
    </http>
    thanks
    vasi2020

  • #2
    What do you mean by "I am unable to redirect to a target URL that has requires-channel set to 'http'" - what actually happens?

    Remember also that in tomcat you can't change from a secure to insecure session without losing the session information:

    http://static.springframework.org/sp...-https-session

    Comment


    • #3
      What I meant is once the user is authenticated via https i wanted all protected urls within my application to be accessed via http instead of https.
      I looked up the link you referenced in your thread. I did not understand what they mean by "Starting in HTTP first should work".

      thanks
      vasi2020

      Comment


      • #4
        I found an old thread with code posted by you about extending RetryWithHttpEntryPoint to overcome the session context lost issue in tomcat. How do install and configure this class in spring?

        thanks
        vasi2020

        Comment


        • #5
          RetryWithHttpEntryPoint is used in InsecureChannelProcessor.

          Look at explicit channel configuration:
          http://static.springframework.org/sp...ecurity-config

          Comment


          • #6
            thanks Luke. Is this an issue with JBoss as well? thanks.

            Comment


            • #7
              Luke -
              I tried configuring the custom HttpEntryPoint but it is not taking effect. Here is how I configured it. I tried to place it in both applicationcontext.xml and security.xml. Neither of them took any effect.
              <bean id="customHttpEntryPoint" class="com.common.entrypoint.TomcatRetryWithHttpEn tryPoint"/>

              <bean id="insecureChannelProcessor" class="org.springframework.security.securechannel. InsecureChannelProcessor">
              <property name="entryPoint" ref="customHttpEntryPoint"/>
              </bean>

              What am I doing wrong?

              thanks

              Comment


              • #8
                Tomcat tracks user sessions with the help of the JSESSIONID cookie. If you enter into HTTPS with Tomcat, the cookie will come back with the secure property being set to true. Subsequently when the redirection to http occurs, the browser will not transmit the JSESSIONID cookie and you'll get a new session.

                Two ways of fixing this:
                1. RememberMe

                  Add a remember me entry to your security context:

                  Code:
                  <beans xmlns="http://www.springframework.org/schema/beans"
                  	xmlns:security="http://www.springframework.org/schema/security"
                  	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                                http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
                  
                  	<security:http auto-config="true">
                  		<security:intercept-url pattern="/login.jsp*"
                  			requires-channel="https" access="IS_AUTHENTICATED_ANONYMOUSLY" />
                  
                  		<security:intercept-url pattern="/j_spring_*"
                  			requires-channel="https" access="IS_AUTHENTICATED_ANONYMOUSLY" />
                  
                  		<security:intercept-url pattern="/**" access="ROLE_USER"
                  			requires-channel="http" />
                  
                  		<security:form-login login-page='/login.jsp' />
                  
                  		<security:port-mappings>
                  			<security:port-mapping http="8081" https="8443" />
                  		</security:port-mappings>
                  
                  		<!-- required for he intercept-url patterns above -->
                  		<security:anonymous />
                  
                  		<!-- required for he logout link in index.jsp -->
                  		<security:logout />
                  
                  		<security:remember-me />
                  	</security:http>
                  
                  	<security:authentication-provider>
                  		<security:user-service>
                  			<security:user password="password" name="chris"
                  				authorities="ROLE_USER" />
                  		</security:user-service>
                  	</security:authentication-provider>
                  
                  </beans>
                  and ensure your login form contains an entry for _spring_security_remember_me:

                  Code:
                  <input type='hidden' name='_spring_security_remember_me' value="true" />
                  This will cause Spring to send back another cookie to your browser named SPRING_SECURITY_REMEMBER_ME_COOKIE which doesn't set the secure property, and so you browser will transmit it in either HTTPS or HTTP, and the Spring authentication remember-me bean will be able to 'recover' you previous authentication details

                2. CustomFilter

                  Another solution is to create a filter which overrides the default Tomcat JSESSIONID behaviour. Note this must appear first in the filter chain:

                  web.xml

                  Code:
                  <filter>
                  		<filter-name>httpsCookieFilter</filter-name>
                  		<filter-class>test.HttpsCookieFilter</filter-class>
                  	</filter>
                  	<filter>
                  		<filter-name>springSecurityFilterChain</filter-name>
                  		<filter-class>
                  			org.springframework.web.filter.DelegatingFilterProxy
                  		</filter-class>
                  	</filter>
                  
                  	<!-- Cookie filter must go first to overwrite the default secure property of JSESSIONID -->
                  	<filter-mapping>
                  		<filter-name>httpsCookieFilter</filter-name>
                  		<url-pattern>/*</url-pattern>
                  	</filter-mapping>
                  	<filter-mapping>
                  		<filter-name>springSecurityFilterChain</filter-name>
                  		<url-pattern>/*</url-pattern>
                  	</filter-mapping>
                  and the filter code:

                  Code:
                  package test;
                  
                  import java.io.IOException;
                  
                  import javax.servlet.Filter;
                  import javax.servlet.FilterChain;
                  import javax.servlet.FilterConfig;
                  import javax.servlet.ServletException;
                  import javax.servlet.ServletRequest;
                  import javax.servlet.ServletResponse;
                  import javax.servlet.http.Cookie;
                  import javax.servlet.http.HttpServletRequest;
                  import javax.servlet.http.HttpServletResponse;
                  import javax.servlet.http.HttpSession;
                  
                  public class HttpsCookieFilter implements Filter {
                  
                  	@Override
                  	public void destroy() {}
                  
                  	@Override
                  	public void doFilter(ServletRequest request, ServletResponse response,
                  			FilterChain chain) throws IOException, ServletException {
                  
                  
                  		final HttpServletRequest httpRequest = (HttpServletRequest) request;
                  		final HttpServletResponse httpResponse = (HttpServletResponse) response;
                  		final HttpSession session = httpRequest.getSession(false);
                  
                  		if (session != null) {
                  			final Cookie sessionCookie = new Cookie("JSESSIONID", session
                  					.getId());
                  			sessionCookie.setMaxAge(-1);
                  			sessionCookie.setSecure(false);
                  			sessionCookie.setPath(httpRequest.getContextPath());
                  			httpResponse.addCookie(sessionCookie);
                  		}
                  
                  		chain.doFilter(request, response);
                  	}
                  
                  	@Override
                  	public void init(FilterConfig arg0) throws ServletException {}
                  
                  }

                Comment


                • #9
                  I should have also added that the reason Tomcat does this is because you otherwise have the potential to hijack another users session

                  Under the hood, i don't know what or how Spring generates the value for the SPRING_SECURITY_REMEMBER_ME_COOKIE cookie, and it *could* store more information such as the original request IP address, user agent, port (although the browser will probably not use the same port for HTTP and HTTPS traffic) etc, and when using the cookie value check the HttpRequest object for the original credentials.

                  These values could be hashed into the cookie value or stored in a LUT.

                  Again not total secure but better than just using the cookie value.

                  Comment


                  • #10
                    thank you so much. I tried the first option. It works - along with your suggestions I also had to include commons codec as spring requires it.

                    Comment


                    • #11
                      Have been struggling on this for days, this post made my day. Thank you!

                      Used the "remember me" feature, now it switch correctly beetwen http and https without losing the session.

                      Thanks again.

                      Comment


                      • #12
                        filter solution doesn't work

                        Thanks for the explanation, but the filter solution isn't working for me. I have verified that the code is running, and the cookies secure flag is getting set to false (checked via Firefox), but this doesn't solve the problem - I still keep getting the login screen. I don't want to use "remember me" exclusively because my users might be accessing the site from a public terminal.

                        A member of my local JUG suggested trying Jetty to verify the problem is Tomcat, and that is the case. Jetty works fine, but I don't want to switch to it just for this problem.

                        Any other solutions? It seems bizarre this can't be done on Tomcat.

                        Thanks!

                        Comment

                        Working...
                        X