Livy REST API:GET 请求有效,但 POST 请求失败并显示“需要 401 身份验证”

Posted

技术标签:

【中文标题】Livy REST API:GET 请求有效,但 POST 请求失败并显示“需要 401 身份验证”【英文标题】:Livy REST API: GET requests work but POST requests fail with '401 Authentication required' 【发布时间】:2017-10-24 11:13:00 【问题描述】:

我为https://github.com/apache/incubator-livy/blob/master/docs/rest-api.md 的 Livy 的部分 REST API 编写了一个 Java 客户端。客户端使用 Spring 的 RestTemplate.getForObject()postForObject() 分别发出 GET 和 POST 请求。 Livy 服务器由 Kerberos 保护。

GET /sessionsGET /batches 请求工作正常:我得到了 Livy 的预期响应。但是POST /sessionsPOST /batches 请求都失败了:

org.springframework.web.client.HttpClientErrorException: 401 Authentication required

有谁知道为什么 GET 请求成功时 POST 请求失败?我的代码对身份验证没有任何明确的作用。

我尝试过通过 Kerberos 对几个不同的用户进行身份验证,但我总是遇到这个问题。 Livy 是否需要额外的配置来允许来自特定用户的 POST 请求(因为 POST 请求有效地创建交互式会话或向 Spark 提交作业)?

【问题讨论】:

您是否跟踪了在 SPNego“协商”期间发送/接收的 HTTP 标头(始终以401 质询开始,但应以200403 结束)? GETPOST 的事件序列中的任何可见差异,例如在某个时候重定向? 很久以前 WebHDFS 也有类似的问题,但由于 Java 6 netlibrary 中的一个错误...希望您使用的是更新的东西! 感谢您的提示!不,我使用的是 Java 8(和 Livy v0.3.0 BTW)。我还没有设法跟踪这些 HTTP 标头,但与 GET 请求相比,Livy 似乎需要额外的 POST 请求安全性。目前正在尝试使用 Spring 的特殊版本 RestTemplate 与 Kerberos 一起使用:KerberosRestTemplate。几天后我有机会再发更多... 出于调试目的,您可以尝试 curl 命令行 HTTP 查询(如果 Kerberos TGT 在默认缓存中可用),然后使用 curl --negotiate -u : --trace-ascii - <some-GET-URL> 然后 -X POST --data 'blah blah' <some-POST-URL> 【参考方案1】:

事实证明,虽然常规的 org.springframework.web.client.RestTemplate 类足以处理 GET 请求,但您需要使用 org.springframework.security.kerberos.client.KerberosRestTemplate 处理 POST 请求。如果 Livy 服务器启用了 CSRF(跨站点请求伪造)保护,如here 所述,您可能还需要向 POST 请求添加额外的标头。

GET /batches 示例

RestTemplate restTemplate = new RestTemplate();
GetBatchesResponse response2 = restTemplate.getForObject("http://your_livy_server:8998" + "/batches", GetBatchesResponse.class);

GetBatchesResponse 是我编写的一个简单 POJO,它代表 response body 到 GET /batches

POST /batches 示例

PostBatchesRequest postRequestBody = new PostBatchesRequest();
postRequestBody.setFile("/path/to/your/application"); // In HDFS

KerberosRestTemplate kerberosRestTemplate = new KerberosRestTemplate("path_to_your_key_tab_file", "your_user@your_realm");

// Add CSRF header if required:
HttpHeaders headers = new HttpHeaders();
headers.set("X-Requested-By", "your_user@your_realm");
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<PostBatchesRequest> postRequest = new HttpEntity<PostBatchesRequest>(postRequestBody, headers);

Batch batch = kerberosRestTemplate.postForObject("http://your_livy_server:8998" + "/batches", postRequest, Batch.class);

其中PostBatchesRequestBatch 是我编写的POJO,分别代表request body 和response。

【讨论】:

感谢 Hortonworks 帮助我找到了这个解决方案! 如果可能的话,你也可以粘贴导入和依赖项吗?我很难找到它们。我也在尝试向 Livy 发布请求。 @Explorer - 你找不到 POJO(例如 PostBatchesRequest),因为它们是我写的。它们是公司代码,所以我不能分享它们,但我所做的只是为 Livy 的 REST API 编写一个 Java 客户端,并使用 org.springframework.web.client.RestTemplate 发出 GET 请求或使用 org.springframework.security.kerberos.client.KerberosRestTemplate 发出 POST 请求。..

以上是关于Livy REST API:GET 请求有效,但 POST 请求失败并显示“需要 401 身份验证”的主要内容,如果未能解决你的问题,请参考以下文章

Apache Livy:通过 REST 查询 Spark SQL:可能吗?

如何使用 Scala 在具有请求正文的 REST API 上执行 GET 请求?

我是否需要为SPA保护仅支持GET的REST API

WorkManager 如何安排对 REST API 的 GET 请求?

Gmail REST API:400错误请求+失败的前提条件

邮递员之外的 Netsuite REST Web 服务 API GET 请求