我正在使用带有Guice的RESTEasy开发REST API,目前我正在尝试使用类似于Dropwizard中的@Auth的注释来合并基本身份验证。与
@Path("hello")
public class HelloResource {
@GET
@Produces("application/json")
public String hello(@Auth final Principal principal) {
return principal.getUsername();
}
}
hello资源调用应该被一些代码拦截,这些代码使用Authorization HTTP请求头中传递的凭据执行基本身份验证,并且成功将主体注入方法主体参数。我还希望能够将允许的角色列表传递给注释,例如@Auth("admin")
。
我真的需要一些建议去实现这个目标?
答案 0 :(得分:7)
我认为您最好的选择是在请求范围内使用中间值。假设您没有将HelloResource
放在单例作用域中,可以在某个ContainerRequestFilter
实现和资源中注入此中间值,并且可以在此ContainerRequestFilter
实现中填充所有值您需要的身份验证和授权信息。
看起来像这样:
// Authentication filter contains code which performs authentication
// and possibly authorization based on the request
@Provider
public class AuthFilter implements ContainerRequestFilter {
private final AuthInfo authInfo;
@Inject
AuthFilter(AuthInfo authInfo) {
this.authInfo = authInfo;
}
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// You can check request contents here and even abort the request completely
// Fill authInfo with the data you need
Principal principal = ...; // Ask some other service possibly
authInfo.setPrincipal(principal);
}
}
@Path("hello")
public class HelloResource {
private final AuthInfo authInfo;
@Inject
HelloResource(AuthInfo authInfo) {
this.authInfo = authInfo;
}
@GET
@Produces("application/json")
public String hello() {
// authInfo here will be pre-filled with the principal, assuming
// you didn't abort the request in the filter
return authInfo.getPrincipal().getUsername();
}
}
public class MainModule extends AbstractModule {
@Override
protected void configure() {
bind(AuthFilter.class);
bind(HelloResource.class);
bind(AuthInfo.class).in(RequestScoped.class);
}
}
即使您因某种原因确实将资源(甚至是过滤器)放在单一作用域中,您也可以始终注入Provider<AuthInfo>
而不是AuthInfo
。
<强>更新强>
似乎我有点错误,因为默认情况下过滤器不在单例范围内。事实上它似乎表现得像单身,即使它不受此限制。它是在JAX-RS容器启动时创建的。因此,您需要将Provider<AuthInfo>
注入过滤器。实际上,如果AuthInfo
在绑定到请求范围时直接注入过滤器,则容器启动将失败。资源(如果没有明确地绑定为单例)可以直接注入。
我已将工作程序上传至github。