You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by we...@apache.org on 2020/03/05 06:48:35 UTC

[incubator-apisix] branch master updated: feature: supported key-based authentication to the dashboard. (#1169)

This is an automated email from the ASF dual-hosted git repository.

wenming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new be2eec3  feature: supported key-based authentication to the dashboard. (#1169)
be2eec3 is described below

commit be2eec3c6d6151e4e5d76a1e82797605151d5d6c
Author: Wen Ming <mo...@gmail.com>
AuthorDate: Thu Mar 5 14:48:27 2020 +0800

    feature: supported key-based authentication to the dashboard. (#1169)
---
 FAQ.md                             |   4 +-
 FAQ_CN.md                          |   4 +-
 benchmark/run.sh                   |   4 +-
 conf/config.yaml                   |  15 +++
 doc/admin-api-cn.md                |   6 +-
 doc/admin-api.md                   |   6 +-
 doc/architecture-design-cn.md      |  36 +++----
 doc/architecture-design.md         |  34 +++---
 doc/benchmark.md                   |   4 +-
 doc/getting-started.md             |  10 +-
 doc/grpc-proxy-cn.md               |   2 +-
 doc/grpc-proxy.md                  |   2 +-
 doc/health-check.md                |   2 +-
 doc/how-to-build-cn.md             |  32 ++++++
 doc/how-to-build.md                |  37 ++++++-
 doc/https-cn.md                    |   4 +-
 doc/https.md                       |   4 +-
 doc/plugins-cn.md                  |   2 +-
 doc/plugins.md                     |   2 +-
 doc/plugins/basic-auth-cn.md       |   6 +-
 doc/plugins/basic-auth.md          |   4 +-
 doc/plugins/fault-injection-cn.md  |   6 +-
 doc/plugins/fault-injection.md     |   6 +-
 doc/plugins/grpc-transcoding-cn.md |   6 +-
 doc/plugins/grpc-transcoding.md    |   4 +-
 doc/plugins/ip-restriction-cn.md   |   2 +-
 doc/plugins/ip-restriction.md      |   2 +-
 doc/plugins/jwt-auth-cn.md         |   4 +-
 doc/plugins/jwt-auth.md            |   4 +-
 doc/plugins/key-auth-cn.md         |   4 +-
 doc/plugins/key-auth.md            |   4 +-
 doc/plugins/limit-conn-cn.md       |   4 +-
 doc/plugins/limit-conn.md          |   4 +-
 doc/plugins/limit-count-cn.md      |   6 +-
 doc/plugins/limit-count.md         |   6 +-
 doc/plugins/limit-req-cn.md        |   4 +-
 doc/plugins/limit-req.md           |   4 +-
 doc/plugins/mqtt-proxy-cn.md       |   2 +-
 doc/plugins/mqtt-proxy.md          |   2 +-
 doc/plugins/oauth.md               |   2 +-
 doc/plugins/prometheus-cn.md       |   2 +-
 doc/plugins/prometheus.md          |   2 +-
 doc/plugins/proxy-rewrite-cn.md    |   4 +-
 doc/plugins/proxy-rewrite.md       |   4 +-
 doc/plugins/redirect-cn.md         |   6 +-
 doc/plugins/redirect.md            |   6 +-
 doc/plugins/response-rewrite-cn.md |   2 +-
 doc/plugins/response-rewrite.md    |   4 +-
 doc/plugins/serverless-cn.md       |   4 +-
 doc/plugins/serverless.md          |   4 +-
 doc/plugins/wolf-rbac-cn.md        |   6 +-
 doc/plugins/wolf-rbac.md           |   6 +-
 doc/plugins/zipkin-cn.md           |   2 +-
 doc/plugins/zipkin.md              |   2 +-
 doc/router-radixtree.md            |   2 +-
 doc/stream-proxy-cn.md             |   4 +-
 doc/stream-proxy.md                |   4 +-
 lua/apisix/admin/init.lua          |  70 ++++++++++++-
 t/APISIX.pm                        |   2 +
 t/admin/token.t                    | 205 +++++++++++++++++++++++++++++++++++++
 t/grpc-proxy-test.sh               |   6 +-
 t/router/radixtree-host-uri.t      |   1 +
 t/router/radixtree-host-uri2.t     |   1 +
 t/router/radixtree-uri-host.t      |   1 +
 t/router/radixtree-uri-multiple.t  |   1 +
 t/router/radixtree-uri-priority.t  |   1 +
 t/router/radixtree-uri-sanity.t    |   1 +
 67 files changed, 506 insertions(+), 143 deletions(-)

diff --git a/FAQ.md b/FAQ.md
index 26ee8e9..166a8b0 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -80,7 +80,7 @@ An example, if you want to group by the request param `arg_id`:
 
 here is the way:
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "vars": [
@@ -93,7 +93,7 @@ curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
     }
 }'
 
-curl -i http://127.0.0.1:9080/apisix/admin/routes/2 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "vars": [
diff --git a/FAQ_CN.md b/FAQ_CN.md
index 55f4ceb..3775093 100644
--- a/FAQ_CN.md
+++ b/FAQ_CN.md
@@ -82,7 +82,7 @@ luarocks 服务。 运行 `luarocks config rocks_servers` 命令(这个命令
 
 可以这么做:
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "vars": [
@@ -95,7 +95,7 @@ curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
     }
 }'
 
-curl -i http://127.0.0.1:9080/apisix/admin/routes/2 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "vars": [
diff --git a/benchmark/run.sh b/benchmark/run.sh
index b0d26ad..ff068d6 100755
--- a/benchmark/run.sh
+++ b/benchmark/run.sh
@@ -44,7 +44,7 @@ sleep 3
 #############################################
 echo -e "\n\napisix: $worker_cnt worker + 1 upstream + no plugin"
 
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hello",
     "plugins": {
@@ -70,7 +70,7 @@ sleep 1
 #############################################
 echo -e "\n\napisix: $worker_cnt worker + 1 upstream + 2 plugins (limit-count + prometheus)"
 
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hello",
     "plugins": {
diff --git a/conf/config.yaml b/conf/config.yaml
index 3281f47..770bd47 100644
--- a/conf/config.yaml
+++ b/conf/config.yaml
@@ -39,6 +39,21 @@ apisix:
   #   - 127.0.0.0/24              # If we don't set any IP list, then any IP access is allowed by default.
   #   - "::/64"
   # port_admin: 9180              # use a separate port
+
+  # Default token when use API to call for Admin API.
+  # *NOTE*: Highly recommended to modify this value to protect APISIX's Admin API.
+  # Disabling this configuration item means that the Admin API does not
+  # require any authentication.
+  admin_key:
+    -
+      name: "admin"
+      key: edd1c9f034335f136f87ad84b625c8f1
+      role: admin                 # admin: manage all configuration data
+                                  # viewer: only can view configuration data
+    -
+      name: "viewer"
+      key: 4054f7cf07e344346cd3f287985e76a2
+      role: viewer
   router:
     http: 'radixtree_uri'         # radixtree_uri: match route by uri(base on radixtree)
                                   # radixtree_host_uri: match route by host + uri(base on radixtree)
diff --git a/doc/admin-api-cn.md b/doc/admin-api-cn.md
index 0f3aaff..1b61af1 100644
--- a/doc/admin-api-cn.md
+++ b/doc/admin-api-cn.md
@@ -75,7 +75,7 @@
 
 ```shell
 # 创建一个路由
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "hosts": ["foo.com", "*.bar.com"],
@@ -94,7 +94,7 @@ Date: Sat, 31 Aug 2019 01:17:15 GMT
 ...
 
 # 创建一个有效期为 60 秒的路由,过期后自动删除
-$ curl http://127.0.0.1:9080/apisix/admin/routes/2?ttl=60 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/2?ttl=60 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/aa/index.html",
     "upstream": {
@@ -128,7 +128,7 @@ Date: Sat, 31 Aug 2019 01:17:15 GMT
 请看下面例子,匹配请求参数 name 等于 json ,age 大于 18 且 address 开头是 China 的请求:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "vars": [
diff --git a/doc/admin-api.md b/doc/admin-api.md
index 76983e6..c14f0ac 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -71,7 +71,7 @@ Example:
 
 ```shell
 # Create a route
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "hosts": ["foo.com", "*.bar.com"],
@@ -90,7 +90,7 @@ Date: Sat, 31 Aug 2019 01:17:15 GMT
 ...
 
 # Create a route expires after 60 seconds, then it's deleted automatically
-$ curl http://127.0.0.1:9080/apisix/admin/routes/2?ttl=60 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/2?ttl=60 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/aa/index.html",
     "upstream": {
@@ -124,7 +124,7 @@ Return response from etcd currently.
 Consider the following example: matching requests whose `request name` is equal to `json`, `age` is greater than `18`, and `address` begins with `China`:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "vars": [
diff --git a/doc/architecture-design-cn.md b/doc/architecture-design-cn.md
index 227ba25..0747151 100644
--- a/doc/architecture-design-cn.md
+++ b/doc/architecture-design-cn.md
@@ -80,7 +80,7 @@ Route 中主要包含三部分内容:匹配规则(比如 uri、host、remote_a
 下面创建的 Route 示例,是把 uri 为 "/index.html" 的请求代理到地址为 "39.97.63.215:80" 的 Upstream 服务:
 
 ```shell
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "upstream": {
@@ -120,7 +120,7 @@ Server: APISIX web server
 
 ```shell
 # create new Service
-$ curl http://127.0.0.1:9080/apisix/admin/services/200 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/services/200 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
         "limit-count": {
@@ -139,14 +139,14 @@ $ curl http://127.0.0.1:9080/apisix/admin/services/200 -X PUT -d '
 }'
 
 # create new Route and reference the service by id `200`
-curl http://127.0.0.1:9080/apisix/admin/routes/100 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/100 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
     "service_id": "200"
 }'
 
-curl http://127.0.0.1:9080/apisix/admin/routes/101 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/101 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/foo/index.html",
@@ -157,7 +157,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/101 -X PUT -d '
 当然我们也可以为 Route 指定不同的插件参数或上游,比如下面这个 Route 设置了不同的限流参数,其他部分(比如上游)则继续使用 Service 中的配置参数。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/102 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/102 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/bar/index.html",
     "id": "102",
@@ -253,7 +253,7 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
 创建上游对象用例:
 
 ```json
-curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "type": "roundrobin",
     "nodes": {
@@ -263,7 +263,7 @@ curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -X PUT -d '
     }
 }'
 
-curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "type": "chash",
     "key": "remote_addr",
@@ -278,7 +278,7 @@ curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -X PUT -d '
 上游对象创建后,均可以被具体 `Route` 或 `Service` 引用,例如:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "upstream_id": 2
@@ -288,7 +288,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 为了方便使用,也可以直接把上游地址直接绑到某个 `Route` 或 `Service` ,例如:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -310,7 +310,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 
 下面是一个配置了健康检查的示例:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -350,7 +350,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 ##### Consumer
 创建一个consumer对象:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d `
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d `
 {
     "username": "jack",
     "plugins": {
@@ -362,7 +362,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d `
 ```
 新建路由,打开`key-auth`插件认证,`upstream`的`hash_on`类型为`consumer`:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
         "key-auth": {}
@@ -386,7 +386,7 @@ curl http://127.0.0.1:9080/server_port -H "apikey: auth-jack"
 ##### Cookie
 新建路由和`Upstream`,`hash_on`类型为`cookie`:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hash_on_cookie",
     "upstream": {
@@ -403,13 +403,13 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 
 客户端请求携带`Cookie`:
 ```shell
- curl http://127.0.0.1:9080/hash_on_cookie -H "Cookie: sid=3c183a30cffcda1408daf1c61d47b274"
+ curl http://127.0.0.1:9080/hash_on_cookie -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -H "Cookie: sid=3c183a30cffcda1408daf1c61d47b274"
 ```
 
 ##### Header
 新建路由和`Upstream`,`hash_on`类型为`header`, `key`为`content-type`:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hash_on_header",
     "upstream": {
@@ -426,7 +426,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 
 客户端请求携带`content-type`的`header`:
 ```shell
- curl http://127.0.0.1:9080/hash_on_header -H "Content-Type: application/json"
+ curl http://127.0.0.1:9080/hash_on_header -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -H "Content-Type: application/json"
 ```
 
 [返回目录](#目录)
@@ -482,7 +482,7 @@ APISIX 区别于其他 API 网关的一大特点是允许用户选择不同 Rout
 
 ```shell
 # 创建 Consumer ,指定认证插件 key-auth ,并开启特定插件 limit-count
-$ curl http://127.0.0.1:9080/apisix/admin/consumers/1 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/consumers/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "jack",
     "plugins": {
@@ -499,7 +499,7 @@ $ curl http://127.0.0.1:9080/apisix/admin/consumers/1 -X PUT -d '
 }'
 
 # 创建 Router,设置路由规则和启用插件配置
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
         "key-auth": {}
diff --git a/doc/architecture-design.md b/doc/architecture-design.md
index d678da9..3a312f7 100644
--- a/doc/architecture-design.md
+++ b/doc/architecture-design.md
@@ -81,7 +81,7 @@ The shortcomings mentioned above are independently abstracted in APISIX by the t
 The route example created below is to proxy the request with uri `/index.html` to the Upstream service with the address `39.97.63.215:80`:
 
 ```shell
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "upstream": {
@@ -120,7 +120,7 @@ The following example creates a Service that enables the current-limit plugin, a
 
 ```shell
 # create new Service
-$ curl http://127.0.0.1:9080/apisix/admin/services/200 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/services/200 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
         "limit-count": {
@@ -139,14 +139,14 @@ $ curl http://127.0.0.1:9080/apisix/admin/services/200 -X PUT -d '
 }'
 
 # create new Route and reference the service by id `200`
-curl http://127.0.0.1:9080/apisix/admin/routes/100 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/100 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
     "service_id": "200"
 }'
 
-curl http://127.0.0.1:9080/apisix/admin/routes/101 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/101 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/foo/index.html",
@@ -157,7 +157,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/101 -X PUT -d '
 Of course, we can also specify different plugin parameters or upstream for Route. Some of the following Routes have different current-limit parameters. Other parts (such as upstream) continue to use the configuration parameters in Service.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/102 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/102 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/bar/index.html",
     "id": "102",
@@ -241,7 +241,7 @@ In addition to the basic complex equalization algorithm selection, APISIX's Upst
 Create an upstream object use case:
 
 ```json
-curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "type": "roundrobin",
     "nodes": {
@@ -251,7 +251,7 @@ curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -X PUT -d '
     }
 }'
 
-curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "type": "chash",
     "key": "remote_addr",
@@ -266,7 +266,7 @@ curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -X PUT -d '
 After the upstream object is created, it can be referenced by specific `Route` or `Service`, for example:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "upstream_id": 2
@@ -276,7 +276,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 For convenience, you can also directly bind the upstream address to a `Route` or `Service`, for example:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -299,7 +299,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 Here's an example of configuring a health check:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -340,7 +340,7 @@ Here are some examples of configurations using different `hash_on` types:
 ##### Consumer
 Create a consumer object:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d `
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d `
 {
     "username": "jack",
     "plugins": {
@@ -352,7 +352,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d `
 ```
 Create route object and enable `key-auth` plugin authentication:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
         "key-auth": {}
@@ -376,7 +376,7 @@ curl http://127.0.0.1:9080/server_port -H "apikey: auth-jack"
 ##### Cookie
 Create route and upstream object, `hash_on` is `cookie`:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hash_on_cookie",
     "upstream": {
@@ -398,7 +398,7 @@ The client requests with `Cookie`:
 ##### Header
 Create route and upstream object, `hash_on` is `header`, `key` is `Content-Type`:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hash_on_header",
     "upstream": {
@@ -415,7 +415,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 
 The client requests with header `Content-Type`:
 ```shell
- curl http://127.0.0.1:9080/hash_on_header -H "Content-Type: application/json"
+ curl http://127.0.0.1:9080/hash_on_header -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -H "Content-Type: application/json"
 ```
 
 [Back to top](#Table-of-contents)
@@ -471,7 +471,7 @@ How to enable a specific plugin for a Consumer, you can see the following exampl
 
 ```shell
 # Create a Consumer , specify the authentication plugin key-auth, and enable the specific plugin limit-count
-$ curl http://127.0.0.1:9080/apisix/admin/consumers/1 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/consumers/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "jack",
     "plugins": {
@@ -488,7 +488,7 @@ $ curl http://127.0.0.1:9080/apisix/admin/consumers/1 -X PUT -d '
 }'
 
 # Create a Router, set routing rules and enable plugin configuration
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
         "key-auth": {}
diff --git a/doc/benchmark.md b/doc/benchmark.md
index b2fbf11..ac63f5e 100644
--- a/doc/benchmark.md
+++ b/doc/benchmark.md
@@ -45,7 +45,7 @@ The result of Flame Graph:
 And if you want to run the benchmark test in your machine, you should run another Nginx to listen 80 port.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/hello",
@@ -86,7 +86,7 @@ The result of Flame Graph:
 And if you want to run the benchmark test in your machine, you should run another Nginx to listen 80 port.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/hello",
diff --git a/doc/getting-started.md b/doc/getting-started.md
index 9d2f156..01b4d03 100644
--- a/doc/getting-started.md
+++ b/doc/getting-started.md
@@ -58,7 +58,7 @@ It will take a while to download the source for the first time. But the conseque
 After the docker containers have started visit the following link to check if you are getting a successful response.
 
 ```bash
-$ curl "http://127.0.0.1:9080/apisix/admin/services/"
+$ curl "http://127.0.0.1:9080/apisix/admin/services/" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
 ```
 
 The following will be the response from the Admin API.
@@ -128,7 +128,7 @@ Technically all this information(upstream or service, plugins) can be included i
 Execute the following command to create an upstream with the id of '50' in APISIX. Let's use the round-robin mechanism for load balancing.
 
 ```bash
-curl "http://127.0.0.1:9080/apisix/admin/upstreams/50" -X PUT -d '
+curl "http://127.0.0.1:9080/apisix/admin/upstreams/50" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "type": "roundrobin",
     "nodes": {
@@ -142,7 +142,7 @@ curl "http://127.0.0.1:9080/apisix/admin/upstreams/50" -X PUT -d '
 By default APISIX proxies the request via the HTTP protocol. As our backend is hosted in a HTTPS environment, let's use the proxy-rewrite plugin to change the scheme to HTTPS.
 
 ```bash
-curl "http://127.0.0.1:9080/apisix/admin/routes/5" -X PUT -d '
+curl "http://127.0.0.1:9080/apisix/admin/routes/5" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/get",
     "host": "httpbin.org",
@@ -177,7 +177,7 @@ Execute the following command to create a user called John with a dedicated api-
 Note: APISIX supports multiple authentication mechanism, view the plugin docs to learn more.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "john",
     "plugins": {
@@ -191,7 +191,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
 Now, let's configure our endpoint to include the key-auth plugin.
 
 ```bash
-curl http://127.0.0.1:9080/apisix/admin/routes/5 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/get",
     "host": "httpbin.org",
diff --git a/doc/grpc-proxy-cn.md b/doc/grpc-proxy-cn.md
index 301933c..4c1647b 100644
--- a/doc/grpc-proxy-cn.md
+++ b/doc/grpc-proxy-cn.md
@@ -40,7 +40,7 @@
 * 下面例子所代理的 gRPC 服务可供参考:[grpc_server_example](https://github.com/iresty/grpc_server_example)。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["POST", "GET"],
     "uri": "/helloworld.Greeter/SayHello",
diff --git a/doc/grpc-proxy.md b/doc/grpc-proxy.md
index c59141c..a6b8cf0 100644
--- a/doc/grpc-proxy.md
+++ b/doc/grpc-proxy.md
@@ -41,7 +41,7 @@ Here's an example, to proxying gRPC service by specified route:
 * the grpc server example:[grpc_server_example](https://github.com/iresty/grpc_server_example)
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["POST", "GET"],
     "uri": "/helloworld.Greeter/SayHello",
diff --git a/doc/health-check.md b/doc/health-check.md
index d992218..00d4e54 100644
--- a/doc/health-check.md
+++ b/doc/health-check.md
@@ -26,7 +26,7 @@ you can use it for upstream.
 The following is a example of health check:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
diff --git a/doc/how-to-build-cn.md b/doc/how-to-build-cn.md
index 2da7b95..c0000f1 100644
--- a/doc/how-to-build-cn.md
+++ b/doc/how-to-build-cn.md
@@ -108,3 +108,35 @@ Makefile rules:
 4. 通过 perl 的 `prove` 命令来加载 test-nginx 的库,并运行 `/t` 目录下的测试案例集:
     * 直接运行:`prove -Itest-nginx/lib -r t`
     * 指定 nginx 二进制路径:`TEST_NGINX_BINARY=/usr/local/bin/openresty prove -Itest-nginx/lib -r t`
+
+## 5. 更新 Admin API 的 token ,保护 Apache APISIX
+
+修改 `conf/config.yaml` 中的 `apisix.admin_key` 并重启服务。例如下面例子:
+
+```yaml
+apisix:
+  # ... ...
+  admin_key
+    -
+      name: "admin"
+      key: abcdefghabcdefgh
+      role: admin
+```
+
+当我们需要访问 Admin API 时,就可以使用上面记录的 key 作为 token 了。
+
+```shell
+$ curl http://127.0.0.1:9080/apisix/admin/routes?api_key=abcdefghabcdefgh -i
+HTTP/1.1 200 OK
+Date: Fri, 28 Feb 2020 07:48:04 GMT
+Content-Type: text/plain
+... ...
+{"node":{...},"action":"get"}
+
+$ curl http://127.0.0.1:9080/apisix/admin/routes?api_key=abcdefghabcdefgh-invalid -i
+HTTP/1.1 401 Unauthorized
+Date: Fri, 28 Feb 2020 08:17:58 GMT
+Content-Type: text/html
+... ...
+{"node":{...},"action":"get"}
+```
diff --git a/doc/how-to-build.md b/doc/how-to-build.md
index 8774f4b..a52a9ba 100644
--- a/doc/how-to-build.md
+++ b/doc/how-to-build.md
@@ -69,7 +69,7 @@ sudo luarocks install --lua-dir=/path/openresty/luajit apisix 1.1
 sudo luarocks install apisix 1.1
 ```
 
-## Manage (start/stop) APISIX Server
+## 3. Manage (start/stop) APISIX Server
 
 We can start the APISIX server by command `make run` in APISIX home folder,
 or we can stop APISIX server by command `make stop`.
@@ -102,7 +102,7 @@ Makefile rules:
     license-check: Check lua souce code for Apache License
 ```
 
-## Test
+## 4. Test
 
 1. Install perl's package manager `cpanminus` first
 2. Then install `test-gninx` via `cpanm`::`sudo cpanm --notest Test::Nginx IPC::Run > build.log 2>&1 || (cat build.log && exit 1)`
@@ -110,3 +110,36 @@ Makefile rules:
 4. Load the `test-nginx` library with perl's `prove` command and run the test cases in the `/t` directory:
     * Run the test cases: `prove -Itest-nginx/lib -r t`
     * To set the path of nginx to run the test cases: `TEST_NGINX_BINARY=/usr/local/bin/openresty prove -Itest-nginx/lib -r t`
+
+## 5. Update Admin API token to protect Apache APISIX
+
+Changes the `apisix.admin_key` in the file `conf/config.yaml` and restart the service.
+Here is an example:
+
+```yaml
+apisix:
+  # ... ...
+  admin_key
+    -
+      name: "admin"
+      key: abcdefghabcdefgh
+      role: admin
+```
+
+When calling the Admin API, `key` can be used as a token.
+
+```shell
+$ curl http://127.0.0.1:9080/apisix/admin/routes?api_key=abcdefghabcdefgh -i
+HTTP/1.1 200 OK
+Date: Fri, 28 Feb 2020 07:48:04 GMT
+Content-Type: text/plain
+... ...
+{"node":{...},"action":"get"}
+
+$ curl http://127.0.0.1:9080/apisix/admin/routes?api_key=abcdefghabcdefgh-invalid -i
+HTTP/1.1 401 Unauthorized
+Date: Fri, 28 Feb 2020 08:17:58 GMT
+Content-Type: text/html
+... ...
+{"node":{...},"action":"get"}
+```
diff --git a/doc/https-cn.md b/doc/https-cn.md
index 34de2d4..cf9a8ce 100644
--- a/doc/https-cn.md
+++ b/doc/https-cn.md
@@ -33,7 +33,7 @@ SNI(Server Name Indication)是用来改善 SSL 和 TLS 的一项特性,它允
 * `sni`: SSL 证书所指定的域名,注意在设置这个参数之前,你需要确保这个证书对应的私钥是有效的。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/ssl/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "cert": "...",
     "key": "....",
@@ -70,7 +70,7 @@ curl --resolve 'test.com:9443:127.0.0.1' https://test.com:9443/hello  -vvv
 看下面这个例子,请注意 `sni` 这个属性:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/ssl/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "cert": "...",
     "key": "....",
diff --git a/doc/https.md b/doc/https.md
index c63c709..04f2ea5 100644
--- a/doc/https.md
+++ b/doc/https.md
@@ -31,7 +31,7 @@ It is most common for an SSL certificate to contain only one domain. We can crea
 * `sni`: Hostname to associate with this certificate as SNIs. To set this attribute this certificate must have a valid private key associated with it.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/ssl/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "cert": "...",
     "key": "....",
@@ -69,7 +69,7 @@ Here is an example, please pay attention on the field `sni`.
 
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/ssl/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "cert": "...",
     "key": "....",
diff --git a/doc/plugins-cn.md b/doc/plugins-cn.md
index e93afec..02632b2 100644
--- a/doc/plugins-cn.md
+++ b/doc/plugins-cn.md
@@ -25,5 +25,5 @@ APISIX 的插件是热加载的,不管你是新增、删除还是修改插件
 
 只需要通过 admin API 发送一个 HTTP 请求即可:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/plugins/reload -X PUT
+curl http://127.0.0.1:9080/apisix/admin/plugins/reload -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT
 ```
diff --git a/doc/plugins.md b/doc/plugins.md
index 711290c..5f938c3 100644
--- a/doc/plugins.md
+++ b/doc/plugins.md
@@ -24,5 +24,5 @@ APISIX plug-ins are hot-loaded. No matter you add, delete or modify plug-ins, yo
 
 Just send an HTTP request through admin API:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/plugins/reload -X PUT
+curl http://127.0.0.1:9080/apisix/admin/plugins/reload -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT
 ```
diff --git a/doc/plugins/basic-auth-cn.md b/doc/plugins/basic-auth-cn.md
index 4ac16c8..19c8db5 100644
--- a/doc/plugins/basic-auth-cn.md
+++ b/doc/plugins/basic-auth-cn.md
@@ -45,7 +45,7 @@
 1. 创建一个 consumer 对象,并设置插件 `basic-auth` 的值。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "foo",
     "plugins": {
@@ -65,7 +65,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
 2. 创建 Route 或 Service 对象,并开启 `basic-auth` 插件。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/hello",
@@ -128,7 +128,7 @@ hello, foo!
 当你想去掉 `basic-auth` 插件的时候,很简单,在插件的配置中把对应的 `json` 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/hello",
diff --git a/doc/plugins/basic-auth.md b/doc/plugins/basic-auth.md
index 26a9df1..5c9efba 100644
--- a/doc/plugins/basic-auth.md
+++ b/doc/plugins/basic-auth.md
@@ -47,7 +47,7 @@ For more information on Basic authentication, refer to [Wiki](https://en.wikiped
 1. set a consumer and config the value of the `basic-auth` option
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "foo",
     "plugins": {
@@ -71,7 +71,7 @@ then add basic-auth plugin in the Consumer page:
 2. add a Route or add a Service , and enable the `basic-auth` plugin
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/hello",
diff --git a/doc/plugins/fault-injection-cn.md b/doc/plugins/fault-injection-cn.md
index da8d50a..103e6f7 100644
--- a/doc/plugins/fault-injection-cn.md
+++ b/doc/plugins/fault-injection-cn.md
@@ -40,7 +40,7 @@
 示例1:为特定路由启用 `fault-injection` 插件,并指定 `abort` 参数:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
        "fault-injection": {
@@ -79,7 +79,7 @@ Fault Injection!
 示例2:为特定路由启用 `fault-injection` 插件,并指定 `delay` 参数:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
        "fault-injection": {
@@ -123,7 +123,7 @@ sys     0m0.010s
 移除插件配置中相应的 JSON 配置可立即禁用该插件,无需重启服务:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hello",
     "plugins": {},
diff --git a/doc/plugins/fault-injection.md b/doc/plugins/fault-injection.md
index 9ccccef..da51044 100644
--- a/doc/plugins/fault-injection.md
+++ b/doc/plugins/fault-injection.md
@@ -41,7 +41,7 @@ Note: `abort` and `delay` must have at least one.
 1: enable the fault-injection plugin for a specific route and specify the abort attribute:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
        "fault-injection": {
@@ -80,7 +80,7 @@ Fault Injection!
 2: Enable the `fault-injection` plugin for a specific route and specify the `delay` attribute:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "plugins": {
        "fault-injection": {
@@ -124,7 +124,7 @@ sys     0m0.010s
 Remove the corresponding JSON in the plugin configuration to disable the plugin immediately without restarting the service:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hello",
     "plugins": {},
diff --git a/doc/plugins/grpc-transcoding-cn.md b/doc/plugins/grpc-transcoding-cn.md
index 83d8080..835f600 100644
--- a/doc/plugins/grpc-transcoding-cn.md
+++ b/doc/plugins/grpc-transcoding-cn.md
@@ -32,7 +32,7 @@ HTTP(s) -> APISIX -> gRPC server
 路径中最后的数字,会被用作 proto 的 id 做唯一标识,比如下面示例的 proto `id` 是 `1` :
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/proto/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/proto/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "content" : "syntax = \"proto3\";
     package helloworld;
@@ -66,7 +66,7 @@ curl http://127.0.0.1:9080/apisix/admin/proto/1 -X PUT -d '
 * 例子所代理的 grpc 服务可参考:[grpc_server_example](https://github.com/iresty/grpc_server_example)
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/111 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/111 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/grpctest",
@@ -133,7 +133,7 @@ Proxy-Connection: keep-alive
     > disable_hooks
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/23 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/23 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/zeebe/WorkflowInstanceCreate",
diff --git a/doc/plugins/grpc-transcoding.md b/doc/plugins/grpc-transcoding.md
index 0b5c391..9813a2f 100644
--- a/doc/plugins/grpc-transcoding.md
+++ b/doc/plugins/grpc-transcoding.md
@@ -33,7 +33,7 @@ HTTP(s) -> APISIX -> gRPC server
 Here's an example, adding a proto which `id` is `1`:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/proto/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/proto/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "content" : "syntax = \"proto3\";
     package helloworld;
@@ -65,7 +65,7 @@ Here's an example, to enable the grpc-transcode plugin to specified route:
 * the grpc server example:[grpc_server_example](https://github.com/iresty/grpc_server_example)
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/111 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/111 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/grpctest",
diff --git a/doc/plugins/ip-restriction-cn.md b/doc/plugins/ip-restriction-cn.md
index 55f4754..c9f1fcf 100644
--- a/doc/plugins/ip-restriction-cn.md
+++ b/doc/plugins/ip-restriction-cn.md
@@ -42,7 +42,7 @@
 下面是一个示例,在指定的 route 上开启了 `ip-restriction` 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "upstream": {
diff --git a/doc/plugins/ip-restriction.md b/doc/plugins/ip-restriction.md
index 429003f..d6e0698 100644
--- a/doc/plugins/ip-restriction.md
+++ b/doc/plugins/ip-restriction.md
@@ -48,7 +48,7 @@ together.
 Creates a route or service object, and enable plugin `ip-restriction`.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "upstream": {
diff --git a/doc/plugins/jwt-auth-cn.md b/doc/plugins/jwt-auth-cn.md
index 3e9d47d..8dfc5cb 100644
--- a/doc/plugins/jwt-auth-cn.md
+++ b/doc/plugins/jwt-auth-cn.md
@@ -47,7 +47,7 @@
 1. 创建一个 consumer 对象,并设置插件 `jwt-auth` 的值。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "jack",
     "plugins": {
@@ -67,7 +67,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
 2. 创建 Route 或 Service 对象,并开启 `jwt-auth` 插件。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/jwt-auth.md b/doc/plugins/jwt-auth.md
index 2028107..4d4e352 100644
--- a/doc/plugins/jwt-auth.md
+++ b/doc/plugins/jwt-auth.md
@@ -49,7 +49,7 @@ For more information on JWT, refer to [JWT](https://jwt.io/) for more informatio
 1. set a consumer and config the value of the `jwt-auth` option
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "jack",
     "plugins": {
@@ -71,7 +71,7 @@ then add jwt-auth plugin in the Consumer page:
 2. add a Route or add a Service , and enable the `jwt-auth` plugin
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/key-auth-cn.md b/doc/plugins/key-auth-cn.md
index 93cd7b7..e7b392c 100644
--- a/doc/plugins/key-auth-cn.md
+++ b/doc/plugins/key-auth-cn.md
@@ -42,7 +42,7 @@
 1. 创建一个 consumer 对象,并设置插件 `key-auth` 的值。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "jack",
     "plugins": {
@@ -62,7 +62,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
 2. 创建 route 或 service 对象,并开启 `key-auth` 插件。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/key-auth.md b/doc/plugins/key-auth.md
index 33153ae..acb02f7 100644
--- a/doc/plugins/key-auth.md
+++ b/doc/plugins/key-auth.md
@@ -47,7 +47,7 @@ Two steps are required:
 1. creates a consumer object, and set the attributes of plugin `key-auth`.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "username": "jack",
     "plugins": {
@@ -67,7 +67,7 @@ Then add key-auth plugin:
 2. creates a route or service object, and enable plugin `key-auth`.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/limit-conn-cn.md b/doc/plugins/limit-conn-cn.md
index acb11c7..fb0b4d7 100644
--- a/doc/plugins/limit-conn-cn.md
+++ b/doc/plugins/limit-conn-cn.md
@@ -40,7 +40,7 @@ Apisix 的限制并发请求(或并发连接)插件。
 下面是一个示例,在指定的 route 上开启了 limit-conn 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
@@ -93,7 +93,7 @@ curl -i http://127.0.0.1:9080/index.html?sleep=20
 当你想去掉 limit-conn 插件的时候,很简单,在插件的配置中把对应的 json 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/limit-conn.md b/doc/plugins/limit-conn.md
index c73ebac..db963f7 100644
--- a/doc/plugins/limit-conn.md
+++ b/doc/plugins/limit-conn.md
@@ -45,7 +45,7 @@ Limiting request concurrency (or concurrent connections) plugin for Apisix.
 Here's an example, enable the limit-conn plugin on the specified route:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
@@ -99,7 +99,7 @@ When you want to disable the limit-conn plugin, it is very simple,
   no need to restart the service, it will take effect immediately:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/limit-count-cn.md b/doc/plugins/limit-count-cn.md
index 98fc1ca..bee8ef4 100644
--- a/doc/plugins/limit-count-cn.md
+++ b/doc/plugins/limit-count-cn.md
@@ -43,7 +43,7 @@
 下面是一个示例,在指定的 `route` 上开启了 `limit count` 插件:
 
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -74,7 +74,7 @@ curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 请看下面例子:
 
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -139,7 +139,7 @@ Server: APISIX web server
 当你想去掉 `limit count` 插件的时候,很简单,在插件的配置中把对应的 json 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/limit-count.md b/doc/plugins/limit-count.md
index 8d436d1..122f0dc 100644
--- a/doc/plugins/limit-count.md
+++ b/doc/plugins/limit-count.md
@@ -49,7 +49,7 @@ Limit request rate by a fixed number of requests in a given time window.
 Here's an example, enable the `limit count` plugin on the specified route:
 
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -80,7 +80,7 @@ If you need a cluster-level precision traffic limit, then we can do it with the
 Here is the example:
 
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -147,7 +147,7 @@ When you want to disable the `limit count` plugin, it is very simple,
  you can delete the corresponding json configuration in the plugin configuration,
   no need to restart the service, it will take effect immediately:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/limit-req-cn.md b/doc/plugins/limit-req-cn.md
index 74b27f1..25fb4e1 100644
--- a/doc/plugins/limit-req-cn.md
+++ b/doc/plugins/limit-req-cn.md
@@ -34,7 +34,7 @@
 下面是一个示例,在指定的 route 上开启了 limit req 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
@@ -92,7 +92,7 @@ Server: APISIX web server
 当你想去掉 limit req 插件的时候,很简单,在插件的配置中把对应的 json 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/limit-req.md b/doc/plugins/limit-req.md
index 59c1847..6d41d2d 100644
--- a/doc/plugins/limit-req.md
+++ b/doc/plugins/limit-req.md
@@ -43,7 +43,7 @@ limit request rate using the "leaky bucket" method.
 Here's an example, enable the limit req plugin on the specified route:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
@@ -102,7 +102,7 @@ When you want to disable the limit req plugin, it is very simple,
  you can delete the corresponding json configuration in the plugin configuration,
   no need to restart the service, it will take effect immediately:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/mqtt-proxy-cn.md b/doc/plugins/mqtt-proxy-cn.md
index 287fc31..141e998 100644
--- a/doc/plugins/mqtt-proxy-cn.md
+++ b/doc/plugins/mqtt-proxy-cn.md
@@ -60,7 +60,7 @@
 下面是一个示例,在指定的 route 上开启了 mqtt-proxy 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "remote_addr": "127.0.0.1",
     "plugins": {
diff --git a/doc/plugins/mqtt-proxy.md b/doc/plugins/mqtt-proxy.md
index fb0abe2..83ff9f9 100644
--- a/doc/plugins/mqtt-proxy.md
+++ b/doc/plugins/mqtt-proxy.md
@@ -66,7 +66,7 @@ Then send the MQTT request to port 9100.
 Creates a stream route, and enable plugin `mqtt-proxy`.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "remote_addr": "127.0.0.1",
     "plugins": {
diff --git a/doc/plugins/oauth.md b/doc/plugins/oauth.md
index fb893b3..3ecfeea 100644
--- a/doc/plugins/oauth.md
+++ b/doc/plugins/oauth.md
@@ -55,7 +55,7 @@ The following is the curl command to enable the plugin to an external service.
 This route will protect `https://httpbin.org/get`(echo service) by introspecting the token provided in the header of the request.
 
 ```bash
-curl http://127.0.0.1:9080/apisix/admin/routes/5 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
   "uri": "/get",
   "plugins": {
diff --git a/doc/plugins/prometheus-cn.md b/doc/plugins/prometheus-cn.md
index 139d9bf..1dd8142 100644
--- a/doc/plugins/prometheus-cn.md
+++ b/doc/plugins/prometheus-cn.md
@@ -34,7 +34,7 @@
 例子如下:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hello",
     "plugins": {
diff --git a/doc/plugins/prometheus.md b/doc/plugins/prometheus.md
index 154ede9..1b57a97 100644
--- a/doc/plugins/prometheus.md
+++ b/doc/plugins/prometheus.md
@@ -34,7 +34,7 @@ any options yet.
 For example:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/hello",
     "plugins": {
diff --git a/doc/plugins/proxy-rewrite-cn.md b/doc/plugins/proxy-rewrite-cn.md
index 1a44162..a49bdf8 100644
--- a/doc/plugins/proxy-rewrite-cn.md
+++ b/doc/plugins/proxy-rewrite-cn.md
@@ -38,7 +38,7 @@
 下面是一个示例,在指定的 route 上开启了 `proxy rewrite` 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
@@ -81,7 +81,7 @@ curl -X GET http://127.0.0.1:9080/test/index.html
 当你想去掉 `proxy rewrite` 插件的时候,很简单,在插件的配置中把对应的 json 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
diff --git a/doc/plugins/proxy-rewrite.md b/doc/plugins/proxy-rewrite.md
index c0b5755..06dd685 100644
--- a/doc/plugins/proxy-rewrite.md
+++ b/doc/plugins/proxy-rewrite.md
@@ -45,7 +45,7 @@ upstream proxy info rewrite plugin.
 Here's an example, enable the `proxy rewrite` plugin on the specified route:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
@@ -89,7 +89,7 @@ When you want to disable the `proxy rewrite` plugin, it is very simple,
  you can delete the corresponding json configuration in the plugin configuration,
   no need to restart the service, it will take effect immediately :
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
diff --git a/doc/plugins/redirect-cn.md b/doc/plugins/redirect-cn.md
index 5edaaf8..ba7d94c 100644
--- a/doc/plugins/redirect-cn.md
+++ b/doc/plugins/redirect-cn.md
@@ -37,7 +37,7 @@ URI 重定向插件。
 下面是一个基本实例,为特定路由启用 `redirect` 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/test/index.html",
     "plugins": {
@@ -58,7 +58,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 我们可以在新的 URI 中使用 Nginx 内置的任意变量:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/test",
     "plugins": {
@@ -99,7 +99,7 @@ Location: /test/default.html
 移除插件配置中相应的 JSON 配置可立即禁用该插件,无需重启服务:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/test/index.html",
     "plugins": {},
diff --git a/doc/plugins/redirect.md b/doc/plugins/redirect.md
index 8a0e44c..86a12ab 100644
--- a/doc/plugins/redirect.md
+++ b/doc/plugins/redirect.md
@@ -42,7 +42,7 @@ URI redirect.
 Here's a mini example, enable the `redirect` plugin on the specified route:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/test/index.html",
     "plugins": {
@@ -63,7 +63,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
 And we can use any Nginx built-in variable in the new URI.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/test",
     "plugins": {
@@ -108,7 +108,7 @@ When you want to disable the `redirect` plugin, it is very simple,
   no need to restart the service, it will take effect immediately :
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/test/index.html",
     "plugins": {},
diff --git a/doc/plugins/response-rewrite-cn.md b/doc/plugins/response-rewrite-cn.md
index d81e62b..2a97f42 100644
--- a/doc/plugins/response-rewrite-cn.md
+++ b/doc/plugins/response-rewrite-cn.md
@@ -40,7 +40,7 @@
 下面是一个示例,在指定的 route 上开启了 `response rewrite` 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
diff --git a/doc/plugins/response-rewrite.md b/doc/plugins/response-rewrite.md
index 0857f37..98adcb3 100644
--- a/doc/plugins/response-rewrite.md
+++ b/doc/plugins/response-rewrite.md
@@ -44,7 +44,7 @@ response rewrite plugin, rewrite the content from upstream.
 Here's an example, enable the `response rewrite` plugin on the specified route:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
@@ -92,7 +92,7 @@ When you want to disable the `response rewrite` plugin, it is very simple,
  you can delete the corresponding json configuration in the plugin configuration,
   no need to restart the service, it will take effect immediately:
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/test/index.html",
diff --git a/doc/plugins/serverless-cn.md b/doc/plugins/serverless-cn.md
index c9f5f49..be8e7c8 100644
--- a/doc/plugins/serverless-cn.md
+++ b/doc/plugins/serverless-cn.md
@@ -57,7 +57,7 @@ ngx.say(count)
 下面是一个示例,在指定的 route 上开启了 serverless 插件:
 
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -88,7 +88,7 @@ curl -i http://127.0.0.1:9080/index.html
 当你想去掉插件的时候,很简单,在插件的配置中把对应的 json 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/serverless.md b/doc/plugins/serverless.md
index e6cffda..c3a722f 100644
--- a/doc/plugins/serverless.md
+++ b/doc/plugins/serverless.md
@@ -69,7 +69,7 @@ ngx.say(count)
 Here's an example, enable the serverless plugin on the specified route:
 
 ```shell
-curl -i http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl -i http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "uri": "/index.html",
     "plugins": {
@@ -104,7 +104,7 @@ When you want to disable the serverless plugin, it is very simple,
   no need to restart the service, it will take effect immediately:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/wolf-rbac-cn.md b/doc/plugins/wolf-rbac-cn.md
index 37c9dd7..bd06281 100644
--- a/doc/plugins/wolf-rbac-cn.md
+++ b/doc/plugins/wolf-rbac-cn.md
@@ -56,7 +56,7 @@ rbac功能由[wolf](https://github.com/iGeeky/wolf)提供, 有关 `wolf` 的更
 1. 创建一个 consumer 对象,并设置插件 `wolf-rbac` 的值。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
   "username":"wolf_rbac",
   "plugins":{
@@ -80,7 +80,7 @@ curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
 2. 创建 Route 或 Service 对象,并开启 `wolf-rbac` 插件。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/*",
@@ -190,7 +190,7 @@ HTTP/1.1 200 OK
 当你想去掉 `rbac-wolf` 插件的时候,很简单,在routes中的插件配置中把对应的 `插件` 配置删除即可,无须重启服务,即刻生效:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/*",
diff --git a/doc/plugins/wolf-rbac.md b/doc/plugins/wolf-rbac.md
index e237b63..0b582c6 100644
--- a/doc/plugins/wolf-rbac.md
+++ b/doc/plugins/wolf-rbac.md
@@ -56,7 +56,7 @@ The rbac feature is provided by [wolf](https://github.com/iGeeky/wolf). For more
 1. set a consumer and config the value of the `wolf-rbac`。
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/consumers -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/consumers  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
   "username":"wolf_rbac",
   "plugins":{
@@ -80,7 +80,7 @@ Notes: The `appid` filled in above needs to already exist in the wolf system.
 1. Add a `Route` or `Service` and enable the wolf-rbac plugin.
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/*",
@@ -192,7 +192,7 @@ When you want to disable the `wolf-rbac` plugin, it is very simple,
   no need to restart the service, it will take effect immediately:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/*",
diff --git a/doc/plugins/zipkin-cn.md b/doc/plugins/zipkin-cn.md
index 2f43999..2e5b75c 100644
--- a/doc/plugins/zipkin-cn.md
+++ b/doc/plugins/zipkin-cn.md
@@ -42,7 +42,7 @@
 下面是一个示例,在指定的 route 上开启了 zipkin 插件:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/plugins/zipkin.md b/doc/plugins/zipkin.md
index 629e35b..b351219 100644
--- a/doc/plugins/zipkin.md
+++ b/doc/plugins/zipkin.md
@@ -45,7 +45,7 @@ It's also works with `Apache SkyWalking`, which is support Zipkin v1/v2 format.
 Here's an example, enable the zipkin plugin on the specified route:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["GET"],
     "uri": "/index.html",
diff --git a/doc/router-radixtree.md b/doc/router-radixtree.md
index 0641dd7..de47cda 100644
--- a/doc/router-radixtree.md
+++ b/doc/router-radixtree.md
@@ -75,7 +75,7 @@ Please take a look at [radixtree-new](https://github.com/iresty/lua-resty-radixt
 here is an simple example:
 
 ```shell
-$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -i -d '
+$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
 {
     "uri": "/index.html",
     "vars": [
diff --git a/doc/stream-proxy-cn.md b/doc/stream-proxy-cn.md
index 536751f..92416b2 100644
--- a/doc/stream-proxy-cn.md
+++ b/doc/stream-proxy-cn.md
@@ -46,7 +46,7 @@ apisix:
 简例如下:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "remote_addr": "127.0.0.1",
     "upstream": {
@@ -66,7 +66,7 @@ curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
 我们可以添加更多的选项来匹配 route ,例如
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "server_addr": "127.0.0.1",
     "server_port": 2000,
diff --git a/doc/stream-proxy.md b/doc/stream-proxy.md
index 0bf1197..e149ce4 100644
--- a/doc/stream-proxy.md
+++ b/doc/stream-proxy.md
@@ -46,7 +46,7 @@ apisix:
 Here is a mini example:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "remote_addr": "127.0.0.1",
     "upstream": {
@@ -67,7 +67,7 @@ For more use cases, please take a look at [test case](../t/stream-node/sanity.t)
 And we can add more limit options to match a route, here is an example:
 
 ```shell
-curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "server_addr": "127.0.0.1",
     "server_port": 2000,
diff --git a/lua/apisix/admin/init.lua b/lua/apisix/admin/init.lua
index ee4ebea..af56288 100644
--- a/lua/apisix/admin/init.lua
+++ b/lua/apisix/admin/init.lua
@@ -14,6 +14,7 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 --
+
 local core = require("apisix.core")
 local route = require("resty.radixtree")
 local plugin = require("apisix.plugin")
@@ -23,9 +24,15 @@ local tonumber = tonumber
 local str_lower = string.lower
 local require = require
 local reload_event = "/apisix/admin/plugins/reload"
+local ipairs = ipairs
 local events
 
 
+local viewer_methods = {
+    get = true,
+}
+
+
 local resources = {
     routes          = require("apisix.admin.routes"),
     services        = require("apisix.admin.services"),
@@ -40,11 +47,54 @@ local resources = {
 }
 
 
-local _M = {version = 0.3}
+local _M = {version = 0.4}
 local router
 
 
+local function check_token(ctx)
+    local local_conf = core.config.local_conf()
+    if not local_conf or not local_conf.apisix
+       or not local_conf.apisix.admin_key then
+        return true
+    end
+
+    local req_token = ctx.var.arg_api_key or ctx.var.http_x_api_key
+                      or ctx.var.cookie_x_api_key
+    if not req_token then
+        return false, "missing apikey"
+    end
+
+    local admin
+    for i, row in ipairs(local_conf.apisix.admin_key) do
+        if req_token == row.key then
+            admin = row
+            break
+        end
+    end
+
+    if not admin then
+        return false, "wrong apikey"
+    end
+
+    if admin.role == "viewer" and
+       not viewer_methods[str_lower(get_method())] then
+        return false, "invalid method for role viewer"
+    end
+
+    return true
+end
+
+
 local function run()
+    local api_ctx = {}
+    core.ctx.set_vars_meta(api_ctx)
+
+    local ok, err = check_token(api_ctx)
+    if not ok then
+        core.log.warn("failed to check token: ", err)
+        core.response.exit(401)
+    end
+
     local uri_segs = core.utils.split_uri(ngx.var.uri)
     core.log.info("uri: ", core.json.delay_encode(uri_segs))
 
@@ -98,12 +148,30 @@ end
 
 
 local function get_plugins_list()
+    local api_ctx = {}
+    core.ctx.set_vars_meta(api_ctx)
+
+    local ok, err = check_token(api_ctx)
+    if not ok then
+        core.log.warn("failed to check token: ", err)
+        core.response.exit(401)
+    end
+
     local plugins = resources.plugins.get_plugins_list()
     core.response.exit(200, plugins)
 end
 
 
 local function post_reload_plugins()
+    local api_ctx = {}
+    core.ctx.set_vars_meta(api_ctx)
+
+    local ok, err = check_token(api_ctx)
+    if not ok then
+        core.log.warn("failed to check token: ", err)
+        core.response.exit(401)
+    end
+
     local success, err = events.post(reload_event, get_method(), ngx.time())
     if not success then
         core.response.exit(500, err)
diff --git a/t/APISIX.pm b/t/APISIX.pm
index 7e8755e..6d4da7a 100644
--- a/t/APISIX.pm
+++ b/t/APISIX.pm
@@ -42,6 +42,8 @@ my $ssl_crt = read_file("conf/cert/apisix.crt");
 my $ssl_key = read_file("conf/cert/apisix.key");
 $yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
 $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
+
 my $profile = $ENV{"APISIX_PROFILE"};
 
 
diff --git a/t/admin/token.t b/t/admin/token.t
new file mode 100644
index 0000000..80cc441
--- /dev/null
+++ b/t/admin/token.t
@@ -0,0 +1,205 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+use Cwd qw(cwd);
+
+repeat_each(1);
+no_long_string();
+no_root_location();
+no_shuffle();
+log_level("info");
+
+my $apisix_home = $ENV{APISIX_HOME} || cwd();
+
+sub read_file($) {
+    my $infile = shift;
+    open my $in, "$apisix_home/$infile"
+        or die "cannot open $infile for reading: $!";
+    my $data = do { local $/; <$in> };
+    close $in;
+    $data;
+}
+
+my $yaml_config = read_file("conf/config.yaml");
+$yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
+$yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    my $user_yaml_config = $block->yaml_config;
+    $user_yaml_config .= <<_EOC_;
+$yaml_config
+_EOC_
+
+    $block->set_value("yaml_config", $user_yaml_config);
+});
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: set route without token
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").req_self_with_http
+            local res, err = t('/apisix/admin/routes/1',
+                "PUT",
+                [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8080": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/index.html"
+                }]]
+                )
+
+            ngx.status = res.status
+            ngx.print(res.body)
+        }
+    }
+--- request
+GET /t
+--- error_code: 401
+--- no_error_log
+[error]
+
+
+
+=== TEST 2: set route with wrong token
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").req_self_with_http
+            local res, err = t(
+                '/apisix/admin/routes/1',
+                "PUT",
+                [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8080": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/index.html"
+                }]],
+                {apikey = "wrong_key"}
+                )
+
+            ngx.status = res.status
+            ngx.print(res.body)
+        }
+    }
+--- request
+GET /t
+--- error_code: 401
+--- no_error_log
+[error]
+
+
+
+=== TEST 3: set route with correct token
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").req_self_with_http
+            local res, err = t(
+                '/apisix/admin/routes/1',
+                "PUT",
+                [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:8080": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/index.html"
+                }]],
+                {x_api_key = "edd1c9f034335f136f87ad84b625c8f1"}
+                )
+
+            if res.status > 299 then
+                ngx.status = res.status
+            end
+            ngx.say("done")
+        }
+    }
+--- request
+GET /t
+--- response_body
+done
+--- no_error_log
+[error]
+
+
+
+=== TEST 4: get plugins name
+--- request
+GET /apisix/admin/plugins/list
+--- error_code: 401
+--- no_error_log
+[error]
+
+
+
+=== TEST 5: reload plugins
+--- request
+PUT /apisix/admin/plugins/reload
+--- error_code: 401
+--- no_error_log
+[error]
+
+
+
+=== TEST 6: reload plugins with api key(arguments)
+--- request
+PUT /apisix/admin/plugins/reload?api_key=edd1c9f034335f136f87ad84b625c8f1
+--- error_code: 200
+--- no_error_log
+[error]
+
+
+
+=== TEST 7: reload plugins with api key(cookie)
+--- request
+PUT /apisix/admin/plugins/reload
+--- more_headers
+X-API-KEY: edd1c9f034335f136f87ad84b625c8f1
+--- error_code: 200
+--- no_error_log
+[error]
+
+
+
+=== TEST 8: reload plugins with api key(viewer role)
+--- request
+PUT /apisix/admin/plugins/reload?api_key=4054f7cf07e344346cd3f287985e76a2
+--- error_code: 401
+--- no_error_log
+[error]
+
+
+
+=== TEST 9: fetch with api key(viewer role)
+--- request
+GET /apisix/admin/routes??api_key=4054f7cf07e344346cd3f287985e76a2
+--- error_code: 401
+--- no_error_log
+[error]
diff --git a/t/grpc-proxy-test.sh b/t/grpc-proxy-test.sh
old mode 100644
new mode 100755
index 50cd96f..6f8f2d1
--- a/t/grpc-proxy-test.sh
+++ b/t/grpc-proxy-test.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -16,8 +16,10 @@
 # limitations under the License.
 #
 
+set -ex
+
 #test grpc proxy
-curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
+curl http://127.0.0.1:9080/apisix/admin/routes/1  -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
 {
     "methods": ["POST"],
     "uri": "/helloworld.Greeter/SayHello",
diff --git a/t/router/radixtree-host-uri.t b/t/router/radixtree-host-uri.t
index f80e3eb..b0eb66b 100644
--- a/t/router/radixtree-host-uri.t
+++ b/t/router/radixtree-host-uri.t
@@ -35,6 +35,7 @@ our $yaml_config = read_file("conf/config.yaml");
 $yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
 $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
 $yaml_config =~ s/http: 'radixtree_uri'/http: 'radixtree_host_uri'/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
 
 run_tests();
 
diff --git a/t/router/radixtree-host-uri2.t b/t/router/radixtree-host-uri2.t
index 1c7c3c3..358ff12 100644
--- a/t/router/radixtree-host-uri2.t
+++ b/t/router/radixtree-host-uri2.t
@@ -37,6 +37,7 @@ $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
 $yaml_config =~ s/config_center: etcd/config_center: yaml/;
 $yaml_config =~ s/enable_admin: true/enable_admin: false/;
 $yaml_config =~ s/http: 'radixtree_uri'/http: 'radixtree_host_uri'/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
 
 run_tests();
 
diff --git a/t/router/radixtree-uri-host.t b/t/router/radixtree-uri-host.t
index cefe0a0..9faa508 100644
--- a/t/router/radixtree-uri-host.t
+++ b/t/router/radixtree-uri-host.t
@@ -34,6 +34,7 @@ sub read_file($) {
 our $yaml_config = read_file("conf/config.yaml");
 $yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
 $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
 
 run_tests();
 
diff --git a/t/router/radixtree-uri-multiple.t b/t/router/radixtree-uri-multiple.t
index f591fd7..565f9de 100644
--- a/t/router/radixtree-uri-multiple.t
+++ b/t/router/radixtree-uri-multiple.t
@@ -34,6 +34,7 @@ sub read_file($) {
 our $yaml_config = read_file("conf/config.yaml");
 $yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
 $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
 
 run_tests();
 
diff --git a/t/router/radixtree-uri-priority.t b/t/router/radixtree-uri-priority.t
index efae88c..6dc8f55 100644
--- a/t/router/radixtree-uri-priority.t
+++ b/t/router/radixtree-uri-priority.t
@@ -34,6 +34,7 @@ sub read_file($) {
 our $yaml_config = read_file("conf/config.yaml");
 $yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
 $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
 
 run_tests();
 
diff --git a/t/router/radixtree-uri-sanity.t b/t/router/radixtree-uri-sanity.t
index d34ecbc..3bfaa43 100644
--- a/t/router/radixtree-uri-sanity.t
+++ b/t/router/radixtree-uri-sanity.t
@@ -34,6 +34,7 @@ sub read_file($) {
 our $yaml_config = read_file("conf/config.yaml");
 $yaml_config =~ s/node_listen: 9080/node_listen: 1984/;
 $yaml_config =~ s/enable_heartbeat: true/enable_heartbeat: false/;
+$yaml_config =~ s/admin_key:/admin_key_useless:/;
 
 run_tests();