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

Sti*_*ine 6 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

hello资源调用应该被一些使用Authorization HTTP请求头中传递的凭据执行基本身份验证的代码拦截,并且成功将主体注入方法主体参数.我还希望能够将允许的角色列表传递给注释,例如@Auth("admin").

我真的需要一些建议,以实现这一目标的方向?

Vla*_*eev 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

即使你因为某种原因确实把资源(甚至是过滤器)放在单例范围内,你总是可以注入Provider<AuthInfo>而不是AuthInfo.

更新

似乎我有点错误,因为默认情况下过滤器不在单例范围内.事实上它似乎表现得像单身,即使它不受此限制.它是在JAX-RS容器启动时创建的.因此,您需要注入Provider<AuthInfo>过滤器.实际上,如果AuthInfo在绑定到请求范围时直接注入过滤器,容器启动将失败.虽然资源(如果没有明确地绑定为单例)可以直接注入.

我已将工作程序上传到github.