在 Dropwizard 0.8.4 中,如何使用 rolesAllowed 注解?

In Dropwizard 0.8.4, how do you make use of the rolesAllowed annotation?

在新的 dropwizard 版本中,您可以创建一个基本的身份验证过滤器,它接受授权者和身份验证者。然后可以使用 @RolesAllowed 标记对每个资源进行注释。

在 0.8.4 中,您无法以相同的方式创建授权方 - 但 RolesAllowed 标签仍​​然存在。您如何使用 rolesAllowed 标签来获得与更高版本相同的行为?

在 Dropwizard 0.8.x 中,由于身份验证的方式,无法使用 @RolesAllowed;它与 Jersey 如何使用 SecurityContext 无关。从 0.9.0 开始,Dropwizard 开始使用 SecurityContext,这是 Jersey 用来使 @RolesAllowed 注释起作用的。

幸运的是,您只需将 dropwizard-auth 依赖项升级到 0.9.0,它仍然可以与 Dropwizard 0.8.4 一起使用。我实际上刚刚测试过这个并且它工作正常。您只需要从中排除 dropwizard-core

<dependencies>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-core</artifactId>
        <version>0.8.4</version>
    </dependency>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-auth</artifactId>
        <version>0.9.0</version>
        <exclusions>
            <exclusion>
                <groupId>io.dropwizard</groupId>
                <artifactId>dropwizard-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

这样做之后,应该一切正常。我将 post 我用来测试它的所有 类。

ExamplePrincipal

public class ExamplePrincipal implements Principal {
    private String name;
    private List<String> roles;

    public ExamplePrincipal(String name, List<String> roles) {
        this.name = name;
        this.roles = roles;
    }
    public String getName() {
        return this.name;
    }
    public List<String> getRoles() {
        return this.roles;
    }
}

ExampleAuthenticator

public class ExampleAuthenticator implements Authenticator<BasicCredentials, ExamplePrincipal> {

    @Override
    public Optional<ExamplePrincipal> authenticate(BasicCredentials credentials) throws AuthenticationException {
        if ("peeskillet".equals(credentials.getUsername())
                && "secret".equals(credentials.getPassword())) {
            return Optional.of(new ExamplePrincipal(credentials.getUsername(), Arrays.asList("ADMIN")));
        }
        return Optional.absent();
    }
}

ExampleAuthorizer

public class ExampleAuthorizer implements Authorizer<ExamplePrincipal> {

    @Override
    public boolean authorize(ExamplePrincipal principal, String role) {
        return principal.getRoles().contains(role);
    }
}

ExampleResource

@Path("example")
public class ExampleResource {

    private String name;

    public ExampleResource(String name) {
        this.name = name;
    }

    @GET
    @RolesAllowed("ADMIN")
    public String get() {
        return "Hello " + name + "!";
    }

    @GET
    @Path("root")
    @RolesAllowed("ROOT")
    public String getRoot() {
        return "Root Access";
    }
}

ExampleConfiguration

public class ExampleConfiguration extends Configuration {

    private String name;

    @JsonProperty
    public String getName() {
        return this.name;
    }

    @JsonProperty
    public void setName(String name) {
        this.name = name;
    }
}

ExampleApplication

public class ExampleApplication extends Application<ExampleConfiguration> {

    public static void main(String...args) throws Exception {
        new ExampleApplication().run(args);
    }


    public void run(ExampleConfiguration config, Environment env) throws Exception {
        env.jersey().property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
        env.jersey().register(new ExampleResource(config.getName()));

        env.jersey().register(RolesAllowedDynamicFeature.class);
        env.jersey().register(new AuthDynamicFeature(
                new BasicCredentialAuthFilter.Builder<ExamplePrincipal>()
                        .setAuthenticator(new ExampleAuthenticator())
                        .setAuthorizer(new ExampleAuthorizer())
                        .setRealm("ExampleRealm")
                        .buildAuthFilter()
        ));
        env.jersey().register(new AuthValueFactoryProvider.Binder<ExamplePrincipal>(ExamplePrincipal.class));
    }
}

example.yml

name: "Peeskillet"

要测试应用程序,您只需 运行 以下 cURL 命令

curl -i -u peeskillet:secret http://locahost:8080/example

如果您转到需要 ROOT 用户的 example/root 端点,您将看到 403 禁止响应

url -i -u peeskillet:secret http://locahost:8080/example/root