My web application uses the internal web API (simple AJAX requests from the browser as the main client), which should ultimately be open to third parties. Since the API must be protected by security restrictions in web.xml , the user or client must be authenticated. A custom form authenticator is currently implemented, it performs some additional checks and actions, and then simply delegates further authentication processing to the FormAuthenticator class from which the custom authenticator is derived. This works very well, because the user is simply forced to log in and authenticate, and the only client is a web browser.
But FORM authentication is not very suitable for other clients: let it be an Android client, various third-party clients, etc. It is too easy to authenticate the form, they should all mimic the behavior I was looking for in this question: How to simulate form authentication in Tomcat using JMeter? . After some study of the Tomcat source code, I got the idea that you can extend the AuthenticatorBase class to implement your own authentication method (for example, FormAuthenticator or BasicAuthenticator.java do). I tried to do this:
public final class SimpleAuthenticator extends AuthenticatorBase { private static final String USERNAME_PARAMETER = "username"; private static final String PASSWORD_PARAMETER = "password"; @Override protected boolean authenticate(Request request, Response response, LoginConfig config) throws IOException { final Principal principal = request.getUserPrincipal(); final String ssoId = (String) request.getNote(REQ_SSOID_NOTE); if ( principal != null ) { if ( ssoId != null ) { associate(ssoId, request.getSessionInternal(true)); } return true; } if ( ssoId != null && reauthenticateFromSSO(ssoId, request) ) { return true; } final String contextPath = request.getContextPath(); final String requestURI = request.getDecodedRequestURI(); final boolean login = requestURI.equals(contextPath + "/authenticate"); if ( !login ) { response.sendError(SC_FORBIDDEN); return false; } final String username = request.getParameter(USERNAME_PARAMETER); final String password = request.getParameter(PASSWORD_PARAMETER); final Realm realm = context.getRealm(); final Principal authenticatedUserPrincipal = realm.authenticate(username, password); if ( authenticatedUserPrincipal == null ) { response.sendError(SC_UNAUTHORIZED); return false; } register(request, response, authenticatedUserPrincipal, "SIMPLE", username, password); return true; } }
Simply put, I would like to use something like /%CONTEXT_PATH%/authenticate?username=%USERNAME%&password=%PASSWORD% to authenticate the user using my non-standard SimpleAuthenticator form. Not quite sure if BasicAuthentication would be better for this case, but I had the following problems with the above example:
- Tomcat allows you to specify multiple
Valve in context.xml . If another authenticator is added to the context.xml file, then each protected resource is processed by each authenticator. (In principle, I understand why this is happening, but can they be divided into different resources?) /%CONTEXT_PATH%/authenticate unreachable (HTTP 404). (It is not clear knowing that /j_security_check somehow modeled.)- I could not find a way to specify several authentication schemes in Tomcat, so the "old" client of the web browser can still use
FormAuthenticator (as it is today), but the "light" clients can use the simplified one I tried to implement using SimpleAuthenticator . (I donβt even know if this is possible - this is the core). - As far as I understood the servlet specification, only one
login-config allowed for the entire web application. (Well, should I use another web application to provide an API?) - I saw some mention of the implementation of user authentication through
Filter , but if possible, I would like to separately store the authentication module in one place (for example, it already exists and is confirmed by Tomcat: an arbitrary form authenticator in a web application, and not as a separate JAR- module. Perhaps? .. However, I will very well consider the general concept that I use from scratch.
I suspect that I am doing a completely wrong thing and have a complete understanding, but I do not believe that there is no way to implement several authentication schemes in Tomcat.
Is there a way to provide multiple authentication schemes to extract authentication from FormAuthetication (for lightweight clients)? Your help will be greatly appreciated. Thanks in advance.