我们在Wildfly 8上运行了一个JQuery Web应用程序和一个基于JAX-RS的后端。
应用程序使用基本身份验证和自定义DatabaseServerLoginModule,后者又实现PBKDF2以进行密码散列。每个请求都以这种方式进行身份验证。
我们发现在某些浏览器上以及在某些情况下(还没有弄清楚哪些),Wildfly在验证失败时返回的401会触发浏览器的本机登录弹出窗口,而不是让我们的JQuery应用程序处理状态代码。毋庸置疑,这并不能带来非常好的用户体验。
我正在寻找一种避免这种行为的方法,似乎一般的解决方案似乎要么返回不同的状态代码,要么跳过www-authenticate标头。问题是我不能为我的生活弄清楚如何在Wildfly中定制这种行为,并且一般来说整个区域似乎都记录得很差。有谁知道这样做的简单方法?或者任何方式呢?你可以配置Wildfly或覆盖失败登录时返回401的类(哪一个?)?
我发现this forum post处理同样的问题,但是它使用了我无法启动和运行的PicketLink,无论哪种方式都不能让我成为一个“简单”的解决方案我将其定义为一个微不足道的问题。
非常感谢任何帮助。
答案 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。