Am 08.01.16 um 14:03 schrieb André Warnier (tomcat):
Hi Thomas.
It is a bit difficult to figure out where the problem really is, without
having the full picture of what is going on (your web.xml configuration,
the order and precise timing in which requests really happen etc.).
But one thing I would really focus on, is the general overall logic of
the application, to see if the order in which things happen is really
consistent with the authentication method that you are using.
For example, if the initial call to the first page (the one which
contains the document links) does not immediately trigger a session
authentication, and in the meantime the browser starts making multiple
quasi-simultaneous requests for the links present in that page, then
things would get out of sync, since when the authentication does happen,
the session-id /will/ change (check Wikipedia for "web session
fixation"). That would overwrite the session-id cookie, perhaps in the
middle of the calls still being made to retrieve the document links
mentioned in the page.
Hi André,
I would like to give some insight information on how authentication is
handled.
As the application can run in command line or as a web application we
have a custom session handling (refer to it as 'core session'). Within
the core session there is a UserInformation implementation attached.
UserInformation can have different implementations and allows to ask for
the user id and if the user in in a specific role.
In the HttpSession we only store the sessionId of our core session. When
the http session is destroyed we also close the core session.
So there is only this one property "mycore.session" in the httpsession.
When using servlet container authentication (error happens only with
it). I need to access the request object which is stored in a
ThreadLocal and released at end of the request.
Here are the most important methods
private void loginIfNeeded() {
//getCurrentRequest() returns Optional<HttpServletRequest>
getCurrentRequest().ifPresent(currentRequest -> {
if (currentRequest.getUserPrincipal() == null) {
try {
currentRequest.login(user, pwd);
LOGGER.debug("Re-Logged in: " + user);
} catch (ServletException e) {
throw new RuntimeException(e);
}
}
});
}
public String getUserID() {
loginIfNeeded();
lastUser = getCurrentRequest()
.flatMap(r -> Optional.ofNullable(r.getUserPrincipal()))
.map(Principal::getName)
.orElseGet(() -> Optional.ofNullable(lastUser)
.orElseGet("guest");
return lastUser;
}
public boolean isUserInRole(String role) {
loginIfNeeded();
return getCurrentRequest().map(r ->
r.isUserInRole(role)).orElse(Boolean.FALSE);
}
When the user first authenticated with his login credentials we put the
servlet container user information to the core session. As the HTTP
session is linked to it, we just need the http session to keep track of it.
The error happens to be later, (possibly) many requests after the login
form that put UserInformation to the core session. So there is no racing
condition at that position.
You can see in the code that I need to re-login from time to time, as
the request object does not always return the remote user.
Why does that change the sessionId? How can I track the user than?
IMHO if HttpServletRequest.login() should only be called once in a http
session than getUserPrincipal() should always return a user after
login() is called on one request regarding to the same session, or?
But if calling login() always invalidates the old session we have a
problem here.
As long as request are coming in sequentially this would be OK, as the
browser gets a new cookie value with every response. But browsers are
out of control and want to give cpu cores a good time.
Anyway. I hope you are not lost in the details and are still willing to
help me.
regards,
Thomas
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org