Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x

This commit is contained in:
Jan Bartel 2019-03-20 18:39:53 +11:00
commit e01eefe40e
13 changed files with 473 additions and 66 deletions

View File

@ -52,13 +52,13 @@ Let's look at an example.
===== Step 1
Configure a Jetty `org.eclipse.jetty.jaas.JAASLoginService` to match the `<realm-name>` in your `web.xml` file. For example, if the `web.xml` contains a realm called "xyz" like so:
Configure a Jetty `org.eclipse.jetty.jaas.JAASLoginService` to match the `<realm-name>` in your `web.xml` file. For example, if the `web.xml` contains a realm called "Test JAAS Realm" like so:
[source, xml, subs="{sub-order}"]
----
<login-config>
<auth-method>FORM</auth-method>
<realm-name>xyz</realm-name>
<realm-name>Test JAAS Realm</realm-name>
<form-login-config>
<form-login-page>/login/login</form-login-page>
<form-error-page>/login/error</form-error-page>
@ -66,7 +66,7 @@ Configure a Jetty `org.eclipse.jetty.jaas.JAASLoginService` to match the `<realm
</login-config>
----
Then you need to create a `JAASLoginService` with the matching name of "xyz":
then you need to create a `JAASLoginService` with the matching realm name of "Test JAAS Realm":
[source, xml, subs="{sub-order}"]
----
@ -76,9 +76,10 @@ Then you need to create a `JAASLoginService` with the matching name of "xyz":
</New>
----
The `LoginModuleName` must match the name of your LoginModule as declared in your login module configuration file (see <<jaas-step-2,Step 2>>).
____
[CAUTION]
The name of the realm-name that you declare in `web.xml` must match exactly the name of your `JAASLoginService`.
The name of the realm-name that you declare in `web.xml` must match *exactly* the `Name` field of your `JAASLoginService`.
____
You can declare your `JAASLoginService` in a couple of different ways:
@ -135,7 +136,7 @@ xyz {
____
[CAUTION]
It is imperative that the application name on the first line is exactly the same as the `LoginModuleName` of your `JAASLoginService`.
It is imperative that the application name on the first line is *exactly* the same as the `LoginModuleName` of your `JAASLoginService`.
____
You may find it convenient to name this configuration file as `etc/login.conf` because, as we will see below, some of the wiring up for JAAS has been done for you.

View File

@ -21,6 +21,11 @@ package org.eclipse.jetty.security;
import java.io.Serializable;
import java.util.Set;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.UserIdentity.Scope;
@ -95,4 +100,23 @@ public abstract class AbstractUserAuthentication implements User, Serializable
return false;
}
@Override
public Authentication logout (ServletRequest request)
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
{
security.logout(this);
Authenticator authenticator = security.getAuthenticator();
if (authenticator instanceof LoginAuthenticator)
{
((LoginAuthenticator)authenticator).logout(request);
return new LoggedOutAuthentication((LoginAuthenticator)authenticator);
}
}
return Authentication.UNAUTHENTICATED;
}
}

View File

@ -80,7 +80,7 @@ public interface Authenticator
* @param mandatory True if authentication is mandatory.
* @return An Authentication. If Authentication is successful, this will be a {@link org.eclipse.jetty.server.Authentication.User}. If a response has
* been sent by the Authenticator (which can be done for both successful and unsuccessful authentications), then the result will
* implement {@link org.eclipse.jetty.server.Authentication.ResponseSent}. If Authentication is not manditory, then a
* implement {@link org.eclipse.jetty.server.Authentication.ResponseSent}. If Authentication is not mandatory, then a
* {@link org.eclipse.jetty.server.Authentication.Deferred} may be returned.
*
* @throws ServerAuthException if unable to validate request

View File

@ -0,0 +1,60 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.security;
import javax.servlet.ServletRequest;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
/**
* LoggedOutAuthentication
*
* An Authentication indicating that a user has been previously, but is not currently logged in,
* but may be capable of logging in after a call to Request.login(String,String)
*/
public class LoggedOutAuthentication implements Authentication.NonAuthenticated
{
private LoginAuthenticator _authenticator;
public LoggedOutAuthentication (LoginAuthenticator authenticator)
{
_authenticator = authenticator;
}
@Override
public Authentication login(String username, Object password, ServletRequest request)
{
if (username == null)
return null;
UserIdentity identity = _authenticator.login(username, password, request);
if (identity != null)
{
IdentityService identity_service = _authenticator.getLoginService().getIdentityService();
UserAuthentication authentication = new UserAuthentication("API",identity);
if (identity_service != null)
identity_service.associate(identity);
return authentication;
}
return null;
}
}

View File

@ -581,6 +581,9 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
public void logout(Authentication.User user)
{
LOG.debug("logout {}",user);
if (user == null)
return;
LoginService login_service=getLoginService();
if (login_service != null)
{

View File

@ -40,10 +40,9 @@ public class UserAuthentication extends AbstractUserAuthentication
}
@Override
@Deprecated
public void logout()
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
security.logout(this);
}
}

View File

@ -33,6 +33,8 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.LoggedOutAuthentication;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.server.Authentication;
@ -65,7 +67,6 @@ public class DeferredAuthentication implements Authentication.Deferred
try
{
Authentication authentication = _authenticator.validateRequest(request,__deferredResponse,true);
if (authentication!=null && (authentication instanceof Authentication.User) && !(authentication instanceof Authentication.ResponseSent))
{
LoginService login_service= _authenticator.getLoginService();
@ -131,6 +132,25 @@ public class DeferredAuthentication implements Authentication.Deferred
return null;
}
@Override
public Authentication logout (ServletRequest request)
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
{
security.logout(null);
if (_authenticator instanceof LoginAuthenticator)
{
((LoginAuthenticator)_authenticator).logout(request);
return new LoggedOutAuthentication((LoginAuthenticator)_authenticator);
}
}
return Authentication.UNAUTHENTICATED;
}
/* ------------------------------------------------------------ */
public Object getPreviousAssociation()
{

View File

@ -192,6 +192,7 @@ public class FormAuthenticator extends LoginAuthenticator
UserIdentity user = super.login(username,password,request);
if (user!=null)
{
HttpSession session = ((HttpServletRequest)request).getSession(true);
Authentication cached=new SessionAuthentication(getAuthMethod(),user,password);
session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
@ -200,6 +201,21 @@ public class FormAuthenticator extends LoginAuthenticator
}
@Override
public void logout(ServletRequest request)
{
super.logout(request);
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession(false);
if (session == null)
return;
//clean up session
session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
}
/* ------------------------------------------------------------ */
@Override
public void prepareRequest(ServletRequest request)
@ -537,7 +553,8 @@ public class FormAuthenticator extends LoginAuthenticator
}
/* ------------------------------------------------------------ */
/** This Authentication represents a just completed Form authentication.
/**
* This Authentication represents a just completed Form authentication.
* Subsequent requests from the same user are authenticated by the presents
* of a {@link SessionAuthentication} instance in their session.
*/

View File

@ -41,6 +41,8 @@ public abstract class LoginAuthenticator implements Authenticator
protected IdentityService _identityService;
private boolean _renewSession;
protected LoginAuthenticator()
{
}
@ -63,6 +65,19 @@ public abstract class LoginAuthenticator implements Authenticator
return null;
}
public void logout (ServletRequest request)
{
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession(false);
if (session == null)
return;
session.removeAttribute(Session.SESSION_CREATED_SECURE);
}
@Override
public void setConfiguration(AuthConfiguration configuration)
{

View File

@ -33,18 +33,25 @@ import org.eclipse.jetty.security.AbstractUserAuthentication;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.session.Session;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class SessionAuthentication extends AbstractUserAuthentication implements Serializable, HttpSessionActivationListener, HttpSessionBindingListener
/**
* SessionAuthentication
*
* When a user has been successfully authenticated with some types
* of Authenticator, the Authenticator stashes a SessionAuthentication
* into a HttpSession to remember that the user is authenticated.
*
*/
public class SessionAuthentication extends AbstractUserAuthentication
implements Serializable, HttpSessionActivationListener, HttpSessionBindingListener
{
private static final Logger LOG = Log.getLogger(SessionAuthentication.class);
private static final long serialVersionUID = -4643200685888258706L;
public final static String __J_AUTHENTICATED="org.eclipse.jetty.security.UserIdentity";
private final String _name;
@ -92,22 +99,11 @@ public class SessionAuthentication extends AbstractUserAuthentication implements
}
@Override
@Deprecated
public void logout()
{
if (_session!=null && _session.getAttribute(__J_AUTHENTICATED)!=null)
_session.removeAttribute(__J_AUTHENTICATED);
doLogout();
}
private void doLogout()
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
security.logout(this);
if (_session!=null)
_session.removeAttribute(Session.SESSION_CREATED_SECURE);
}
@Override
public String toString()
@ -118,7 +114,6 @@ public class SessionAuthentication extends AbstractUserAuthentication implements
@Override
public void sessionWillPassivate(HttpSessionEvent se)
{
}
@Override
@ -131,18 +126,15 @@ public class SessionAuthentication extends AbstractUserAuthentication implements
}
@Override
@Deprecated
public void valueBound(HttpSessionBindingEvent event)
{
if (_session==null)
{
_session=event.getSession();
}
}
@Override
@Deprecated
public void valueUnbound(HttpSessionBindingEvent event)
{
doLogout();
}
}

View File

@ -34,6 +34,8 @@ import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.servlet.DispatcherType;
import javax.servlet.HttpConstraintElement;
import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.ServletException;
@ -61,6 +63,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
@ -1054,6 +1057,174 @@ public class ConstraintTest
assertThat(response, containsString("!role"));
}
/**
* Test Request.login() Request.logout() with FORM authenticator
* @throws Exception
*/
@Test
public void testFormProgrammaticLoginLogout() throws Exception
{
//Test programmatic login/logout within same request:
// login - perform programmatic login that should succeed, next request should be also logged in
// loginfail - perform programmatic login that should fail, next request should not be logged in
// loginfaillogin - perform programmatic login that should fail then another that succeeds, next request should be logged in
// loginlogin - perform successful login then try another that should fail, next request should be logged in
// loginlogout - perform successful login then logout, next request should not be logged in
// loginlogoutlogin - perform successful login then logout then login successfully again, next request should be logged in
_security.setHandler(new ProgrammaticLoginRequestHandler());
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",false));
_server.start();
String response;
//login
response = _connector.getResponse("GET /ctx/prog?action=login HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
_server.stop();
//loginfail
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginfail HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
if (response.contains("JSESSIONID"))
{
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
}
else
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n\r\n");
assertThat(response, not(containsString("user=admin")));
_server.stop();
//loginfaillogin
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginfail HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
response = _connector.getResponse("GET /ctx/prog?action=login HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
_server.stop();
//loginlogin
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginlogin HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
_server.stop();
//loginlogout
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginlogout HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=null"));
_server.stop();
//loginlogoutlogin
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginlogoutlogin HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=user0"));
_server.stop();
//Test constraint-based login with programmatic login/logout:
// constraintlogin - perform constraint login, followed by programmatic login which should fail (already logged in)
_server.start();
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertThat(response, containsString(" 302 Found"));
assertThat(response, containsString("/ctx/testLoginPage"));
assertThat(response, containsString("JSESSIONID="));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/testLoginPage HTTP/1.0\r\n"+
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
assertThat(response, not(containsString("JSESSIONID=" + session)));
response = _connector.getResponse("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password");
assertThat(response, startsWith("HTTP/1.1 302 "));
assertThat(response, containsString("Location"));
assertThat(response, containsString("/ctx/auth/info"));
assertThat(response, containsString("JSESSIONID="));
assertThat(response, not(containsString("JSESSIONID=" + session)));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?action=constraintlogin HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
_server.stop();
// logout - perform constraint login, followed by programmatic logout, which should succeed
_server.start();
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertThat(response, containsString(" 302 Found"));
assertThat(response, containsString("/ctx/testLoginPage"));
assertThat(response, containsString("JSESSIONID="));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/testLoginPage HTTP/1.0\r\n"+
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
assertThat(response, not(containsString("JSESSIONID=" + session)));
response = _connector.getResponse("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password");
assertThat(response, startsWith("HTTP/1.1 302 "));
assertThat(response, containsString("Location"));
assertThat(response, containsString("/ctx/auth/info"));
assertThat(response, containsString("JSESSIONID="));
assertThat(response, not(containsString("JSESSIONID=" + session)));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?action=logout HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
assertThat(response, containsString("user=null"));
}
@Test
public void testStrictBasic() throws Exception
{
@ -1512,6 +1683,72 @@ public class ConstraintTest
}
}
private class ProgrammaticLoginRequestHandler extends AbstractHandler
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
{
baseRequest.setHandled(true);
String action = request.getParameter("action");
if (StringUtil.isBlank(action))
{
response.setStatus(200);
response.setContentType("text/plain; charset=UTF-8");
response.getWriter().println("user="+request.getRemoteUser());
return;
}
else if ("login".equals(action))
{
request.login("admin", "password");
return;
}
else if ("loginfail".equals(action))
{
request.login("admin", "fail");
return;
}
else if ("loginfaillogin".equals(action))
{
try
{
request.login("admin", "fail");
}
catch (ServletException se)
{
request.login("admin", "password");
}
return;
}
else if ("loginlogin".equals(action))
{
request.login("admin", "password");
request.login("foo", "bar");
}
else if ("loginlogout".equals(action))
{
request.login("admin", "password");
request.logout();
}
else if ("loginlogoutlogin".equals(action))
{
request.login("admin", "password");
request.logout();
request.login("user0", "password");
}
else if ("constraintlogin".equals(action))
{
String user = request.getRemoteUser();
request.login("admin", "password");
}
else if ("logout".equals(action))
{
request.logout();
}
else
response.sendError(500);
}
}
private class RoleRefHandler extends HandlerWrapper
{
/* ------------------------------------------------------------ */

View File

@ -45,11 +45,12 @@ public interface Authentication
/* ------------------------------------------------------------ */
/** A successful Authentication with User information.
*/
public interface User extends Authentication
public interface User extends LogoutAuthentication
{
String getAuthMethod();
UserIdentity getUserIdentity();
boolean isUserInRole(UserIdentity.Scope scope,String role);
@Deprecated
void logout();
}
@ -63,31 +64,13 @@ public interface Authentication
HttpServletResponse getHttpServletResponse();
}
/* ------------------------------------------------------------ */
/** A deferred authentication with methods to progress
* the authentication process.
/**
* An authentication that is capable of performing a programmatic login
* operation.
*
*/
public interface Deferred extends Authentication
public interface LoginAuthentication extends Authentication
{
/* ------------------------------------------------------------ */
/** Authenticate if possible without sending a challenge.
* This is used to check credentials that have been sent for
* non-manditory authentication.
* @param request the request
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request);
/* ------------------------------------------------------------ */
/** Authenticate and possibly send a challenge.
* This is used to initiate authentication for previously
* non-manditory authentication.
* @param request the request
* @param response the response
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request,ServletResponse response);
/* ------------------------------------------------------------ */
/** Login with the LOGIN authenticator
@ -100,6 +83,53 @@ public interface Authentication
}
/**
* An authentication that is capable of performing a programmatic
* logout operation.
*
*/
public interface LogoutAuthentication extends Authentication
{
/* ------------------------------------------------------------ */
/**
* Remove any user information that may be present in the request
* such that a call to getUserPrincipal/getRemoteUser will return null.
*
* @param request the request
* @return NoAuthentication if we successfully logged out
*/
Authentication logout (ServletRequest request);
}
/* ------------------------------------------------------------ */
/** A deferred authentication with methods to progress
* the authentication process.
*/
public interface Deferred extends LoginAuthentication, LogoutAuthentication
{
/* ------------------------------------------------------------ */
/** Authenticate if possible without sending a challenge.
* This is used to check credentials that have been sent for
* non-mandatory authentication.
* @param request the request
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request);
/* ------------------------------------------------------------ */
/** Authenticate and possibly send a challenge.
* This is used to initiate authentication for previously
* non-mandatory authentication.
* @param request the request
* @param response the response
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request,ServletResponse response);
}
/* ------------------------------------------------------------ */
/** Authentication Response sent state.
* Responses are sent by authenticators either to issue an
@ -128,6 +158,14 @@ public interface Authentication
{
}
/* ------------------------------------------------------------ */
/** After a logout, the authentication reverts to a state
* where it is possible to programmatically log in again.
*/
public interface NonAuthenticated extends LoginAuthentication
{
}
/* ------------------------------------------------------------ */
/** Unauthenticated state.
* <p>

View File

@ -2413,11 +2413,13 @@ public class Request implements HttpServletRequest
@Override
public void login(String username, String password) throws ServletException
{
if (_authentication instanceof Authentication.Deferred)
if (_authentication instanceof Authentication.LoginAuthentication)
{
_authentication=((Authentication.Deferred)_authentication).login(username,password,this);
if (_authentication == null)
Authentication auth = ((Authentication.LoginAuthentication)_authentication).login(username,password,this);
if (auth == null)
throw new Authentication.Failed("Authentication failed for username '"+username+"'");
else
_authentication = auth;
}
else
{
@ -2429,9 +2431,8 @@ public class Request implements HttpServletRequest
@Override
public void logout() throws ServletException
{
if (_authentication instanceof Authentication.User)
((Authentication.User)_authentication).logout();
_authentication=Authentication.UNAUTHENTICATED;
if (_authentication instanceof Authentication.LogoutAuthentication)
_authentication = ((Authentication.LogoutAuthentication)_authentication).logout(this);
}
/* ------------------------------------------------------------ */