【问题标题】:Return locked user in dropwizard auth在 dropwizard auth 中返回锁定的用户
【发布时间】:2017-01-11 07:26:17
【问题描述】:

dropwizard auth 模块中,我想向我的rest-api 的调用者返回用户被锁定

(凭据可能正确,但用户已被锁定/禁用)

我看过这里:http://www.dropwizard.io/1.0.5/docs/manual/auth.html,但找不到任何相关内容。

Authenticatorauthenticate 方法返回我的T 对象的Optional,并且文档说:

您应该只在身份验证器的情况下抛出 AuthenticationException 无法检查凭据(例如,您的数据库已关闭)。

【问题讨论】:

  • 您不能只创建一个标准非活动用户并返回该用户吗?或者,您可以按照文档和此处的说明创建一个基本角色系统:stackoverflow.com/questions/27392224/dropwizard-auth-by-example 并创建一个“禁用”角色,也不是?
  • 在我看来两者都是解决方法,感谢您的建议。这是否意味着 DW 没有为这个要求提供解决方案?在这两种情况下,用户在尝试访问资源时不会得到401,而是得到403。因为他将是一个没有权限的有效登录用户,而事实并非如此。他应该被视为仍然没有登录的用户,应该总是得到401 错误。
  • 我相信 DW 不希望您抛出任何其他异常,因为身份验证处理程序不处理该异常。您当然可以抛出自己的异常并拥有一个处理程序,该处理程序为您的特定用例返回正确的响应。他们想要避免的是身份验证在错误身份验证时返回 500 错误。或者,编写您自己的身份验证过滤器。
  • @pandaadb 我不想在这里抛出异常,我只需要告诉客户端用户被锁定。顺便说一句,您能否提供有关如何自定义身份验证处理程序的链接?
  • 如果你抛出一个自定义异常并使用异常映射器处理异常,那么你可以抛出 ClientUserLockedException() 处理程序可以将其转换为 4XX 响应代码(无论你想要哪个)

标签: dropwizard


【解决方案1】:

所以,在某些背景下,你应该只抛出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,不如编写自己的代码来为您做正确的事情。

但是,从代码 sn-p 中,我们可以看到这个过滤器所做的只是抛出一个WebApplicationException。所以我们可以缩短这个。

我们的Authenticator 实现可以预先进行用户锁定检查并填充异常让我们绕过此行为。这样,保留了下游逻辑(对WebapplicationException 做出反应,我认为这实际上是一个球衣 feautere(请参阅:异常映射器))。

所以,考虑这个例子:

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 中抛出。但是,正确的做法是:

  1. 基于 io.dropwizard.auth.AuthFilter 实现一个新的 AuthFilter
  2. 覆盖AuthFilter 上的身份验证方法以检查您的用户并在那里抛出正确的异常。

【讨论】:

  • 感谢您的宝贵回答,您认为在这种情况下我们应该返回 401 吗?
  • 这取决于你想做什么。 401 - 未授权,如果“锁定用户”表示未授权,那么这里的 401 可能是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-12
  • 2020-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多