I'm not an expert on Spring Security, but my understanding is that at least in some cases, it works alongside the
J2EE standard (container-managed) security system. CM security wasn't really designed for a "login" button, because it automatically forces you to login whenever you submit a secured URL, as defined in the web.xml security URL
pattern set. This avoids the very common security hack where people simply bypass the login and go straight to (allegedly) secured pages.
Somewhere about JEE 6, however, the Enterprise
Java spec introduced an explicit login command that could force login from application program logic. I haven't had much luck with this, although then again, I never had need to try.
One thing that you do have to remember, however, when using container-managed security in
JSF is that the JSF URL isn't a direct URL, but rather more of a "handle" on the JSF session. So it often doesn't reflect the actual page requested. The CM security system, however, looks at the URL and
only at the URL to determine security requirements, so to force the URL and requested resource into sync, you need to navigate using the "redirect" option. It's a little extra overhead, but that way container security is enforced properly.
Please note, however that when you do form-based logins using container-managed security, the operative
word is
Container managed. The container (web server) is NOT routing the login through application logic, and in particular, not through the FacesServlet. Your login form must be either straight HTML or at least straight
JSP (NOT JSF). Because while you can format what goes out, what comes back goes directly to the webapp server, and not to program code, and all the webapp server will do is pluck the userid and password from the security form and feed them to the internal security Realm processor. That's part of what makes container security more secure than Do-It-Yourself code - if the login isn't done with user code, then it cannot exploit user code.
Additionally, please note that the client cannot force login by using the login form page path as a URL. The page will display, but since the container didn't request it, the mechanisms for processing the login form will not be returned to the login processor in the container. The container itself is the sole determinant of when to invoke the login form and the actual process of login is completely transparent to the application. No events are fired or methods invoked on login. The only actual change is that magically the remote user ID and userPrincipal fields in the HttpRequest are no longer going to be blank.