If you are reading this, then I’m sure that you know that with the latest release, Spring’s Acegi Security has been renamed  Spring Security.

Much has changed. Setting up Spring Security for most applications now involves a drastically reduced amount of configuration xml, mostly thanks to the <http auto-config=’true’> tag, which automatically sets up the most commonly used options.

Most of the examples that I was able to find on the web for custom form-login, even for Acegi, showed the login form posting the login credentials in the clear, via http. Not very secure….

The solution seemed pretty simple - add channel security for the login page, like so:

<intercept-url pattern=”/login**” access=”IS_AUTHENTICATED_ANONYMOUSLY” requires-channel=”https” />

This did indeed make the login page switch to https. Unfortunately, it also made my login fail with a “Bad Credentials” message.

Many hours later, after trying all sorts of combinations, and combing the web for a clue, I determined that, not surprisingly, Spring Security was not broken, it was something that I had misconfigured.

Turns out that I had added a catch-all intercept-url, requiring http for anything not matching a url pattern that I had explicitly configured for https. The gotcha was that the login form posts to /j_spring_security_check - which was getting switched to http by the catch-all. Doh!

So, the solution was to explicitly configure /j_spring_security_check for https.

My resulting configuration is:

<http auto-config=’true’> <form-login login-page=”/login.jsp” authentication-failure-url=”/login.jsp?login_error=1” default-target-url=”/admin/user.htm” />

<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=”/admin/index.htm” access=”ROLE_USER” requires-channel=”https” />

<intercept-url pattern=”/admin/user.htm” access=”ROLE_USER” requires-channel=”https” />

<intercept-url pattern=”/admin/**” access=”ROLE_ADMIN” requires-channel=”https” />

<intercept-url pattern=”/**” access=”IS_AUTHENTICATED_ANONYMOUSLY” requires-channel=”http” />

</http>

And now everything works properly. Doh! Indeed.

If you’ve read this far, I hope that this saves you a few hours.