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

 AAAAaaaa叶子 发布于 2023-02-04 20:19

我正在使用带有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 个回答
  • 我认为你最好的选择是在请求范围内使用中间值.假设您没有放入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.

    2023-02-04 20:24 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有