I wanted to update this particular thread with a valid and fairly easy
solution. For those just tuning in: If you want a way to have your login
form use SSL but the rest of your application use whatever the original
URL specified.... read on. Note this also keeps the login form from
showing as a URL in the browser.


Here are snippets of code used within our XMSLogin.jsp:

<%!
    StringBuffer sb;
    String orgHostURL;    // The original string that the user typed
    String actionURL;     // https://$orgHostURL/...
%>

<%
    int x;
    int y;
   
    sb = request.getRequestURL ();
    x = sb.indexOf("://");
    if (x >= 3)
    {
        x = x + 3;
    }
    else
    {
        x = 0;
    }
    
    y = sb.indexOf ("/", x);
    if (y <= 0)
    {
        y = sb.length ();
    }
    
    orgHostURL = sb.substring (x, y);
    // /Monitor should be changed to the context for future use.
    actionURL = "https://"; + orgHostURL + "/Monitor/j_security_check";
%>

<% // make sure the login is happening over a secure connection.
  if(!request.isSecure())
  {  
        String reqURL = request.getRequestURL().toString();
    if(reqURL.startsWith("http"))
    {
        // set this attribute to know that the session uses http 
        // instead of https
        request.getSession().setAttribute("http",new Boolean(true)); 
     }
  }
%>

and then later within the same XMSLogin.jsp:

<body>
  
  <form method="POST" 
        name="loginForm" 
        id="loginForm" 
        onsubmit="return(loginValidator(this));" 
        action="<%=response.encodeURL (actionURL)%>">
.... other html goes here ....

  </form>
</body>
</html>

The important part of the above is how the actionURL is built and the
setting of the session attribute.

Now once the user clicks on the form OK button, the action uses https.
It will stay that way unless we do a bit of work. You'll notice that in
the code above there is the following:

<% // make sure the login is happening over a secure connection.
  if(!request.isSecure())
  {  
        String reqURL = request.getRequestURL().toString();
    if(reqURL.startsWith("http"))
    {
        // set this attribute to know that the session uses http 
        // instead of https
        request.getSession().setAttribute("http",new Boolean(true)); 
     }
  }
%>

This sets up a session attribute if the original URL was only http. The
other JSP file(s) (which is the original URL target) have the following
at the top:

<% 
   com.mycompany.hm.callq.common.JSPHttpRedirect.redirectToHTTP(request,
response);
%>


Now here is java code:

package com.mycompany.hm.callq.common;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** This object is used by JSP pages in order to redirect the user from
the 
 *  https login screen to the url they requested. The only catch is that
the 
 *  URL the user requested required http. Therefore this object will 
 *  change the protocol of the URL back to http instead of https.
 *
 * @author psantos
 */
public class JSPHttpRedirect
{
    public final static boolean DEBUG = false;
    
    /** Creates a new instance of JSPHttpRedirect */
    public JSPHttpRedirect()
    {
    }
    
