避免使用Wildfly服务器和基本身份验证进行401弹出

时间:2015-05-10 09:03:20

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

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

应用程序使用基本身份验证和自定义DatabaseServerLoginModule,后者又实现PBKDF2以进行密码散列。每个请求都以这种方式进行身份验证。

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

我正在寻找一种避免这种行为的方法,似乎一般的解决方案似乎要么返回不同的状态代码,要么跳过www-authenticate标头。问题是我不能为我的生活弄清楚如何在Wildfly中定制这种行为,并且一般来说整个区域似乎都记录得很差。有谁知道这样做的简单方法?或者任何方式呢?你可以配置Wildfly或覆盖失败登录时返回401的类(哪一个?)?

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

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

我们找到了解决这个问题的方法。 我们必须通过扩展现有的BASIC身份验证机制来创建我们自己的身份验证机制(我们将其命名为#34; 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);
        }
    }
}

然后你需要&#34;注册&#34;通过实施 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); 

答案 1 :(得分:0)

如果您使用:

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

然后wildfly永远不会发送www-authenticate标头,你应该得到403而不是401.

这也可以与表单auth:

结合使用
<auth-method>BASIC?silent=true,FORM</auth-method>

然后您可以将FORM登录页面映射到返回所需内容的Servlet。