启用身份验证后我的所有资源都需要身份验证
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 个方法: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。
Dropwizard 提示 API 用户为那些包含 @Auth 用户主体 参数的方法提供凭据。如果删除参数和注释,该方法将不受密码保护。
@PermitAll 和@RolesAllowed 等注释与授权有关,与身份验证无关。
编辑: 看看an example application.
我正在使用 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 个方法: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。
Dropwizard 提示 API 用户为那些包含 @Auth 用户主体 参数的方法提供凭据。如果删除参数和注释,该方法将不受密码保护。
@PermitAll 和@RolesAllowed 等注释与授权有关,与身份验证无关。
编辑: 看看an example application.