使用Guice在RESTEasy中将主体注入资源方法

时间:2014-01-09 11:24:01

标签: java rest guice code-injection resteasy

我正在使用带有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")

我真的需要一些建议去实现这个目标?

1 个答案:

答案 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