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 /sessions
和 GET /batches
请求工作正常:我得到了 Livy 的预期响应。但是POST /sessions
和POST /batches
请求都失败了:
org.springframework.web.client.HttpClientErrorException: 401 Authentication required
有谁知道为什么 GET 请求成功时 POST 请求失败?我的代码对身份验证没有任何明确的作用。
我尝试过通过 Kerberos 对几个不同的用户进行身份验证,但我总是遇到这个问题。 Livy 是否需要额外的配置来允许来自特定用户的 POST 请求(因为 POST 请求有效地创建交互式会话或向 Spark 提交作业)?
【问题讨论】:
您是否跟踪了在 SPNego“协商”期间发送/接收的 HTTP 标头(始终以401
质询开始,但应以200
或403
结束)? GET 和 POST 的事件序列中的任何可见差异,例如在某个时候重定向?
很久以前 WebHDFS 也有类似的问题,但由于 Java 6 net
library 中的一个错误...希望您使用的是更新的东西!
感谢您的提示!不,我使用的是 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);
其中PostBatchesRequest
和Batch
是我编写的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 请求?
WorkManager 如何安排对 REST API 的 GET 请求?