我们找到了解决此问题的方法。
我们必须通过扩展现有的 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);