JETTY-1529 Ensure new session that has just been authenticated does not get renewed
This commit is contained in:
parent
2de6fa5c35
commit
748f06cad7
|
@ -24,8 +24,11 @@ import java.util.Set;
|
|||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
|
||||
import org.eclipse.jetty.server.AbstractHttpConnection;
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -34,6 +37,7 @@ import org.eclipse.jetty.server.UserIdentity;
|
|||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler.Context;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionManager;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -286,6 +290,32 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
getInitParameter(name)==null)
|
||||
setInitParameter(name,context.getInitParameter(name));
|
||||
}
|
||||
|
||||
//register a session listener to handle securing sessions when authentication is performed
|
||||
context.getContextHandler().addEventListener(new HttpSessionListener()
|
||||
{
|
||||
|
||||
public void sessionDestroyed(HttpSessionEvent se)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void sessionCreated(HttpSessionEvent se)
|
||||
{
|
||||
//if current request is authenticated, then as we have just created the session, mark it as secure, as it has not yet been returned to a user
|
||||
AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
|
||||
if (connection == null)
|
||||
return;
|
||||
Request request = connection.getRequest();
|
||||
if (request == null)
|
||||
return;
|
||||
|
||||
if (request.isSecure())
|
||||
{
|
||||
se.getSession().setAttribute(AbstractSessionManager.SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// complicated resolution of login and identity service to handle
|
||||
|
|
|
@ -83,7 +83,7 @@ public class BasicAuthenticator extends LoginAuthenticator
|
|||
UserIdentity user = _loginService.login(username,password);
|
||||
if (user!=null)
|
||||
{
|
||||
renewSessionOnAuthentication(request,response);
|
||||
renewSession(request,response);
|
||||
return new UserAuthentication(getAuthMethod(),user);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ public class ClientCertAuthenticator extends LoginAuthenticator
|
|||
UserIdentity user = _loginService.login(username,credential);
|
||||
if (user!=null)
|
||||
{
|
||||
renewSessionOnAuthentication(request,response);
|
||||
renewSession(request,response);
|
||||
return new UserAuthentication(getAuthMethod(),user);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ public class DigestAuthenticator extends LoginAuthenticator
|
|||
UserIdentity user = _loginService.login(digest.username,digest);
|
||||
if (user!=null)
|
||||
{
|
||||
renewSessionOnAuthentication(request,response);
|
||||
renewSession(request,response);
|
||||
return new UserAuthentication(getAuthMethod(),user);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
UserIdentity user = _loginService.login(username,password);
|
||||
if (user!=null)
|
||||
{
|
||||
session=renewSessionOnAuthentication(request,response);
|
||||
session=renewSession(request,response);
|
||||
|
||||
// Redirect to original request
|
||||
String nuri;
|
||||
|
|
|
@ -13,10 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.security.authentication;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -24,10 +20,10 @@ import javax.servlet.http.HttpSession;
|
|||
import org.eclipse.jetty.security.Authenticator;
|
||||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionManager;
|
||||
|
||||
public abstract class LoginAuthenticator implements Authenticator
|
||||
{
|
||||
public final static String SESSION_SECURED="org.eclipse.jetty.security.secured";
|
||||
protected final DeferredAuthentication _deferred=new DeferredAuthentication(this);
|
||||
protected LoginService _loginService;
|
||||
protected IdentityService _identityService;
|
||||
|
@ -53,34 +49,29 @@ public abstract class LoginAuthenticator implements Authenticator
|
|||
return _loginService;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Change the session when the request is authenticated for the first time
|
||||
/** Change the session id.
|
||||
* The session is changed to a new instance with a new ID if and only if:<ul>
|
||||
* <li>A session exists.
|
||||
* <li>The {@link AuthConfiguration#isSessionRenewedOnAuthentication()} returns true.
|
||||
* <li>The session ID has been given to unauthenticated responses
|
||||
* </ul>
|
||||
* @param request
|
||||
* @param response
|
||||
* @return The new session.
|
||||
*/
|
||||
protected HttpSession renewSessionOnAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
protected HttpSession renewSession(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
HttpSession httpSession = request.getSession(false);
|
||||
if (_renewSession && httpSession!=null && httpSession.getAttribute(SESSION_SECURED)==null)
|
||||
|
||||
//if we should renew sessions, and there is an existing session that may have been seen by non-authenticated users
|
||||
//(indicated by SESSION_SECURED not being set on the session) then we should change id
|
||||
if (_renewSession && httpSession!=null && httpSession.getAttribute(AbstractSessionManager.SESSION_KNOWN_ONLY_TO_AUTHENTICATED)!=Boolean.TRUE)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
Map<String,Object> attributes = new HashMap<String, Object>();
|
||||
for (Enumeration<String> e=httpSession.getAttributeNames();e.hasMoreElements();)
|
||||
{
|
||||
String name=e.nextElement();
|
||||
attributes.put(name,httpSession.getAttribute(name));
|
||||
httpSession.removeAttribute(name);
|
||||
}
|
||||
httpSession.invalidate();
|
||||
httpSession = request.getSession(true);
|
||||
httpSession.setAttribute(SESSION_SECURED,Boolean.TRUE);
|
||||
for (Map.Entry<String, Object> entry: attributes.entrySet())
|
||||
httpSession.setAttribute(entry.getKey(),entry.getValue());
|
||||
httpSession = AbstractSessionManager.renewSession(request, httpSession,true);
|
||||
}
|
||||
}
|
||||
|
||||
return httpSession;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.security.SecurityHandler;
|
|||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.eclipse.jetty.server.UserIdentity.Scope;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionManager;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -102,7 +103,7 @@ public class SessionAuthentication implements Authentication.User, Serializable,
|
|||
if (security!=null)
|
||||
security.logout(this);
|
||||
if (_session!=null)
|
||||
_session.removeAttribute(LoginAuthenticator.SESSION_SECURED);
|
||||
_session.removeAttribute(AbstractSessionManager.SESSION_KNOWN_ONLY_TO_AUTHENTICATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ import static java.lang.Math.round;
|
|||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
@ -57,6 +58,7 @@ import org.eclipse.jetty.util.statistic.SampleStatistic;
|
|||
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
|
||||
{
|
||||
final static Logger __log = SessionHandler.LOG;
|
||||
public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated";
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public final static int __distantFuture=60*60*24*7*52*20;
|
||||
|
@ -103,6 +105,28 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
protected final CounterStatistic _sessionsStats = new CounterStatistic();
|
||||
protected final SampleStatistic _sessionTimeStats = new SampleStatistic();
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static HttpSession renewSession (HttpServletRequest request, HttpSession httpSession, boolean authenticated)
|
||||
{
|
||||
Map<String,Object> attributes = new HashMap<String, Object>();
|
||||
|
||||
for (Enumeration<String> e=httpSession.getAttributeNames();e.hasMoreElements();)
|
||||
{
|
||||
String name=e.nextElement();
|
||||
attributes.put(name,httpSession.getAttribute(name));
|
||||
httpSession.removeAttribute(name);
|
||||
}
|
||||
|
||||
httpSession.invalidate();
|
||||
httpSession = request.getSession(true);
|
||||
if (authenticated)
|
||||
httpSession.setAttribute(SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE);
|
||||
for (Map.Entry<String, Object> entry: attributes.entrySet())
|
||||
httpSession.setAttribute(entry.getKey(),entry.getValue());
|
||||
return httpSession;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public AbstractSessionManager()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue