Jersey 和 HK2 - 注入当前用户

2023-12-04

我正在使用 jersey 2.17 和 HK2 创建一个简单的休息应用程序。 我有一个ContainerRequestFilter拒绝任何没有“currentuser”cookie 的请求。

我有这样的事情:

@Path("/users")
public class UserResource { 

      private UserService userService; 

      @GET
      @Path("/orders")
      @Produces("application/json")
      public List<Order> findOrdersOfCurrentUser() { 
            // some ugly code to access headers, extract cookies, and finally
            // extract username (a String) from a particular cookie

            return this.userService.findOrdersByUsername(username) ; 
      }
}

我想编写一些比这更优雅的代码。 像这样:

 @Path("/users")
 public class UserResource { 

          private UserService userService; 

          @CurrentUsername
          private String currentUser; 

          @GET
          @Path("/orders")
          @Produces("application/json")
          public List<Order> findOrdersOfCurrentUser() { 
                return this.userService.findOrdersByUsername(username) ; 
          }
    }

我对 hk2 真的很陌生,并且很难找到实现它的方法。

我只是要求实现正确的接口(或扩展类)。


您正在寻找的东西并非易事。处理这个问题的一种方法是设置SecurityContext在 - 的里面ContainerRequestFilter, as 在这里看到。这不涉及与 HK2 的任何直接交互。然后你可以注入SecurityContext在您的资源类中。并通过以下方式获取用户

securityContext.getUserPrincipal().getName();

如果您确实想使用自定义注释注入用户名,则需要创建一个InjectionResolver (请参阅定义自定义注入注释。你可以注射ContainerRequestContext(与传递给过滤器方法的相同ContainerRequestFilter) 或者SecurityContext进入InjectionResolver。例如

Filter

@Provider
@PreMatching
public class UserFilter implements ContainerRequestFilter {

    public static final String USER_PROP = "user";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestContext.setProperty(USER_PROP, new User("peeskillet"));
    }
}

注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CurrentUser {   
}

注入解析器

public class CurrentUserInjectionResolver implements InjectionResolver<CurrentUser> {

    javax.inject.Provider<ContainerRequestContext> requestContext;

    @Inject
    public CurrentUserInjectionResolver(
        javax.inject.Provider<ContainerRequestContext> requestContext) {
        this.requestContext = requestContext;
    }

    @Override
    public Object resolve(Injectee injectee, ServiceHandle<?> sh) {
        if (User.class == injectee.getRequiredType()) {
            return requestContext.get().getProperty(UserFilter.USER_PROP);
        }
        return null;
    }

    @Override
    public boolean isConstructorParameterIndicator() { return false; }

    @Override
    public boolean isMethodParameterIndicator() { return false; }
}

绑定 InjectionResolver

@Provider
public class UserFeature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        context.register(new AbstractBinder(){
            @Override
            public void configure() {

                bind(CurrentUserInjectionResolver.class)
                .to(new TypeLiteral<InjectionResolver<CurrentUser>>(){})
                        .in(Singleton.class);
            }
        });
        return true;          
    } 
}

Resource

@Path("user")
public class UserResource {

    @CurrentUser 
    private User user;

    @GET
    public Response getCurrentUser() {
        return Response.ok(user.getUsername()).build();
    }
}

现在我不太确定第二种方法,至少关于过滤器的部分是@PreMatching筛选。如果我不进行预匹配,User将为空。看来ContainerRequestContext还没有我们设置的属性,这意味着正在发生的事情是InjectResolver在过滤器之前被调用。我需要调查一下。使其成为预匹配,IMO 不应该是必需的。

但就我个人而言,我会采用第一种方法,只需使用SecurityContext。完整的示例位于我上面提供的链接中。通过这种方法,您可以利用泽西岛的RolesAllowedDynamicFeature如果需要的话。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jersey 和 HK2 - 注入当前用户 的相关文章

