I've finally got my app deployed to a 2 instance single node test cluster fronted by apache/mod_jk load balancing.
In a non-clustered environment I've been using container security with JDBCRealm for ages and it works reliably.
In the cluster environment, I get the login page in the browser, type a valid username and password, click the submit button and j_security_check sets the location page in the response header as the login page, not the welcome-file. It fowards to the login page we were just on.
I've enabled the MySQL general query log and can see that password & group name are being read from the right table for the right user.
I tried setting javax.enterprise.system.core.security.level=FINEST but there's still no output in the server log.
With the same app deployed to the local server rather than the cluster I can access localhost:8080/ and login ok. If I just type "localhost" and go through the load balancer it won't work.
I know that j_security_check can forward to the page that triggered the authentication (which is presumably what's happening here), but when does it forward to the welcome-file, when there is no "page that triggered the authentication"? Edit: I see now, it always 302 redirects to the referer, which is the context-root in this case. The container must have some rules which determine which page actually gets shown. In my cluster example it is not the welcome-file from web.xml.
I also setup my auth realm in the cluster config:
asadmin> create-auth-realm --target c1 --classname com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm --property jaas-context=jdbcRealm:datasource-jndi=jdbc/sportquest:user-table=users:user-name-column=username:password-column=password:group-table=users:group-name-column=groupname:digest-algorithm=SHA-256:encoding=Base64
The only difference I can think of between the two environments is that in the cluster setup I have a mod_rewrite rule which fowards from http -> https (httpd.conf):
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# This redirects from thingy.com to www.thingy.com
#
RewriteCond %{HTTP_HOST} !^thingy\.com$ [NC]
RewriteRule ^(.*)$ %{HTTPS}://thingy.com/$1 [R=301,L]
Edit: added below chrome dev tools network trace
The working scenario deployed as /MyApp:
GET http://localhost:8080/MyApp - 301 Moved Permanently (from cache)
GET http://localhost:8080/MyApp/ - 200 Ok
... login page loads ...
POST http://localhost:8080/MyApp/j_security_check - 302 Moved Temporarily
the form data contains user/pass as expected & response header Location:
http://localhost:8080/MyApp/
GET http://localhost:8080/MyApp/ - 200 Ok
... welcome-file page loads ...
The not working scenario (cluster) deployed as root / :
GET http://localhost/ - 301 Moved Permanently (from cache)
GET https://localhost/ - 200 Ok
... login page loads ...
POST https://localhost/j_security_check - 302 Moved Temporarily
the form data contains user/pass as expected & response header Location:
https://localhost/
GET https://localhost/ - 200 Ok
... the login page loads ...
If I type in invalid login credentials then in both cases I successfully redirect to the form-error-page.
Anyone got any suggestions? I'm just not seeing it. Thanks.
p.s. I did try a browser cache clean, no help!
Update: The problem is that in the clustered/mod_jk environment the postback from j_security_check has a Set-Cookie with a new sessionid, so the next request comes in on a different session. It seems that this is something to do with sticky sessions, however I still don't know how to fix it. I've tried setting the loadbalancer sticky_sessions to true and false but neither helps.
jvmRoute is set for both instances to the workers.
Why don't you just use mod_proxy & mod_proxy_balancer instead? That way you can set the reverse cookie path for the different context roots. Let me know if you need some configuration examples (on the iPhone atm)