【问题标题】:Avoid 401 popup with Wildfly server and Basic Authentication使用 Wildfly 服务器和基本身份验证避免 401 弹出窗口
【发布时间】:2015-07-20 21:20:56
【问题描述】:

我们有一个 JQuery Web 应用程序和一个在 Wildfly 8 上运行的基于 JAX-RS 的后端。

应用程序使用带有自定义 DatabaseServerLoginModule 的基本身份验证,该模块反过来实现 PBKDF2 进行密码散列。每个请求都以这种方式进行身份验证。

我们发现在某些浏览器和某些情况下(还没有完全弄清楚是哪个),Wildfly 在身份验证失败时返回的 401 会触发浏览器的本机登录弹出窗口显示,而不是让我们的 JQuery 应用程序处理状态码。不用说,这并不能带来非常好的用户体验。

我正在寻找一种方法来避免这种行为,似乎一般的解决方案似乎是要么返回不同的状态代码,要么跳过 www-authenticate 标头。问题是我一生都无法弄清楚如何在 Wildfly 中自定义这种行为,而且总的来说,整个区域的文档似乎都很少。有谁知道一个简单的方法吗?或者有什么办法吗?您能否配置 Wildfly 或覆盖登录失败时返回 401 的类(哪个?)?

我发现this forum post 处理了同样的问题,但它使用了我无法启动和运行的 PicketLink,而且无论哪种方式,它都不完全是一个“简单”的解决方案。我会定义为一个微不足道的问题。

任何帮助将不胜感激。

【问题讨论】:

    标签: jakarta-ee authentication basic-authentication wildfly http-status-code-401


    【解决方案1】:

    我们找到了解决此问题的方法。 我们必须通过扩展现有的 BASIC 身份验证机制来创建自己的身份验证机制(我们将其命名为“CUSTOM-BASIC”)。

    这样做:

    扩展类 io.undertow.security.impl.BasicAuthenticationMechanism 并重写 sendChallenge 方法,如下所示:

    public class CustomBasicAuthenticationMecanism extends BasicAuthenticationMechanism {
    
        public CustomBasicAuthenticationMecanism(final String realmName, final String mechanismName, final boolean silent, final IdentityManager identityManager) {
           super(realmName, mechanismName, silent, identityManager);
        }
    
        @Override
        public ChallengeResult sendChallenge(HttpServerExchange exchange, SecurityContext securityContext) {
            //Commented to remove the www-authenticate header which makes the login popup show up in the browser
            //exchange.getResponseHeaders().add(WWW_AUTHENTICATE, challenge); 
            return new ChallengeResult(true, StatusCodes.UNAUTHORIZED);
        }
    
        public static class Factory implements AuthenticationMechanismFactory {
    
            private final IdentityManager identityManager;
    
            public Factory(IdentityManager identityManager) {
                this.identityManager = identityManager;
            }
    
            @Override
            public AuthenticationMechanism create(String mechanismName, FormParserFactory formParserFactory, Map<String, String> properties) {
                String realm = properties.get(REALM);
                return new CustomBasicAuthenticationMecanism(realm, mechanismName, false, identityManager);
            }
        }
    }
    

    然后您需要通过实现 io.undertow.servlet.ServletExtension 来“注册”您的自定义身份验证机制:

    public class CustomBasicAuthenticationServletExtension implements ServletExtension {
        @Override
        public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
            deploymentInfo.addAuthenticationMechanism("CUSTOM-BASIC", new CustomBasicAuthenticationMecanism.Factory(deploymentInfo.getIdentityManager()));
        }
    }
    

    并在 META-INF/services 中创建一个名为 io.undertow.servlet.ServletExtension 的文件。 该文件应包含 ServletExtension 的完全限定名称。 例如:

    com.company.authentication.CustomBasicAuthenticationServletExtension
    

    然后在您的 web.xml 中,您可以将 BASIC 替换为您的自定义身份验证机制名称(此处为 CUSTOM-BASIC):

    <login-config>
        <auth-method>CUSTOM-BASIC</auth-method>
        ...
    </login-config>
    

    这样做您仍会收到 401 响应,但没有 WWW-Authenticate 标头。

    如果出于任何原因您需要另一个响应代码(比如 403),只需更改此行:

    return new ChallengeResult(true, StatusCodes.FORBIDDEN); 
    

    【讨论】:

    • 如果您想以编程方式控制 http 处理程序链,这是一个很好的解决方案。我希望我有更多的赞成票
    【解决方案2】:

    如果你使用:

    <auth-method>BASIC?silent=true</auth-method>
    

    那么 wildfly 将永远不会发送 www-authenticate 标头,您应该得到 403 而不是 401。

    这也可以与表单身份验证结合使用:

    <auth-method>BASIC?silent=true,FORM</auth-method>
    

    然后您可以将 FORM 登录页面映射到返回您想要的任何内容的 Servlet。

    【讨论】:

    • 我已经对 web.xml 进行了更改,它部署得很好,但我似乎仍然得到 401。它需要最新版本的 Wildfly 还是我遗漏了什么?
    • Wildfly 9.0.2.Final:将静默设置为 true 不会阻止响应中包含 www-authenticate 标头,并且仍会返回 401
    • 我得到了 401,但它按照 Jboss 7 的要求保持沉默(我认为是 Wildfly 10)!绝对比编程简单
    • 来自 Wilfly 文档:“仅当请求包含授权标头时,静默模式下的基本身份验证才会发送质询以进行身份​​验证,否则假定另一种方法将发送质询。” => 这意味着即使在静默模式下,Wildfly 仍然会发送 www-authenticate 标头...(请参阅:docs.wildfly.org/18/WildFly_Elytron_Security.html
    猜你喜欢
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 2011-08-07
    相关资源
    最近更新 更多