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

时间:2016-11-01 05:11:44

标签: authentication dropwizard

我正在使用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版

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

从源 - 动态功能将在@PermitAll上进行 ENABLE 身份验证,而不是禁用它。

从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);

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

见这个例子:

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有两种方法: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。

答案 1 :(得分:-1)

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

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

修改:查看an example application