我的 Web 应用程序使用内部 Web API(来自浏览器的简单 AJAX 请求,因为它是主要客户端)最终应该向外部公开给第 3 方。由于 API 已经并且必须使用 中的安全约束进行保护,因此必须对web.xml
用户或客户端进行身份验证。目前,实现了一个自定义表单身份验证器,它执行一些额外的检查和操作,然后简单地将进一步的身份验证处理委托给FormAuthenticator
自定义身份验证器派生的类。这真的很好用,因为用户只是被迫登录并通过身份验证,唯一的客户端是 Web 浏览器。
但是 FORM 身份验证不太适合其他类型的客户端:比方说 Android 客户端、各种 3rd 方客户端等。太通过表单身份验证它们都必须模拟我在这个问题中寻找的行为:我如何模拟使用 JMeter 在 Tomcat 中进行表单身份验证?. 在对 Tomcat 源代码进行了一些调查之后,我有了一个想法,即应该可以扩展AuthenticatorBase
该类以实现自己的身份验证方式(喜欢FormAuthenticator
或BasicAuthenticator.java
做)。我试图做的是:
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;
}
}
简单地说,我想使用类似的东西/%CONTEXT_PATH%/authenticate?username=%USERNAME%&password=%PASSWORD%
来验证我的自定义 non-form 用户SimpleAuthenticator
。不太确定在BasicAuthentication
这种情况下是否会更好,但我在上面的示例中遇到了以下问题:
- Tomcat 允许
Valve
在context.xml
. 如果将另一个身份验证器添加到context.xml
文件中,则每个安全资源都会与每个身份验证器一起处理。(原则上,我理解它为什么会发生,但是它们可以为不同的资源分开吗?) /%CONTEXT_PATH%/authenticate
不可访问(HTTP 404)。(尚不清楚,但不知道这/j_security_check
是以某种方式模拟的。)- 我找不到在 Tomcat 中指定多个身份验证方案的方法,因此“旧”Web 浏览器客户端仍然可以使用
FormAuthenticator
(就像今天一样),但“轻量级”客户端可以使用我尝试实现的简化身份验证SimpleAuthenticator
. (甚至不知道这是否可能——这是核心) - 据我了解 servlet 规范,
login-config
整个 web 应用程序只允许一个。(好吧,我应该使用另一个 Web 应用程序来提供 API 吗?) - 我看到一些提到通过 实现自定义身份验证
Filter
,但如果可能的话——我想将身份验证器模块单独保存在一个地方(就像它已经存在并通过Tomcat 确认:Web 应用程序中的自定义表单身份验证器,而不是一个独立的 JAR 模块。可能吗?)。但是,我可以从头开始回顾我使用的一般概念。
我怀疑我在做一件非常错误的事情并且完全理解,但我不相信没有办法在 Tomcat 中实现多个身份验证方案。
有没有办法提供多种身份验证方案来提取身份验证FormAuthetication
(对于轻量级客户端)?您的帮助将非常感激。提前致谢。