无法在ContainerRequestFilter中接收标头参数

时间:2019-04-20 11:11:46

标签: java web-services jersey-2.0

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

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

@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")
        }
    }
}

私有密钥是我的请求标头名称。现在,这是我的 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);
        }
    });

Edit2 我正在使用ResourceConfig来注册我的提供程序。这是我的ResourceConfig类。

class MyResourceConfig : ResourceConfig() {

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

1 个答案:

答案 0 :(得分:2)

在实际请求之前发生了preflight request。预检请求不发送任何标头(包括键标头)。它仅发送标头,询问服务器是否允许该请求。因此,当预检请求到达过滤器时,令牌将不存在。

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

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