【问题标题】:Context injected SecurityContext is null上下文注入 SecurityContext 为空
【发布时间】:2015-08-16 10:43:52
【问题描述】:

我使用 JAX-RS 2.0 和 JPA 创建了一个 Javae EE 应用程序。我为我的用户实体(使用限定符)创建了一个特殊的提供者,以将当前用户(登录)作为应用程序用户数据库中的实体提供。 要获取当前用户,我使用

@Context
private SecurityContext secContext;

问题是这是空的。安全设置很好(Wildfly 8.2) - 应用程序要求身份验证(基本)但SecurityContext 为空。代码如下:

@RequestScoped
public class CurrentUserProducer implements Serializable {

    /**
     * Default
     */
    private static final long serialVersionUID = 1L;

    @Context
    private SecurityContext secContext;

    /**
     * Tries to find logged in user in user db (by name) and returns it. If not
     * found a new user with role {@link UserRole#USER} is created.
     * 
     * @return found user a new user with role user
     */
    @Produces
    @CurrentUser
    public User getCurrentUser() {
        if (secContext == null) {
            throw new IllegalStateException("Can't inject security context - security context is null.");
        //... code to retrieve or create new user
        return user;
    }

}

如您所见,我检查 secContext 是否为空,一旦我尝试访问注入 @CurrentUser 的资源,我就会看到我的异常。

那么如何解决这个问题?为什么SecurityContext 为空。

【问题讨论】:

    标签: java dependency-injection jax-rs resteasy security-context


    【解决方案1】:

    正如我在评论中所说的

    SecurityContext 是一个 JAX-RS 组件,只能注入到其他 JAX-RS 组件中。你所拥有的只是一个 CDI bean。您可以尝试将其设为 EJB 并注入 SessionContext。请参阅保护Enterprise Bean Programmatically

    尚未测试,但似乎适用于 OP。这是一个 EE 堆栈解决方案。

    另一种 JAX-RS(Resteasy 特定)允许注入的方法是借助 ResteasyProviderFactory(在 this answer 的帮助下找到)。您可以在ContainerRequestFilter 中使用它,它可以访问SecurityContext。我们可以使用 RESTeasy 实用程序类将User 推送到上下文中。这允许使用 @Context 注释进行注入。不确定如何/是否可以使用自定义注释。这是一个例子

    @Provider
    public class UserContextFilter implements ContainerRequestFilter {
    
        @Override
        public void filter(ContainerRequestContext context) throws IOException {
            SecurityContext securityContext = context.getSecurityContext();
            String username = securityContext.getUserPrincipal().getName();
    
            ResteasyProviderFactory.pushContext(User.class, new User(username));
        }  
    }
    

    注意:这是一个 JAX-RS 2.0 解决方案(即 RESTeasy 3.x.x)。 2.0之前没有ContainerRequestFilter

    【讨论】:

    • 我正在尝试严格依赖 Java EE 标准。但正如我在实施“ContextResolver”时所说,它工作正常。
    【解决方案2】:

    我找到了另一种让 Jax-Rs 识别类的方法:实现 ContextResolver 并使用提供者注释类。

    实现我添加的接口:

    @Override
    public User getContext(Class<?> type) {
        if (type.equals(User.class)){
            return getCurrentUser();
        }
        return null;
    }
    

    我不确定,但也许我可以做到

    @上下文 私人用户 currentUser;

    但我没有尝试。但是通过限定符的注入现在正在工作(注入安全上下文)。

    【讨论】:

    • 有趣的解决方案。我从来没有想过这样做。您是否尝试过这种User 的注入来查看它是否有效?
    • 不,我还没有尝试过 - 我将不得不重构 seome 代码(包括测试)。但至少所有 Context 的东西都会被注入到一个带有 @Provider 注释的类中(需要实现一些 jax-rs 接口)
    猜你喜欢
    • 1970-01-01
    • 2013-12-17
    • 2023-03-30
    • 2016-04-21
    • 2021-10-09
    • 2013-09-17
    • 1970-01-01
    • 2020-07-19
    • 2010-12-31
    相关资源
    最近更新 更多