我正在使用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版
感谢您的帮助。
答案 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有两种方法:test
和test2
。 test
应用@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。