繁体   English   中英

Tomcat:单个Web应用程序有多种身份验证方案吗?

[英]Tomcat: Multiple authentication schemes for a single web application?

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

但是FORM身份验证不适用于其他类型的客户端:例如Android客户端,各种第三方客户端等。太过了表单身份验证,它们都必须模拟我在此问题中寻找的行为: 如何模拟JMeter在Tomcat中进行表单身份验证? 在对Tomcat源代码进行了一些研究之后,我想到了应该可以扩展AuthenticatorBase类以实现自己的身份验证方式(例如FormAuthenticatorBasicAuthenticator.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规范,整个Web应用程序只允许一个login-config (嗯,我应该使用另一个Web应用程序来提供API吗?)
  • 我看到了一些提到通过Filter实现自定义身份验证的内容,但是,如果可能的话,我想将身份验证器模块放在一个单独的位置(就像已经存在并通过Tomcat确认一样) :Web应用程序中的自定义表单身份验证器,而不是作为独立的JAR模块。可能吗? )。 但是,我可以从头开始回顾一下我使用的一般概念。

我怀疑我做错了一件事情并且已经完全了解了,但是我不相信无法在Tomcat中实现多种身份验证方案。

有什么方法可以提供多种身份验证方案,以从FormAuthetication提取身份验证(对于轻量级客户端)? 非常感谢您的帮助。 提前致谢。

最重要的是:您不能为Tomcat中的同一Web应用程序配置多个身份验证方案。 您可以在web.xml配置一种用于身份验证的身份验证方法:

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

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

为此,您可以在问题中描述您可以使用常规的Tomcat Form Authenticator( <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对用户进行身份验证。 另外,您可以将Form Authenticator用于“旧”代码:)请注意,以上代码使用GET方法。 我建议在POST方法中向j_security_check提交相同的参数(可以在AJAX中完成)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM