aspose file tools*
The moose likes Tomcat and the fly likes Tomcat 7 : JSESSIONID not being sent to client Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Products » Tomcat
Bookmark "Tomcat 7 : JSESSIONID not being sent to client" Watch "Tomcat 7 : JSESSIONID not being sent to client" New topic
Author

Tomcat 7 : JSESSIONID not being sent to client

Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7
Howdy y'all,

I'm migrating from Tomcat6 to Tomcat7. The login process appears to have changed. The cookie: JSESSIONID is no longer sent to the client and when the request comes back to the server sans this vital info I get:

HTTP Status 408 - The time allowed for the login process has been exceeded.

So, I added the following code to my loginform.jsp:

response.addCookie(new Cookie("JSESSIONID", session.getId()));

and that almost works. almost in the sense that the first time I submit the page it doesn't work. but then i hit submit again and it does.

I'd like to know if anyone knows about this difference in Tomcat v6 and v7. I've been searching all day and have tried a number of things. I'm sure it has nothing to do with session-timeout. I also know that this doesn't help:

<meta http-equiv="Cache-Control" content="no-store,no-cache,must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">

I also tried

<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>

that doesn't work. Tomcat 7 won't even start if it sees something like that. the session-timeout is the only config option.

any hints?
Thanks. -E.

Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16250
    
  21

Welcome to the JavaRanch, Edgo!

It's hard to tell what's going on here, although I have a few suspicions. However, as far as cache options go, normally, your login would be done via SSL, and when Tomcat switches to SSL, it also disables ALL client-side cache options in its standard configurations. After all, a cached login form is a major security hole!

Whether or not the information required to maintain identity as you switch from non-authorized to authorized operation remains the same as in Tomcat6 and previous is moot. All that's really important is that the identity is preserved and you'd have to do a major job to convince me that a fundamental component of J(2)EE is no longer functional. So I'm more likely to believe that you're doing something wrong.

We need to have more info before we can tell what exactly isn't right, but a popular one is this:

Are you attempting to display the container-managed login JSP yourself? If so, be aware that that doesn't work and never has worked. Only Tomcat can properly render and process the login and loginfail pages defined in web.xml. If you attempt to manually invoke them by providing a URL, you won't have set up the proper login context and the form will not process properly. The container-managed Authentication and Authorization system of J2EE neither requires nor supports user-written login code. Tomcat will automatically detect when someone requests a protected URL and swap in the login form as needed and the only thing you have to do about it is define the WAR resource location of the login page (assuming form-based authentication).

Well, actually, you also have to setup a Tomcat security Realm, but that's not part of the web application, it's part of the Tomcat server configuration.


Customer surveys are for companies who didn't pay proper attention to begin with.
Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7
Thanks for the reply Sheriff Bar Keep,

I see that I neglected to explicitly mention that I'm using form-based auth but I reeckon you picked up on that. And, I agree that what's really important here is not so much Tomcat6 as it is Tomcat7. But Tomcat6 is my point of reference and here's how that worked:

in server.xml:



in web.xml:




I hope you can take my word for it that we have security-constraints configured properly.

Looking at it, I'm not really sure how I'm getting away without specifying a realm-name in the login-config but it works. And that's neither here nor there right now. The problem, as I see it is getting the JSESSIONID cookie to work.

I take that back. The problem is getting form authentication to work in Tomcat7.

I don't see anything on form-based authentication - or authentication at all - in this:

http://tomcat.apache.org/tomcat-7.0-doc/index.html

there is info on how to set up a realm but not how to use it.

I'll keep looking but in the meantime, I appreciate any suggestions.

thanks. -Erik.
Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7
I think I know why realm-name doesn't apply in the login-config. That realm-name is the area of the application that is protected via a security-constraint A JDBC Realm is a "database" of usernames and passwords . It's just confusing that they're both referred to as realms.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16250
    
  21

The entire J2EE security subssystem is designed to be abstract with a minimum of invasiveness and coupling. So you can mix and match your authentication UI and Realm in any way you want. I did assume form-based authentication simply because basic authentication has annoyances that make it the less common choice.

A Tomcat Realm is not a database. It's a service that provides an API implementation. One of the most commonly-invoked methods of this API is the authenticate() method, which is invoked when someone enters data into a basic dialog or loginpage form. The APU takes 2 arguments (id and credentials - a/k/a/ password) and does a go/no-go check on them. If the check succeeds, the Realm sets up a UserPrincipal object that holds the security objects for that user. If the check fails, the login is rejected.

One of the reasons why things are done this way is for enhanced security. The authenticate method doesn't fetch a user id or password. Instead, it accepts arguments and validates them. That way, the password is never hauled out into public view where an intruder can possibly capture it. In the JDBC realm implementation, an encrypted version of the password may be used to invoke a "SELECT COUNT(*) FROM xxxtable WHERE userid = ? AND password = ?". If the return count is 1, the login succeeds. If it's 0, the login fails. Anything else means someone didn't setup the database correctly. In any event, no decryption is required and secure data never leaves the database server.

Because authenticate is an API and not actually tied to a database, you can also implement it to do things like send the credentials to an LDAP/Active Directory server as an LDAP lookup instead of as an SQL request (I do this for many apps). Or you can create a Realm that asks a web service to authenticate.

