【问题标题】:Not able to receive header parameter in ContainerRequestFilter无法在 ContainerRequestFilter 中接收标头参数
【发布时间】:2019-04-20 11:11:46
【问题描述】:

我正在使用 Jersey2.0 在 Java 中创建 Web 服务。当我从 POSTMAN 执行请求时,一切都按预期工作,但是当我从客户端应用程序执行请求时,我无法接收标头参数。我的客户端应用程序在 JavaScript 上。另外,我在 ContainerResponseContext 中添加了 CORS 允许源请求参数。

以下显示了我在其中添加 CORS 的 ContainerResponseFilter 类。

@Provider
class CORSFilter : ContainerResponseFilter {

    override fun filter(requestContext: ContainerRequestContext?, responseContext: ContainerResponseContext?) {
        responseContext?.apply {
            headers.add("Access-Control-Allow-Origin", "*")
            headers.add("Access-Control-Allow-Headers", "origin, content-type, authorization, accept, privatekey")
            headers.add("Access-Control-Allow-Credentials", "true")
            headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
        }
    }
}

privatekey 是我的请求标头名称。现在这是我的 ContainerRequestFilter 代码。

@Priority(AUTHENTICATION)
@Provider
class JsTokenFilterNeeded : JsBaseFilter(this::class.java.simpleName) {

    override fun filter(request: ContainerRequestContext?) {
        val path = request?.uriInfo?.path       
        val privateKeyHeaderValue = request?.getHeaderString("privatekey")
        println("private key -> $privateKeyHeaderValue")
    }
}

我总是在 privateKeyHeaderValue 中得到空值。两个容器都在 ResourceConfig 类中成功注册。

到目前为止,我在所请求的资源上没有出现“Access-Control-Allow-Origin”标头,这是日志。

{host=[203.***.51.***:5555], connection=[keep-alive], access-control-request-method=[GET], origin=[http://localhost:38596], user-agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36], access-control-request-headers=[privatekey], accept=[*/*], alexatoolbar-alx_ns_ph=[AlexaToolbar/alx-4.0.3], referer=[http://localhost:38596/], accept-encoding=[gzip, deflate], accept-language=[en-US,en;q=0.9]}

编辑 1 这是我的客户端应用程序的 Js 代码。

$.ajax(
    {
        type: "GET",
        headers: {
            'privatekey': privateKey
        },
        url: "http://***.124.**.76:5555/dcu/energy/"+active_import,
        data: {
            'dcu_id': '99220445',
            'tariff': 0
        },
        error: function (result) {
            console.log(result);
        },
        success: function (result) {
            console.log(result);
        }
    });

编辑2 我正在使用 ResourceConfig 来注册我的提供者。这是我的 ResourceConfig 类。

class MyResourceConfig : ResourceConfig() {

    init {
        register(CORSFilter())
        register(JsTokenFilterNeeded())
    }
}

【问题讨论】:

  • 正如你所描述的,从邮递员那里一切正常。请分享 JS 中的客户端代码。此外,我建议打印整个请求以记录(或调试)并查看缺少的内容。
  • 如果你看到,我已经在问题的最后打印了日志,对于 Js 代码,我将编辑我的问题。
  • @AdiOhana 添加了 JavaScript 代码。
  • 签出stackoverflow.com/questions/28065963/…。您是否使用包扫描来发现提供者和资源?如果没有,那么您应该显式注册 CORSFilter
  • @AdiOhana 在发布我的问题之前我已经看过这个链接,而且我正在使用资源配置来注册我的提供者。

标签: java web-services jersey-2.0


【解决方案1】:

在真正的请求之前发生了一个preflight request。预检请求不发送任何标头(包括关键标头)。它只发送标头询问服务器是否允许请求。所以当 preflight 请求到达过滤器时,token 将不存在。

你应该做的是让 CorsFilter 实现一个ContainerRequestFilter 一个ContainerResponseFilter。使其成为@PreMatching 过滤器。这样它将在令牌过滤器之前被调用。在 request 过滤器中,检查它是否是预检请求。如果是,则中止请求。这将导致请求跳​​过其余的请求过滤器并直接进入 response 过滤器。在响应过滤器端,您可以添加 CORS 标头。

您应该阅读这篇文章中的the UPDATE,以更好地了解 CORS 协议的流程,并了解您可以使用的 CorsFilter 的更好实现,它应该适用于您的场景。

【讨论】:

    猜你喜欢
    • 2015-11-12
    • 2021-12-10
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多