    /** This will redirect the user from the https login page to 
     *  the http page they are supposed to go to. If the request url 
     *  uses https then nothing is done.
     *  @param request The object that represents the client request.
     *  @param response The object that representes the client response.
     */
    public static void redirectToHTTP(HttpServletRequest request,
                                      HttpServletResponse response)
    {
        if(request.isSecure())
        {
            if(request.getSession().getAttribute("http") != null)
            {
                // we came from a secure login but we intended to use
http.
                // therefore we need to convert the URL to use http
protocol 

                String reqURL = request.getRequestURL().toString();
                
                if(reqURL.startsWith("https"))
                {
                    reqURL = reqURL.substring(5);
                    reqURL = "http"+reqURL;
                    
                    
                    boolean isMozillaBrowser =
isMozillaBrowser(request);
                    
                    // depending on the browser do the appropriate thing
to 
                    // avoid a popup being shown to the user that they
were 
                    // redirected from an https to an http URL.
                    
                    if(isMozillaBrowser) // mozilla perform a redirect.
                    {
                        try
                        {
 
response.sendRedirect(response.encodeRedirectURL(reqURL));
                        }
                        catch(Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                    else // internet explorer set the location header
field
                    {
                        reqURL = response.encodeURL(reqURL);
                        response.setHeader("Location",reqURL);
                    }
                }
            }
        }
    }
    
    /** This method determines the type of browser the request is from.
     *  If the browser is a netscape or mozilla browser return true.
     *  If it's internet explorer return false.
     *  @param request The object that represents the client request.
     */
    public static boolean isMozillaBrowser(HttpServletRequest request)
    {

        // this snipet of code was found over the web on 11/09/2005 
        // http://hotwired.lycos.com/
        // webmonkey/01/22/index3a_page4.html?tw=programming
        
        String agent = request.getHeader("USER-AGENT");
        if (null != agent && -1 != agent.indexOf("MSIE"))
        {
            return false;
        }
        return true;
    }
}


So in the end, if the user typed http:// then only the form data is
transmitted via https and everything else is http. If the user typed
https:// then it stays that way throughout. This works fine with 5.5.9.

Let me know if you need more details or see a flaw.


-Dennis

-----Original Message-----
From: Klotz Jr, Dennis 
Sent: Tuesday, November 29, 2005 10:49 AM
To: 'Tomcat Users List'
Subject: RE: web.xml question

Thanks for your reply.

I really hope that isn't the case. I really do not want the
computational overhead of SSL for the rest of my web application. We are
sending back thousands of rows of data.

Paulo, my co-worker, figured out that he could use a redirect inside of
the login.jsp to force the use of https but that in itself has problems.
For example, if you directly type the URL of that login.jsp you will get
a 400 error. (the login.jsp is no longer transparent - at least that is
my understanding)

I find this a hard pill to swallow :) that one must enable SSL for the
whole webapp if you wish to use a form based login.


-Dennis

-----Original Message-----
From: Tim Funk [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, November 29, 2005 10:34 AM
To: Tomcat Users List
Subject: Re: web.xml question

Security constraints are only imposed on the incoming URL.

Long story short - you'll need to place the entire webapp in SSL. There
is no 
clean way to use declarative statements to force the login to be SSL and
the 
rest of the webapp be nonssl.

-Tim

Klotz Jr, Dennis wrote:

> Hello all. I hope your day is going well.
> 
> I need your help.
> 
> I cannot get a forms based login page to use SSL when I think I've
setup
> the web.xml correctly. 
> 
> Why doesn't my login.jsp use HTTPS when tomcat is invoking it for
> authorization? (more details at the bottom)
> 
> Here are the relevant sections of my web.xml:
> 
> -----------------------------------------
> 
> <!-- BEGIN_LOGIN_SECURITY -->
>    <security-constraint>
>     <web-resource-collection>
>       <web-resource-name>Login page</web-resource-name>
>       <url-pattern>/login.jsp</url-pattern>
>       <http-method>GET</http-method>
>       <http-method>POST</http-method>
>     </web-resource-collection>
> 
>     <!--   Enable this for SSL -->
> 
>     <user-data-constraint>
>       <transport-guarantee>CONFIDENTIAL
>       </transport-guarantee>
>     </user-data-constraint>
>   </security-constraint>
> 
>   <!-- END_LOGIN_SECURITY -->
> 
>   <!-- ======================================= -->
> 
>   <!-- LOGIN AUTHENTICATION -->
>   <!-- Form authentaication requires SSL -->
>        <login-config>
>            <auth-method>FORM</auth-method>
>            <realm-name>Application</realm-name>
>            <form-login-config>
>                <form-login-page>/login.jsp</form-login-page>
>                <form-error-page>/error_401.html</form-error-page>
>            </form-login-config>
>        </login-config>
> 
> 
> 
>   <security-constraint>
>     <web-resource-collection>
>       <web-resource-name>VoIP Monitor Applications</web-resource-name>
>       <url-pattern>/CallQDiagnostics.jsp</url-pattern>
>       <url-pattern>/report_index.jsp</url-pattern>
>       <url-pattern>/CallQAnalysis.jsp</url-pattern>
>       <url-pattern>/index.jsp</url-pattern>
>       <http-method>GET</http-method>
>       <http-method>POST</http-method>
>     </web-resource-collection>
> 
>     <auth-constraint>
>       <role-name>monitor_tier1</role-name>
>       <role-name>monitor_guest</role-name>
>       <role-name>monitor_admin</role-name>
>       <role-name>monitor_tier3</role-name>
>     </auth-constraint>
> 
>     <!--   Enable this for SSL -->
> 
>     <user-data-constraint>
>       <transport-guarantee>NONE
>       </transport-guarantee>
>     </user-data-constraint>
> 
>   </security-constraint>
> 
> ----------------------------------------------------------
> 
> So here is what happens. I type the full URL to the CallQAnalsysis.jsp
> (for example) and the login.jsp is invoked BUT it has NOT been
> redirected to the HTTPS connector (which is enabled and working).
> 
> Now if I type the address of the login.jsp directly, then the
connection
> is redirected over HTTPS. 
> 
> Why doesn't the login.jsp use HTTPS when tomcat is invoking it for
> authorization?
> 
> Any help figuring out what I am doing wrong is greatly appreciated.
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to