如何在 Quarkus 应用程序中检索 SecurityContext?

问题描述 投票:0回答:3

我有一个 Quarkus 应用程序,在其中实现了

ContainerRequestFilter
接口来保存传入请求的标头:

@PreMatching
public class SecurityFilter implements ContainerRequestFilter {
   private static final String HEADER_EMAIL = "HD-Email";

   @Override
   public void filter(ContainerRequestContext requestContext) throws IOException {
       String email = requestContext.getHeaders().getFirst(HEADER_EMAIL);

       if (email == null) {
           throw new AuthenticationFailedException("Email header is required");
       }

       requestContext.setSecurityContext(new SecurityContext() {
           @Override
           public Principal getUserPrincipal() {
               return () -> email;
           }

           @Override
           public boolean isUserInRole(String role) {
               return false;
           }

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

           @Override
           public String getAuthenticationScheme() {
               return null;
           }
       });
   }
}

在用

ApplicationScoped
注释的类中,我注入了上下文,如下所示:

@ApplicationScoped
public class ProjectService {
    @Context
    SecurityContext context;
    ...
}

问题是

context
属性实际上从未被注入,因为它总是
null

我做错了什么?我应该怎么做才能在整个应用程序代码中检索

SecurityContext

java security jax-rs quarkus
3个回答
15
投票

我喜欢抽象这个问题,以便业务逻辑不依赖于 JAX-RS 特定的构造。因此,我创建一个类来描述我的用户,例如

User
,以及另一个接口
AuthenticationContext
,它保存当前用户和我需要的任何其他与身份验证相关的信息,例如:

public interface AuthenticationContext {
    User getCurrentUser();
}

我创建了这个类的

RequestScoped
实现,它也有相关的设置器:

@RequestScoped
public class AuthenticationContextImpl implements AuthenticationContext {
    private User user;

    @Override
    public User getCurrentUser() {
        return user;
    }

    public void setCurrentUser(User user) {
        this.user = user;
    }
}

现在,我将这个 bean 和 JAX-RS

SecurityContext
注入到过滤器中,该过滤器知道如何创建
User
并将其设置到我的应用程序特定的
AuthenticationContext
:

@PreMatching
public class SecurityFilter implements ContainerRequestFilter {

    @Inject AuthenticationContextImpl authCtx; // Injecting the implementation,
                                               // not the interface!!!

    @Context SecurityContext securityCtx;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        User user = ...// translate the securityCtx into a User
        authCtx.setCurrentUser(user);
    }
}

然后,任何需要用户数据的业务 Bean 都会注入环境中立的、特定于应用程序的

AuthenticationContext


2
投票

@Context
只能在 JAX-RS 类中使用 - 即用
@Path
注释的类。

在您的例子中,

ProjectService
是CDI bean,而不是JAX-RS类。

执行您想要的操作的规范方法是将

SecurityContext
注入 JAX-RS 资源,然后将其作为方法参数传递给您的
ProjectService


0
投票

@Nikos Paraskevopoulos 我根据你的建议实现了一个过滤器,它对我帮助很大。 这是我的代码示例。

    public class Filter {
   @Context
   SecurityContext securityCtx;
   @Inject
   AuthenticationContextImpl authCtx;

   @ServerRequestFilter(preMatching = true)
   public void requestFilter() {
       ClienteDTO clienteDTO = new ClienteDTO();
       clienteDTO.setUsuarioId(1l);
       authCtx.setClienteDTO(clienteDTO);
   }

}

© www.soinside.com 2019 - 2024. All rights reserved.