在dropwizard auth
模块中,我想返回我的rest-api的来电者用户已锁定。
(凭据可能正确,但用户被锁定/禁用)
我看过这里:http://www.dropwizard.io/1.0.5/docs/manual/auth.html但找不到与之相关的任何内容。
authenticate
的{{1}}方法返回我的Authenticator
对象的可选项,文档说:
如果验证者,您应该只抛出AuthenticationException 无法检查凭据(例如,您的数据库已关闭)。
答案 0 :(得分:0)
所以,对于某些背景,你应该只抛出AuthenticationException
的原因是因为DW的好人提供的过滤器只处理这个异常。对于所有其他例外,这是未定义的。
有关详细信息,请参阅:AuthFilter#authenticate
然而,有一种非常简单的方法可以做你想做的事。
查看DW代码,您可以得到:
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final BasicCredentials credentials =
getCredentials(requestContext.getHeaders().getFirst(HttpHeaders.AUTHORIZATION));
if (!authenticate(requestContext, credentials, SecurityContext.BASIC_AUTH)) {
throw new WebApplicationException(unauthorizedHandler.buildResponse(prefix, realm));
}
}
此代码的作用是调用您的Authenticator
来解析用户,然后检查它是否经过身份验证。如果不是,那么它会调用UnauthorizedHandler
来检查它需要什么样的响应。遗憾的是,处理程序没有传入Principal,所以它只能返回一个静态异常。
现在,如果你想手工制作,这将是你的入口点。不是简单地使用他们提供的BasicCredentialAuthFilter
,而是编写自己的东西,为你做正确的事。
但是,从代码片段中,我们可以看到所有这些过滤器都会抛出WebApplicationException
。所以我们可以简化这个。
我们的Authenticator
实现可以事先进行用户锁定检查,并为我们填充异常以绕过此行为。这样,下游逻辑就会被保留(对WebapplicationException
做出反应,我认为它实际上是一个球衣feautere(参见:异常mapppers))。
所以,请考虑这个例子:
public class AuthenticatorTest extends io.dropwizard.Application<Configuration> {
@Override
public void run(Configuration configuration, Environment environment) throws Exception {
environment.jersey().register(new MyHelloResource());
UserAuth a = new UserAuth();
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<Principal>()
.setAuthenticator(a).setRealm("SUPER SECRET STUFF").buildAuthFilter()));
}
public static void main(String[] args) throws Exception {
new AuthenticatorTest().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
}
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public static class MyHelloResource {
@GET
@Path("asd")
@PermitAll
public String test(String x) {
return "Hello";
}
}
public static class UserAuth implements Authenticator<BasicCredentials, Principal> {
@Override
public Optional<Principal> authenticate(BasicCredentials credentials) throws AuthenticationException {
throw new WebApplicationException(Response.status(403).entity("User is blocked").build());
}
}
}
此代码只是创建一个新的异常,而不是验证用户名。这导致了这种卷曲:
artur@pandaadb:/$ curl "artur:artur@localhost:9085/api/test/asd"
User is blockedartur@pandaadb:/$ curl "artur:artur@localhost:9085/api/test/asd" -v
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
* Server auth using Basic with user 'artur'
> GET /api/test/asd HTTP/1.1
> Host: localhost:9085
> Authorization: Basic YXJ0dXI6YXJ0dXI=
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Date: Thu, 12 Jan 2017 14:19:27 GMT
< Content-Type: application/json
< Content-Length: 15
<
* Connection #0 to host localhost left intact
User is blocked
现在,这可能不是您可以做的最干净的解决方案。如果您需要快速,那么您可以将异常抛出Authenticator
。但是,正确的方法是:
io.dropwizard.auth.AuthFilter
AuthFilter
上的authenticate方法以检查您的用户并在那里抛出正确的异常。