You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/01/20 15:34:23 UTC
[iotdb] branch master updated: [IOTDB-2444] Refine /ping API and fix unauthorized NPE error (#4910)
This is an automated email from the ASF dual-hosted git repository.
rong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 09a46f3 [IOTDB-2444] Refine /ping API and fix unauthorized NPE error (#4910)
09a46f3 is described below
commit 09a46f34ed6e12ab978ed372f658c9910d3d38e4
Author: BaiJian <er...@hotmail.com>
AuthorDate: Thu Jan 20 23:32:28 2022 +0800
[IOTDB-2444] Refine /ping API and fix unauthorized NPE error (#4910)
---
docs/UserGuide/API/RestService.md | 47 ++++++++++++----
docs/zh/UserGuide/API/RestService.md | 46 +++++++++++-----
.../protocol/rest/filter/AuthorizationFilter.java | 17 +++++-
.../iotdb/db/protocol/rest/IoTDBRestServiceIT.java | 64 +++++++++++++++++++++-
4 files changed, 146 insertions(+), 28 deletions(-)
diff --git a/docs/UserGuide/API/RestService.md b/docs/UserGuide/API/RestService.md
index 12e7552..534564e 100644
--- a/docs/UserGuide/API/RestService.md
+++ b/docs/UserGuide/API/RestService.md
@@ -39,13 +39,46 @@ RESTful services are disabled by default.
```
### Authentication
-RESTful services use the basic authentication. Each URL request needs to carry `'Authorization': 'Basic ' + base64.encode(username + ':' + password)`.
+Except the liveness probe API `/ping`, RESTful services use the basic authentication. Each URL request needs to carry `'Authorization': 'Basic ' + base64.encode(username + ':' + password)`.
+The username used in the following examples is: `root`, and password is: `root`.
+
+And the authorization header is
+
+```
+Authorization: Basic cm9vdDpyb2901
+```
+
+- If a user authorized with incorrect username or password, the following error is returned:
+
+ HTTP Status Code:`401`
+
+ HTTP response body:
+ ```json
+ {
+ "code": 600,
+ "message": "WRONG_LOGIN_PASSWORD_ERROR"
+ }
+ ```
+
+- If the `Authorization` header is missing,the following error is returned:
+
+ HTTP Status Code:`401`
+
+ HTTP response body:
+ ```json
+ {
+ "code": 603,
+ "message": "UNINITIALIZED_AUTH_ERROR"
+ }
+ ```
### Interface
#### ping
+The `/ping` API can be used for service liveness probing.
+
Request method: `GET`
Request path: http://ip:port/ping
@@ -55,7 +88,7 @@ The user name used in the example is: root, password: root
Example request:
```shell
-$ curl -H "Authorization:Basic cm9vdDpyb2901" http://127.0.0.1:18080/ping
+$ curl http://127.0.0.1:18080/ping
```
Response parameters:
@@ -71,15 +104,8 @@ Sample response:
"message": "SUCCESS_STATUS"
}
```
-Example Of user name and password authentication failure:
-```json
-{
- "code": 600,
- "message": "WRONG_LOGIN_PASSWORD_ERROR"
-}
-```
-
+> `/ping` can be accessed without authorization.
#### query
@@ -882,4 +908,3 @@ trust_store_pwd=
```properties
idle_timeout=5000
```
-
diff --git a/docs/zh/UserGuide/API/RestService.md b/docs/zh/UserGuide/API/RestService.md
index e772bed..6a579a0 100644
--- a/docs/zh/UserGuide/API/RestService.md
+++ b/docs/zh/UserGuide/API/RestService.md
@@ -37,24 +37,52 @@ RESTful 服务默认情况是关闭的
```
### 鉴权
-RESTful 服务使用了基础(basic)鉴权,每次 URL 请求都需要在 header 中携带 `'Authorization': 'Basic ' + base64.encode(username + ':' + password)`。
+除了检活接口 `/ping`,RESTful 服务使用了基础(basic)鉴权,每次 URL 请求都需要在 header 中携带 `'Authorization': 'Basic ' + base64.encode(username + ':' + password)`。
+示例中使用的用户名为:`root`,密码为:`root`,对应的 Basic 鉴权 Header 格式为
+```
+Authorization: Basic cm9vdDpyb2901
+```
+
+- 若用户名密码认证失败,则返回如下信息:
+
+ HTTP 状态码:`401`
+
+ 返回结构体如下
+ ```json
+ {
+ "code": 600,
+ "message": "WRONG_LOGIN_PASSWORD_ERROR"
+ }
+ ```
+
+- 若未设置 `Authorization`,则返回如下信息:
+
+ HTTP 状态码:`401`
+
+ 返回结构体如下
+ ```json
+ {
+ "code": 603,
+ "message": "UNINITIALIZED_AUTH_ERROR"
+ }
+ ```
### 接口
#### ping
+ping 接口可以用于线上服务检活。
+
请求方式:`GET`
请求路径:http://ip:port/ping
-示例中使用的用户名为:root,密码为:root
-
请求示例:
```shell
-$ curl -H "Authorization:Basic cm9vdDpyb2901" http://127.0.0.1:18080/ping
+$ curl http://127.0.0.1:18080/ping
```
响应参数:
@@ -70,15 +98,8 @@ $ curl -H "Authorization:Basic cm9vdDpyb2901" http://127.0.0.1:18080/ping
"message": "SUCCESS_STATUS"
}
```
-用户名密码认证失败示例:
-```json
-{
- "code": 600,
- "message": "WRONG_LOGIN_PASSWORD_ERROR"
-}
-```
-
+> `/ping` 接口访问不需要鉴权。
#### query
@@ -900,4 +921,3 @@ trust_store_pwd=
```properties
idle_timeout=5000
```
-
diff --git a/server/src/main/java/org/apache/iotdb/db/protocol/rest/filter/AuthorizationFilter.java b/server/src/main/java/org/apache/iotdb/db/protocol/rest/filter/AuthorizationFilter.java
index 555adf2..4ee0b51 100644
--- a/server/src/main/java/org/apache/iotdb/db/protocol/rest/filter/AuthorizationFilter.java
+++ b/server/src/main/java/org/apache/iotdb/db/protocol/rest/filter/AuthorizationFilter.java
@@ -51,11 +51,24 @@ public class AuthorizationFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
if ("OPTIONS".equals(containerRequestContext.getMethod())
- || "swagger.json".equals(containerRequestContext.getUriInfo().getPath())) {
+ || "swagger.json".equals(containerRequestContext.getUriInfo().getPath())
+ || "ping".equals(containerRequestContext.getUriInfo().getPath())) {
return;
}
String authorizationHeader = containerRequestContext.getHeaderString("authorization");
+ if (authorizationHeader == null) {
+ Response resp =
+ Response.status(Status.UNAUTHORIZED)
+ .type(MediaType.APPLICATION_JSON)
+ .entity(
+ new ExecutionStatus()
+ .code(TSStatusCode.UNINITIALIZED_AUTH_ERROR.getStatusCode())
+ .message(TSStatusCode.UNINITIALIZED_AUTH_ERROR.name()))
+ .build();
+ containerRequestContext.abortWith(resp);
+ return;
+ }
User user = userCache.getUser(authorizationHeader);
if (user == null) {
user = checkLogin(containerRequestContext, authorizationHeader);
@@ -97,7 +110,7 @@ public class AuthorizationFilter implements ContainerRequestFilter {
try {
if (!authorizer.login(split[0], split[1])) {
Response resp =
- Response.status(Status.OK)
+ Response.status(Status.UNAUTHORIZED)
.type(MediaType.APPLICATION_JSON)
.entity(
new ExecutionStatus()
diff --git a/server/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceIT.java b/server/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceIT.java
index bbd1161..607b46f 100644
--- a/server/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceIT.java
@@ -73,8 +73,6 @@ public class IoTDBRestServiceIT {
HttpGet httpGet = new HttpGet("http://127.0.0.1:18080/ping");
CloseableHttpResponse response = null;
try {
- String authorization = getAuthorization("root", "root");
- httpGet.setHeader("Authorization", authorization);
response = httpClient.execute(httpGet);
HttpEntity responseEntity = response.getEntity();
String message = EntityUtils.toString(responseEntity, "utf-8");
@@ -194,6 +192,68 @@ public class IoTDBRestServiceIT {
}
}
+ @Test
+ public void queryWithUnsetAuthorization() {
+ CloseableHttpResponse response = null;
+ try {
+ CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+ HttpPost httpPost = new HttpPost("http://127.0.0.1:18080/rest/v1/query");
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+ httpPost.setHeader("Accept", "application/json");
+ String sql = "{\"sql\":\"select *,s4+1,s4+1 from root.sg25\"}";
+ httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
+ response = httpClient.execute(httpPost);
+ Assert.assertEquals(401, response.getStatusLine().getStatusCode());
+ String message = EntityUtils.toString(response.getEntity(), "utf-8");
+ JsonObject result = JsonParser.parseString(message).getAsJsonObject();
+ assertEquals(603, Integer.parseInt(result.get("code").toString()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ try {
+ if (response != null) {
+ response.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void queryWithWrongAuthorization() {
+ CloseableHttpResponse response = null;
+ try {
+ CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+ HttpPost httpPost = new HttpPost("http://127.0.0.1:18080/rest/v1/query");
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+ httpPost.setHeader("Accept", "application/json");
+ String authorization = getAuthorization("abc", "def");
+ httpPost.setHeader("Authorization", authorization);
+ String sql = "{\"sql\":\"select *,s4+1,s4+1 from root.sg25\"}";
+ httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
+ response = httpClient.execute(httpPost);
+ Assert.assertEquals(401, response.getStatusLine().getStatusCode());
+ String message = EntityUtils.toString(response.getEntity(), "utf-8");
+ JsonObject result = JsonParser.parseString(message).getAsJsonObject();
+ assertEquals(600, Integer.parseInt(result.get("code").toString()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ try {
+ if (response != null) {
+ response.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+ }
+
public void query(CloseableHttpClient httpClient) {
CloseableHttpResponse response = null;
try {