Also because this is an API, you can set up for testing using one Realm, then switch to another simply by altering the Tomcat webapp context without making any app changes. For example, use a MemoryRealm for testing and an LDAP Realm for production.
Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7

I looked in the source to Tomcat and found the pertinent part of FormAuthenticator.java





Thoughts? anybody?

thanks. -E.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16250
    
  21

GO up a couple of lines. Your code excerpt starts just AFTER the call to authenticate!

Also, the session was supposed to have already been created at this point. The session test code you're looking at is to detect a hung authentication that might have caused the session to expire between the time Tomcat created it and the point that the test was made. You might get this, for example, in a case where the JDBC Realm's authenticate() method was invoked and the backend database server didn't return a response until 35 minutes later but your web.xml defined a 30-minute session timeout.
Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7
I've got session-timeout set to -1 so that ain't it.

Here's what I did: I searched through all of the source code to tomcat looking for the string '408'

%find . -name '*.java' -exec grep 408 {} \;

* Status code (408) indicating that the client did not produce a request
public static final int SC_REQUEST_TIMEOUT = 408;



Found it. So now look for SC_REQUEST_TIMEOUT and show me the name of the file(s) it occurs in

%find . -name '*.java' -exec grep -l SC_REQUEST_TIMEOUT {} \;
./java/javax/servlet/http/HttpServletResponse.java
./java/org/apache/catalina/authenticator/FormAuthenticator.java


That's it. It's defined it HttpServletResponse and used only in FormAuthenticator. And in only one place.


It's true that The session should have already been created and indeed it was. and then it was lost. the call: session = request.getSessionInternal(false); didn't find it.
And since there is no landing page, 408.

I downloaded the source in apache-tomcat-7.0.11-src.zip

I'm not an expert on this. Or, at least I've never even looked at the source to tomcat. But, there it is.

From what I understand, the session IS supposed to be destroyed and a new one is to take its place. That's a new security feature so hackers can't sniff the jsessionid cookie.

Again, I'm not an expert and I can't go saying the code is wrong without spending hours and hours becoming familiar with it. But I wonder what would happen if request.getSessionInternal(false); were instead: request.getSessionInternal(true); That is, create the session if it ain't there.

I have a feeling there's a good reason why it is the way it is. Maybe something else should have already created the session internally before authenticate was ever called.
I'd just like to be able to login.

Thanks for your replies.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16250
    
  21


From what I understand, the session IS supposed to be destroyed and a new one is to take its place. That's a new security feature so hackers can't sniff the jsessionid cookie.


Believe me, if that were true, there would be major breakage every time my JSF apps went from non-secured session-using resources to secured session-using resources. All my existing session objects would evaporate. And because I use container-managed security almost exclusively and routinely have public and private areas in my webapps, the explosion would be heard for miles.

The session remains. However, it is given a different session ID for use in the SSL transport. The session ID is a key used to locate the session in Tomcat's internal session map and has no inherent meaning in and of itself. But if you remove the key, it can no longer retrieve the map value object (session), even though a different key (the secure session ID) still can.

You really shouldn't be attempting to manually manipulate Tomcat's identity-tracking mechanisms. It is capable of doing the job quite well itself and has done so for years. Because it's a purely internal process it feels free to use any tricks it needs to to accomplish its purposes and your sole obligation in the matter is that if you intend to support browsers with cookies disabled, you should generate your hyperlinks using the J2Ee standard URL rewrite methods.

It you attempt to interject yourself directly into the process, you're asking for trouble. Firstly, because to do the job properly, you need to understand Tomcat's internals fairly well, and most of us aren't allotted enough time to make a good study of it. Secondly - and more importantly - updates to Tomcat may cause the whole thing to come crashing down around your ears when they make changes that your code didn't anticipate. Tomcat 7 is a great example of that, as they're adding web connection capabilities that didn't even exist when the earlier Tomcats were designed.

There are times when extreme measures need to be taken and we have to exploit internal and proprietary features of our server of choice , but simply transitioning between non-SSL and SSL with sessions is definitely not one of them. It's a very common function that people have been doing for years. Over a decade now in Tomcat's case, I believe. So they long ago laid that particular issue to rest.
Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7
Right, I misspoke. The session isn't destroyed, the sessionid is changed.

And believe me, I would never put any hack I made in a production environment. But for testing I can mess with it.

But now I have this funny feeling that I've really missed something from the start. Does Tomcat7 require SSL for authentication?
Edgo Quist
Greenhorn

Joined: Mar 28, 2011
Posts: 7
Solved.

/opt/tomcat/conf/catalina.properties had this in it:

# added to enforce Content-Type response header to include a charset=ISO-8859-1 component. (SRV.15.2.22.1)
org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true

that's not supposed to be there.

case closed - until I remember why I needed that.


thanks for all your help Tim.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16250
    
  21

In a long and evil career, one thing I've discovered is that the complex problems often turn out to be easier to solve than expected.

However, simple problems can require days to figure out. It's one of the reasons why I bolt for the exit when someone tells me "All You Have To Do Is...".
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Tomcat 7 : JSESSIONID not being sent to client