随机推荐

  • 如何优雅地终止一个进程?

    我想终止多个进程 但我想让每个进程都有机会保存其数据 询问用户有关保存文件的信息 甚至忽略关闭请求 So TerminateProcess这是不可能的 因为它会立即终止进程 另一种方法是使用SendMessage PostMessage发送
  • case 类私有构造函数 - 需要 readResolve 实现

    我只是在谷歌上搜索如何使用私有构造函数创建案例类 以下是执行此操作的正确方法 如中所述 如何在案例类同伴中覆盖 apply object A def apply s String i Int A new A s toUpperCase i
  • 创建列表视图并从 flutter 上的 firestore 获取数据

    我有一个应用程序 我需要将这些数据从 firestore 数据库一一获取到 flutter 上的 Listview 我尝试了很多东西 例如流构建器和未来构建器 但我无法得到 因为我的数据库使用嵌套数据如果您有任何建议 请告诉我 非常感谢 有
  • 需要 preg_match_all 链接

    我有一个像这样的字符串 string some text http dvz local index index regionId 28 http stuff kiev ua roadmap page php http 192 168 3 1
  • 如何使用查询生成器在 Symfony 4 中连接外部 ID 上的多个实体?

    我正在努力学习 Symfony 今天我正在关注关联教程 我决定制作一个小应用程序 包括房屋 厨房 卧室和橱柜 我 尝试 使用draw io制作一个小的类图 以便为您提供更好的想法 所以基本上一栋房子可以有多个卧室和多个厨房 每个厨房可以有多
  • Javascript - 为什么从函数返回 array.push(x) 不会将元素 x 推入数组?

    我想知道为什么以下功能有效 function foo list var array array push list return array gt foo 1 2 3 1 2 3 而这个则没有 function foo list var a
  • Python 和 .Net 集成选项

    我想将 Python 与 C 集成 我发现两种方法使用进程间通信和 IronPython 进程间通信需要在所有客户端计算机上安装 Python exe 因此这不是一个可行的解决方案 我们开始使用 IronPython 但它目前仅支持 2 7
  • PHP 类 - 如何仅连接一次数据库

    我尝试做一个简单的 SQL 类 只有一个问题 function classDBREAD table where value back link mysql connect 127 0 0 1 XXXX XXXXXX mysql select
  • 如何忽略 LNK2005 和 LNK1169?

    因此 我有一个使用外部库的 Visual Studio 2010 项目 为了在没有 LNK2005 的情况下编译它 我必须在链接器设置中调整库的顺序 我让它在发布模式下编译得很好 但出于某种原因 我无法在调试中没有 LNK 错误的情况下编译
  • 如何在单击按钮时从数据库将新行添加到 jTable 中而不清除现有行

    如何在单击按钮时从数据库将新行添加到 jTable 中而不清除 jTable 中的现有行 我尝试了很多方法 但没有成功 帮助 String SQL SELECT name price FROM items WHERE ID jTextFie
  • Paypal使用phpcurl通过支付密钥获取交易详细信息

    android paypal 付款成功后我得到回复 回应如下 response state approved id PAY 6PU626847B294842SKPEWXHY create time 2014 07 18T18 46 55Z
  • 如何在我的 Activity 中重新启动 Fragment - Android

    我有一个活动 里面有 3 个片段 我需要通过单击按钮重新启动活动中的第一个片段 ViewPagerAdapter adapter new ViewPagerAdapter getSupportFragmentManager adapter
  • 自 iOS 8 起,SignificantLocationChanges 不再起作用

    我有一个问题SignificantLocationChanges自iOS 8发布以来 该方法 locationManager startMonitoringSignificantLocationChanges 在检查可用性后被正确调用 代表
  • 读取由 NewCookie() 创建的 cookie

    I created a cookie using Newcookie and I can access it thorough the browser as below Now I need to read the cookie funct
  • 带有圆角的 UIButton 的活动可点击区域?

    So I have created a button with a border in my storyboard 然后我把它的角弄圆并添加了边框颜色 button layer cornerRadius button bounds size
  • Unified_thread 还没有对外开放?

    据 Facebook 称 他们很久以前就发布了新的消息系统 http developers facebook com blog post 591 来自博客 应用程序应迁移到新的消息传递图形 API 端点和消息传递 FQL 表 unified
  • 为什么 eval('{a:23}') 给我的是 23 而不是 {a:23}?

    我在浏览器中有这段 JavaScript 代码 console log eval a 23 它打印 23 我原本期待看到 Object 有人可以解释一下吗 thanks 在这种背景下 开始一个block 不是对象字面量 a 那么是一个lab
  • .* 匹配 2 次

    我尝试过了match 用C 正则表达式 结果发现它匹配任何字符串两次 first the 完整的字符串 比第二次空字符串 我期望 在一场比赛中匹配所有内容 我完全困惑为什么会这样以及如何防止这种情况 长话短说 我需要替换部分文件名 并且可以
  • 如何在 C++ 中创建文件映射?

    我正在编写一个游戏预加载器 一个简单的程序 在启动程序之前将某些文件 映射 加载到缓存中 我被告知要使用CreateFileMapping 但我仍然不确定它将它加载到物理内存还是虚拟内存中 不管怎样 我应该把需要加载的文件放在哪里 这是我的
  • Jersey 和 HK2 - 注入当前用户

    我正在使用 jersey 2 17 和 HK2 创建一个简单的休息应用程序 我有一个ContainerRequestFilter拒绝任何没有 currentuser cookie 的请求 我有这样的事情 Path users public