启用身份验证后我的所有资源都需要身份验证

All my resources require authentication after enabling authentication

我正在使用 dropwizard 开发一个应用程序,我正在尝试设置一个简单的用例,用户需要在某些资源 (URL) 上进行身份验证,而不是在其他资源上进行身份验证。

阅读所有教程后,我遇到了一个问题,我的所有资源都被强制进行身份验证...这不是我想要的。

以下是我启动应用程序的操作:

    environment.jersey().register(new AuthDynamicFeature(
            new BasicCredentialAuthFilter.Builder<User>()
            .setAuthenticator(new TestAuthenticators())
            .setAuthorizer(new TestAuthorizer())
            .setRealm("SUPER SECRET STUFF")
            .buildAuthFilter()
    ));
    environment.jersey().register(RolesAllowedDynamicFeature.class);

    environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));

    environment.jersey().register(new LoginResource());

我的 TestAuthenticator 看起来像:

public class TestAuthenticators implements Authenticator<BasicCredentials, User> {

private static final Logger logger = LoggerFactory.getLogger(TestAuthenticators.class);

@Override
public Optional<User> authenticate(BasicCredentials basicCredentials) throws AuthenticationException {

    logger.error("Authenticator {}", basicCredentials.getUsername());

    if ("secret".equals(basicCredentials.getPassword())) {
        return Optional.of(new User(basicCredentials.getUsername(), basicCredentials.getPassword()));
    }
    return Optional.empty();
}

}

我的 TestAuthorizer 看起来像:

public class TestAuthorizer implements Authorizer<User> {

@Override
public boolean authorize(User user, String s) {
    return true;
}

}

我的 LoginResource 看起来像:

@Path("/login")
public class LoginResource {

private static final Logger logger = LoggerFactory.getLogger(LoginResource.class);

@POST
@Produces(MediaType.APPLICATION_JSON)
public Response login(@Auth User principal, @Context HttpServletRequest request) {
    return Response.ok()
            .cookie(new NewCookie("test_cookie", request.getSession().getId(), "/", null, null, 5, false))
            .build();
}
}

其他资源只是普通资源,我试了@PermitAll方法没用,我试了Class级别也没有。

我正在使用 Dropwizard 版本 1.0.3

感谢您的帮助。

来自源 - 动态功能将启用 @PermitAll 上的身份验证,而不是禁用它。

从 AuthDynamicFeature 看到这个:

final boolean annotationOnClass = (resourceInfo.getResourceClass().getAnnotation(RolesAllowed.class) != null) ||
            (resourceInfo.getResourceClass().getAnnotation(PermitAll.class) != null);
        final boolean annotationOnMethod = am.isAnnotationPresent(RolesAllowed.class) || am.isAnnotationPresent(DenyAll.class) ||
            am.isAnnotationPresent(PermitAll.class);

        if (annotationOnClass || annotationOnMethod) {
            context.register(authFilter);

因此,为了不对特定资源进行授权,您永远不能将其应用于 class 级别(因为它将应用于您所有的资源方法)。

看这个例子:

public class AuthenticatorTest extends io.dropwizard.Application<DBConfiguration> {
    @Override
    public void run(DBConfiguration 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
        @UnitOfWork
        public String test(String x) {
            return "Hello";
        }


        @GET
        @Path("asd2")
        public String test2() {
            return "test2";
        }

    }

    public static class Person implements Principal {
        @Override
        public String getName() {
            return null;
        }

    }

    public static class UserAuth implements Authenticator<BasicCredentials, Principal> {
        @Override
        public Optional<Principal> authenticate(BasicCredentials credentials) throws AuthenticationException {
            return Optional.of(new Principal() {
                @Override
                public String getName() {
                    return "artur";
                }

            });
        }
    }

}

MyHelloResource 有 2 个方法:testtest2test 应用 @PermitAll 来启用身份验证,而 test2 则不会那样做。

这意味着auth没有注册到test2。

这是执行:

artur@pandaadb:~/dev/eclipse/eclipse_jee$ curl localhost:9085/api/test/asd -v
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /api/test/asd HTTP/1.1
> Host: localhost:9085
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 401 Unauthorized
< Date: Tue, 01 Nov 2016 10:30:10 GMT
< WWW-Authenticate: Basic realm="SUPER SECRET STUFF"
< Content-Type: text/plain
< Content-Length: 49
< 
* Connection #0 to host localhost left intact
Credentials are required to access this resource.artur@pandaadb:~/dev/eclipse/eclipse_jee$ 
artur@pandaadb:~/dev/eclipse/eclipse_jee$ curl localhost:9085/api/test/asd2 -v
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /api/test/asd2 HTTP/1.1
> Host: localhost:9085
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 01 Nov 2016 10:30:14 GMT
< Content-Type: application/json
< Vary: Accept-Encoding
< Content-Length: 5
< 
* Connection #0 to host localhost left intact
test2

第一种方法使用 401 拒绝访问,而第二种方法正确打印 test2。

Dropwizard 提示 API 用户为那些包含 @Auth 用户主体 参数的方法提供凭据。如果删除参数和注释,该方法将不受密码保护。

@PermitAll 和@RolesAllowed 等注释与授权有关,与身份验证无关。

编辑: 看看an example application.