I have a little problem with tomcat. I'm trying to use the builtin authentication for the first time, but I cannot find a way to do what I need. Our registration process needs an email verified for some roles, but this seems to be a little problem. I have found a few ways to do it, but the most user friendly would be the following:
1. the user registers, and after that he/she can reach all content except those that require a valid email address
2. these special pages are marked with a role, and on 403 page there's a hint, that the email might not have been activated, and get two links pointing to the activation page and another to request new activation code
3. i have problem where they have entered their code:
3/a a relogin is required, but as they're already logged in it could be done automatically through request.login(username, password), but it seems to be broken, as the login succeeds, the new roles are read ( the user gains the email role), but after making a new request to such email page, 403 is shown again
3/b somehow the new role should be added to the subject, but i couldn't find a way to get it
What is "request.login()"? I've never heard of it.
In fact, the whole idea of having a J2EE webapp request a login is foreign to the architecture. The container is supposed to be making the decision on when a login is required; the webapp merely indicates the security constraints.
It also sounds like you're expecting the user's roles to be fluid. In the normal course of events, the roles granted to a user are captured when the user logs in and cannot be refreshed without forcing the user to logout and log back in again. Which in a container-based security environment would be done by invalidating the user's session before sending a response so that the next request (if any) would be vetted for a need to login, followed by a detour to the login process, if the new request URL is marked as secured.
In any event, it's rarely a good idea to make security rules modal. Too confusing.
The standard security mechanism accepts only user id and password as credentials. You could design a realm that would reject logins for users who don't have a valid email address on file, but there would be nothing specific for the need for a valid email returned, just generic login failure.
You could add fine-grained security to the app code itself where before doing one of these email-dependent functions, the user's login ID is used as a key to locate email validation resources, but that's about as close as it gets.
An IDE is no substitute for an Intelligent Developer.
Joined: Aug 04, 2010
HttpServletRequest.login(String, String) was added in Servlet API 3, and so it is available in Tomcat 7 Beta. The Servlet API 3 has a lot of features that could simplify our previous webframework, such as web-fragment jars, builtin support for file uploads, etc. So I thought this login feature would ease adding new roles to the users on the fly, because if the user is logged in than i can have him logout and login again in the background. But it seems that it's only request scoped and not session ( haven't looked at the implementation yet ).
I totally understand your point, and to be honest this email role would be a workaround, so we don't have to call "isEmailActivated" each time we need it. But I just might have to revert back to using that.
There are 2 methods of interest that were added. The authenticate() method induces a container-managed login and basically permits the app to act as though the inbound URL matched one of the secured URLs defined in web.xml
The second method, login() is designed to act as the processor for a login request without actually requiring the container to present the login form or dialog.
Traditionally, one logged out using session.invalidate(), but there's now an explicit logout() method, which ensures that the session and login processes can be handled discretely.
The login() method won't work if you're already logged in, so you have to logout, then login. The docs are sloppy, as they don't say what would happen if you logout when not logged in - whether that's an exception or ignored (which would be more sensible). However, you can test to see if you're logged in by seeing if getUserPrincipal() returns null or not. If it's null (or if getRemoteUser() is null), you're not logged in.
So here's a hypothetical usage:
Joined: Aug 04, 2010
Thanks for correcting the link, that was what I was thinking of, but was working with tomcat and pasted the wrong path.
So in the end everything should work the way I thought... But it still doesnt. I built a small webapp to demonstrate how I try to use it. As you said, the login method should programatically call the authentication in he background with a given username and password. Is it possible that this way the login information (the subject) is kept only for the life of the request and not the session?
To repeat the test the following war should be deployed. It contains everything packed up. (it seems that I cannot attach a war to my message, I'll put it up to my server: http://www.novyon.org:8180/loginDemo/loginDemo.war, the application is up and running at the same place)
1. on the index page click the admin link, and login with test / test
2. you will be welcome by the admin page with a link to a fluid role page and one to a servlet that grant the fluid role and redirects to the fluid page.
3. click the page not the servlet
4. 403 should be called as you don't already have that role, a link will get you to the servlet which should bring you back
5. instead of getting to the page, you will be brought back to the login page
on the system output you should see three loglines from the servlet:
1. before logout is called, you don't have the fluid role
2. after logout, but before login you still don't have the fluid role
3. after login you do have the fluid role
getting back to the login page instead of the 403 means to me that the logout works as expected.