我正在使用带有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")
.
我真的需要一些建议,以实现这一目标的方向?
我认为你最好的选择是在请求范围内使用中间值.假设您没有放入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.