java – Tomcat:单个Web应用程序的多种身份验证方案?

我的Web应用程序使用内部Web API(来自浏览器的简单
AJAX请求,因为它是主要客户端),最终应该在第三方外部公开.由于API必须受到web.xml中的安全性约束的保护,因此必须对用户或客户端进行身份验证.目前,有一个自定义表单身份验证器实现,它执行一些额外的检查和操作,然后简单地将进一步的身份验证处理委托给自定义身份验证器派生自的FormAuthenticator类.这非常好用,因为用户只是被迫登录并通过身份验证,而唯一的客户端是Web浏览器.

但是FORM身份验证并不适合其他类型的客户端:假设有一个Android客户端,各种第三方客户端等.要通过表单身份验证,他们都必须模拟我在这个问题中寻找的行为:How can I simulate form authentication in Tomcat using JMeter?.在对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%来使用我的自定义非格式SimpleAuthenticator对用户进行身份验证.不确定BasicAuthentication是否会对这种情况更好,但我在上面的例子中遇到了以下问题:

> Tomcat允许在context.xml中指定多个Valve.如果将另一个身份验证器添加到context.xml文件中,则每个身份验证器都会处理每个安全资源. (原则上,我理解为什么会发生这种情况,但它们是否可以针对不同的资源分开?)
> /%CONTEXT_PATH%/ authenticate不可访问(HTTP 404). (还不清楚是否知道/ j_security_check是以某种方式模拟的.)
>我找不到在Tomcat中指定多个身份验证方案的方法,因此“旧”Web浏览器客户端仍然可以使用FormAuthenticator(就像今天一样),但“轻量级”客户端可以使用我试过的简化身份验证使用SimpleAuthenticator实现. (甚至不知道是否可能 – 这是核心)
>据我所知,servlet规范只允许一个login-config用于整个web应用程序. (那么,我应该使用其他网络应用程序来提供API吗?)
>我看到一些提及通过过滤器实现自定义身份验证,但如果可能的话 – 我想将验证器模块分开放在一个地方(就像它已经存在并通过Tomcat: Custom form authenicator in a web application, not as a stand-alone JAR module. Possible?确认).但是我很乐意回顾一下我从头开始使用的一般概念.

我怀疑我做了一件非常错误的事情并且完全理解,但我不相信在Tomcat中没有办法实现多个身份验证方案.

有没有办法提供多种身份验证方案来从FormAuthetication中提取身份验证(对于轻量级客户端)?非常感谢您的帮助.提前致谢.

最佳答案 底线:您无法在Tomcat中为同一Web应用程序配置多个身份验证方案.

您配置一个将用于web.xml中的身份验证的auth方法:

<login-config>
    <auth-method>CLIENT-CERT</auth-method>
</login-config>

用于Web应用程序身份验证的身份验证器上的Tomcat映射.
例如,对于CLIENT-CERT,它将使用org.apache.catalina.authenticator.SSLAuthenticator
映射位于文件org / apache / catalina / startup / Authenticators.properties中

为了您在问题中描述的目的,您可以使用常规的Tomcat表单身份验证器(< auth-method> FORM< / auth-method>)

以下代码将对用户进行身份验证:

String url = "j_security_check?j_username=" + username + "&j_password=" + password;
String redirectUrl = response.encodeRedirectURL(url);
response.sendRedirect(redirectUrl);

首次访问应用程序时,通过上面的执行URL对用户进行身份验证.
此外,您可以使用表单身份验证器“旧”代码:)
请注意,上面的代码使用GET方法.
我建议在POST方法中将相同的参数提交给j_security_check(你可以在AJAX中完成).

点赞