当前位置: 首页 > 知识库问答 >
问题:

如何在注入到JAX-RS WebService中的CDI bean中获取HTTP请求头?

王锐
2023-03-14

我有这样一个web服务:

@Path("/projects")
public class Projects {
    [...]

    @Inject
    CurrentRequest current;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{id}")
    public Response getProject(@PathParam("id") String id) {
        if (current.isUserAuthenticated()) {
            [...do something...]
        } else {
            [...produce an error...]
        }
    }
}

和带有身份验证检查器方法的CDI bean,如下所示:

@RequestScoped
public class CurrentRequest {

    public boolean isUserAuthenticated() {
        [...do some header checking...]
    }
}

我目前的方法是在projects内部使用@context HttpServletRequest request并将其作为参数传递给current.isUserAuthenticated(request)。但这感觉太不对劲了。难道CDI bean不应该知道自己的请求吗?

我错过了什么?

共有1个答案

邢晗日
2023-03-14

您不需要JAX-RSendpoint中的HttpServletRequest来从请求中获取HTTP头。相反,您可以注入httpheaders:

@Context
HttpHeaders httpHeaders;

然后可以使用HttpHeadersAPI获取头值:

  • HttpHeaders#GetHeaderString(String)
  • HttpHeaders#GetRequestHeaders()
  • HttpHeaders#GetHeaderString(String)
// Get the value of the Authorization header
String authorizationHeader = httpHeaders.getHeaderString(HttpHeaders.AUTHORIZATION);

因为您正在执行身份验证和/或授权,所以我建议您使用过滤器,这样您就可以保持RESTendpoint的精干,并专注于业务逻辑

为了将过滤器绑定到您的RESTendpoint,JAX-RS提供了元注释@namebinding,可以使用如下:

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured { }

@securited批注将用于修饰筛选器类,该类实现ContainerRequestFilter,允许您处理请求。

ContainerRequestContext帮助您从HTTP请求中提取信息(有关详细信息,请参阅ContainerRequestContextAPI):

@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // Use the ContainerRequestContext to extract information from the HTTP request
        // Information such as the URI, headers and HTTP entity are available
    }
}

如果用户未经过身份验证/授权,ContainerRequestFilter#filter()方法是中止请求的好方法。为此,可以使用ContainerRequestContext#AbortWith()或引发异常。

@provider注释标记了扩展接口的实现,该扩展接口应该在提供程序扫描阶段被JAX-RS运行时发现。

若要将筛选器绑定到endpoint方法或类,请使用上面创建的@securited批注对它们进行批注。对于被注释的方法和/或类,将执行过滤器。

@Path("/")
public class MyEndpoint {

    @GET
    @Path("{id}")
    @Produces("application/json")
    public Response myUnsecuredMethod(@PathParam("id") Long id) {
        // This method is not annotated with @Secured
        // The security filter won't be executed before invoking this method
        ...
    }

    @DELETE
    @Secured
    @Path("{id}")
    @Produces("application/json")
    public Response mySecuredMethod(@PathParam("id") Long id) {
        // This method is annotated with @Secured
        // The security filter will be executed before invoking this method
        ...
    }
}

在上面的示例中,将只对mySecuredMethod(Long)执行安全筛选器,因为它用@Securite进行了注释。

您可以为RESTendpoint设置所需的筛选器。要确保过滤器的执行顺序,请使用@priority对其进行注释。

强烈建议使用priorities类中定义的值之一(将使用以下顺序):

  • 身份验证
  • 授权
  • entity_coder
  • header_decorator
  • 用户

如果筛选器没有使用@priority进行注释,则将使用user优先级执行筛选器。

你可能会发现这个答案很有用。

 类似资料:
  • 我想创建一个API,为了验证API使用者,我将提供一个API密钥、应用id和应用机密。问题是,我想知道http请求来自哪里,这样我就可以知道发出que请求的主机是否是注册主机。例如:www.someone。com的应用程序id为0001,应用程序机密为1200,api密钥为458。如果此凭据用于发出请求,我想知道请求者是否真的是www.someone。通用域名格式

  • 问题内容: 我正在尝试让我的函数返回http get请求,但是,无论如何,它似乎在?scope中丢失了。我对Node.js不熟悉,因此不胜感激 问题答案: 当然,您的日志会返回:您在完成请求之前先进行日志。问题不是范围,而是 异步性 。 是异步的,这就是为什么它将回调作为参数的原因。做您在回调中要做的事情(传递给的):

  • 本文向大家介绍php如何获取Http请求,包括了php如何获取Http请求的使用技巧和注意事项,需要的朋友参考一下 php获取Http请求的方法 $_SERVER介绍 $_SERVER是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。 获取Http请求的方法示例 实例补充: socket方式 使用套接字建立连接,拼接 HTTP

  • 问题内容: 在AngularJS中给出Ajax请求 如果启动另一个请求(相同的后端,例如不同的参数),取消该请求的最有效方法是什么? 问题答案: 此功能通过超时参数添加到1.1.5版本中:

  • 我正在构建一个Java的grpc服务器,我很难得到请求头。proto文件是使用Pro buf-maven-plugin编译的,基于生成的存根,我无法访问上下文或请求元数据。 我还尝试在消息请求中定义一个键/值列表,希望grpc能够处理头映射,但目前为止没有成功。 知道我怎么能拿到标题吗? 谢谢 我的原型文件内容: 服务器端实现如下所示: 版本请求。getHeadersCount()始终返回0,尽管

  • 问题内容: 我现在正在尝试使用Java Cord中的HTTP请求获取JSON对象。 我想知道如何在下面的代码中获取响应或JSON对象。 请告诉我。 (在此程序中,我尝试获取文章“ New York”的Wikipedia类别。) 问题答案: