key-authentication
https://getkong.org/plugins/key-authentication
我们演示还是用books 的Restful api数据接口,把Kong Gateway - 01范例中PostgresSQL中的kong数据库删掉,
(参看安装篇 How to Install kong-community-edition On Cent OS 7)
[root@contoso ~]# pg_dump --help[root@contoso ~]# psql --help
[root@contoso ~]# dropdb --help
[root@contoso ~]# createdb --help
[root@contoso ~]# kong stop # kong 服务必须先停止运行
[root@contoso ~]# dropdb -h 127.0.0.1 -p 5432 -U postgres kong # 删除kong数据库
Password: 123456
[root@contoso ~]# createdb -h 127.0.0.1 -p 5432 -U postgres kong # 创建kong数据库
Password: 123456
[root@contoso ~]# psql -h 127.0.0.1 -p 5432 -U postgres -d kong < /opt/kong-20180427.bak # 恢复kong数据库
Password for user postgres: 123456
[root@contoso ~]# kong start
Kong started
用Kong配置一个books服务
在安装并启动Kong之后,使用Kong的管理API端口8001添加一个名称为books的服务
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/services/ \
--data 'name=books' \
--data 'url=http://contoso.com/v1/books'
HTTP/1.1 201 Created Date: Wed, 02 May 2018 14:37:44 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "host": "contoso.com", "created_at": 1525243064, "connect_timeout": 60000, "id": "8f0179f0-5d88-41ed-98d1-476e041c222e", "protocol": "http", "name": "books", "read_timeout": 60000, "port": 80, "path": "/v1/books", "updated_at": 1525243064, "retries": 5, "write_timeout": 60000 }
添加一个路由(仅支持GET请求,paths[]的值必须与books服务中的/v1/books一致)
使books服务暴露出来以供用户访问,books服务可以添加多个路由。
paths[]=/v1/books 匹配的路由地址以http://contoso.com/v1/books开头的任何地址
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/services/books/routes \
--data 'hosts[]=contoso.com' \
--data 'paths[]=/v1/books' \
--data 'methods[]=GET'
HTTP/1.1 201 Created Date: Wed, 02 May 2018 14:37:58 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "created_at": 1525243078, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243078, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "GET" ], "protocols": [ "http", "https" ], "id": "d9a29df3-c3ae-419c-97bb-1dc97efd0f01" }添加一个路由(仅支持POST请求,paths[]的值必须与books服务中的/v1/books一致)
使books服务暴露出来以供用户访问,books服务可以添加多个路由。
paths[]=/v1/books 匹配的路由地址以http://contoso.com/v1/books开头的任何地址
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/services/books/routes \
--data 'hosts[]=contoso.com' \
--data 'paths[]=/v1/books' \
--data 'methods[]=POST'
HTTP/1.1 201 Created Date: Wed, 02 May 2018 14:38:12 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "created_at": 1525243092, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243092, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "POST" ], "protocols": [ "http", "https" ], "id": "e32ade69-3052-4ef0-9e4f-34d8977797cd" }添加一个路由(仅支持PUT请求,paths[]的值必须与books服务中的/v1/books一致)
使books服务暴露出来以供用户访问,books服务可以添加多个路由。
paths[]=/v1/books 匹配的路由地址以http://contoso.com/v1/books开头的任何地址
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/services/books/routes \
--data 'hosts[]=contoso.com' \
--data 'paths[]=/v1/books' \
--data 'methods[]=PUT'
HTTP/1.1 201 Created Date: Wed, 02 May 2018 14:38:23 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "created_at": 1525243103, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243103, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "PUT" ], "protocols": [ "http", "https" ], "id": "439bf1de-1de1-4bf7-b666-199d43a35be3" }
添加一个路由(仅支持DELETE请求,paths[]的值必须与books服务中的/v1/books一致)
使books服务暴露出来以供用户访问,books服务可以添加多个路由。
paths[]=/v1/books 匹配的路由地址以http://contoso.com/v1/books开头的任何地址
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/services/books/routes \
--data 'hosts[]=contoso.com' \
--data 'paths[]=/v1/books' \
--data 'methods[]=DELETE'
HTTP/1.1 201 Created Date: Wed, 02 May 2018 14:38:34 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "created_at": 1525243114, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243114, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "DELETE" ], "protocols": [ "http", "https" ], "id": "c59ea8be-0a79-42ee-81fc-620377eff4ab" }
重新初始化数据库books表
[root@contoso ~]# mysql -h127.0.0.1 -uroot -p123456 Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 42 Server version: 10.2.12-MariaDB-log MariaDB Server Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> use bookstore Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed MariaDB [bookstore]> SELECT * FROM books; +----+-----------------+-----------+ | id | title | author | +----+-----------------+-----------+ | 1 | TiDB in Action | Joe Brown | | 4 | Redis in Action | Jack Chen | | 5 | Fashion China | Joe Brown | +----+-----------------+-----------+ 3 rows in set (0.00 sec) MariaDB [bookstore]> DELETE FROM books; Query OK, 3 rows affected (0.01 sec) MariaDB [bookstore]> insert into `books` (`id`, `title`, `author`) values('1','Fashion That Changed the World','Jennifer Croll'); Query OK, 1 row affected (0.00 sec) MariaDB [bookstore]> insert into `books` (`id`, `title`, `author`) values('2','Brigitte Bardot - My Life in Fashion','Henry-Jean Servat and Brigitte Bardot'); Query OK, 1 row affected (0.00 sec) MariaDB [bookstore]> insert into `books` (`id`, `title`, `author`) values('3','The Fashion Image','Thomas Werner'); Query OK, 1 row affected (0.00 sec) MariaDB [bookstore]> SELECT * FROM books; +----+--------------------------------------+---------------------------------------+ | id | title | author | +----+--------------------------------------+---------------------------------------+ | 1 | Fashion That Changed the World | Jennifer Croll | | 2 | Brigitte Bardot - My Life in Fashion | Henry-Jean Servat and Brigitte Bardot | | 3 | The Fashion Image | Thomas Werner | +----+--------------------------------------+---------------------------------------+ 3 rows in set (0.00 sec) MariaDB [bookstore]>通过Kong在8000端口暴露出来的服务地址获得所有的书籍
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8000/v1/books \
--header 'Host: contoso.com'
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 244 Connection: keep-alive Date: Wed, 02 May 2018 15:09:20 GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.1.13 X-Powered-By: PHP/7.1.13 X-Kong-Upstream-Latency: 29 X-Kong-Proxy-Latency: 59 Via: kong/0.13.1 [ { "id": 1, "title": "Fashion That Changed the World", "author": "Jennifer Croll" }, { "id": 2, "title": "Brigitte Bardot - My Life in Fashion", "author": "Henry-Jean Servat and Brigitte Bardot" }, { "id": 3, "title": "The Fashion Image", "author": "Thomas Werner" } ]通过Kong在8000端口暴露出来的服务地址获得id=3的书籍
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8000/v1/books/3 \
--header 'Host: contoso.com'
[ { "id": 3, "title": "The Fashion Image", "author": "Thomas Werner" } ]
通过Kong在8000端口暴露出来的服务地址新增一条书籍记录
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8000/v1/books \
--data-urlencode 'title=Fashion China' \
--data-urlencode 'author=Joe Brown' \
--header 'Host: contoso.com'
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 35 Connection: keep-alive Date: Wed, 02 May 2018 15:09:48 GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.1.13 X-Powered-By: PHP/7.1.13 X-Kong-Upstream-Latency: 32 X-Kong-Proxy-Latency: 45 Via: kong/0.13.1 {"message":"inserted successfully"}
通过Kong在8000端口暴露出来的服务地址修改一条书籍记录
[root@contoso ~]# curl -i -X PUT \
--url http://localhost:8000/v1/books \
--data-urlencode 'id=1' \
--data-urlencode 'title=TiDB in Action' \
--data-urlencode 'author=Joe Brown' \
--header 'Host: contoso.com'
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 34 Connection: keep-alive Date: Wed, 02 May 2018 15:10:04 GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.1.13 X-Powered-By: PHP/7.1.13 X-Kong-Upstream-Latency: 29 X-Kong-Proxy-Latency: 26 Via: kong/0.13.1 {"message":"updated successfully"}
通过Kong在8000端口暴露出来的服务地址删除一条书籍记录
--url http://localhost:8000/v1/books/3 \
--header 'Host: contoso.com'
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 34 Connection: keep-alive Date: Wed, 02 May 2018 15:10:20 GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.1.13 X-Powered-By: PHP/7.1.13 X-Kong-Upstream-Latency: 31 X-Kong-Proxy-Latency: 34 Via: kong/0.13.1 {"message":"deleted successfully"}使用Kong的管理端口8001查询所有已经添加路由配置信息列表
返回每条信息中的id(也就是route_id)值,随后我们会用到这些id来配置Key验证
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8001/services/books/routes
HTTP/1.1 200 OK Date: Wed, 02 May 2018 15:30:52 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "next": null, "data": [ { "created_at": 1525243103, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243103, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "PUT" ], "protocols": [ "http", "https" ], "id": "439bf1de-1de1-4bf7-b666-199d43a35be3" // route_id = id }, { "created_at": 1525243114, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243114, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "DELETE" ], "protocols": [ "http", "https" ], "id": "c59ea8be-0a79-42ee-81fc-620377eff4ab" // route_id = id }, { "created_at": 1525243078, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243078, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "GET" ], "protocols": [ "http", "https" ], "id": "d9a29df3-c3ae-419c-97bb-1dc97efd0f01" // route_id = id }, { "created_at": 1525243092, "strip_path": true, "hosts": [ "contoso.com" ], "preserve_host": false, "regex_priority": 0, "updated_at": 1525243092, "paths": [ "/v1/books" ], "service": { "id": "8f0179f0-5d88-41ed-98d1-476e041c222e" }, "methods": [ "POST" ], "protocols": [ "http", "https" ], "id": "e32ade69-3052-4ef0-9e4f-34d8977797cd" // route_id = id } ] }为route_id="d9a29df3-c3ae-419c-97bb-1dc97efd0f01"的这条路由(即GET书籍的路由),启用key-auth验证插件
注意链接http://localhost:8001/routes/{route_id}/plugins中的{route_id}对应路由操作,别搞错了对应关系
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/routes/d9a29df3-c3ae-419c-97bb-1dc97efd0f01/plugins \
--data "name=key-auth"
HTTP/1.1 201 Created Date: Wed, 02 May 2018 15:47:12 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "created_at": 1525276033000, "config": { "key_in_body": false, "run_on_preflight": true, "anonymous": "", "hide_credentials": false, "key_names": [ "apikey" ] }, "id": "1187a6d9-91e3-489d-a8fd-6b3687901c73", "enabled": true, "route_id": "d9a29df3-c3ae-419c-97bb-1dc97efd0f01", "name": "key-auth" }通过Kong在8000端口暴露出来的服务地址读一条书籍记录,
实际上是通过Kong在转发我的请求,不管是读1条记录还读所有书籍记录,我们都无权获得数据
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8000/v1/books/3 \
--header 'Host: contoso.com'
HTTP/1.1 401 Unauthorized Date: Wed, 02 May 2018 15:51:27 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive WWW-Authenticate: Key realm="kong" Server: kong/0.13.1 {"message":"No API key found in request"}
[root@contoso ~]# curl -i -X GET \ --url http://localhost:8000/v1/books \ --header 'Host: contoso.com' HTTP/1.1 401 Unauthorized Date: Wed, 02 May 2018 15:54:59 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive WWW-Authenticate: Key realm="kong" Server: kong/0.13.1 {"message":"No API key found in request"}创建1个username=cathy的消费者
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/consumers \
--data "username=cathy"
HTTP/1.1 201 Created Date: Wed, 02 May 2018 16:06:11 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "created_at": 1525277171000, "username": "cathy", "id": "2aeb2af4-3cd0-4ca2-86bb-dee75c745163" }创建1个username=jack且custom_id=abc123的消费者
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/consumers \
--data 'username=jack' \
--data "custom_id=abc123"
HTTP/1.1 201 Created Date: Wed, 02 May 2018 16:06:25 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "custom_id": "abc123", "created_at": 1525277185000, "username": "jack", "id": "17945134-3eb8-4f62-945b-8c4063907f52" }创建1个custom_id=456789的消费者
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/consumers \
--data 'custom_id=456789'
HTTP/1.1 201 Created Date: Wed, 02 May 2018 16:06:33 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "custom_id": "456789", "created_at": 1525277194000, "id": "e2c7bab7-5bd2-4618-9c7d-21fe18aac367" }使用Kong的管理端口8001查询所有已经添加消费者信息列表
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8001/consumers
HTTP/1.1 200 OK Date: Wed, 02 May 2018 16:06:43 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "total": 3, "data": [ { "custom_id": "abc123", "created_at": 1525277185000, "username": "jack", "id": "17945134-3eb8-4f62-945b-8c4063907f52" }, { "created_at": 1525277171000, "username": "cathy", "id": "2aeb2af4-3cd0-4ca2-86bb-dee75c745163" }, { "custom_id": "456789", "created_at": 1525277194000, "id": "e2c7bab7-5bd2-4618-9c7d-21fe18aac367" } ] }创建一个Key,一个消费者可以定义多个Key值
http://kong:8001/consumers/{consumer}/key-auth
其中{consumer}即可以是消费者的username也可以是消费者的custom_id值
随机的方式生成1个key值
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/consumers/cathy/key-auth \
--data ""
HTTP/1.1 201 Created Date: Wed, 02 May 2018 16:39:17 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "id": "a65174e4-70cb-4fc1-b883-85fde4d3d19c", "created_at": 1525279157000, "key": "H1z8iEjayL1yluE34yLxObcUrHdgwfm7", "consumer_id": "2aeb2af4-3cd0-4ca2-86bb-dee75c745163" }指定值方式给key一个值
[root@contoso ~]# curl -i -X POST \
--url http://localhost:8001/consumers/cathy/key-auth \
--data "key=abcd1234"
HTTP/1.1 201 Created Date: Wed, 02 May 2018 16:39:45 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "id": "a5595b4d-1de0-4077-8b13-bc1f60614051", "created_at": 1525279186000, "key": "abcd1234", "consumer_id": "2aeb2af4-3cd0-4ca2-86bb-dee75c745163" }使用消费者的key值访问Kong的8000端口暴露出来的服务
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8000/v1/books/2 \
--header 'Host: contoso.com' \
--header 'apikey: H1z8iEjayL1yluE34yLxObcUrHdgwfm7'
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 106 Connection: keep-alive Date: Wed, 02 May 2018 17:11:04 GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.1.13 X-Powered-By: PHP/7.1.13 X-Kong-Upstream-Latency: 26 X-Kong-Proxy-Latency: 0 Via: kong/0.13.1 [ { "id": 2, "title": "Brigitte Bardot - My Life in Fashion", "author": "Henry-Jean Servat and Brigitte Bardot" } ]使用消费者的key值访问Kong的8000端口暴露出来的服务
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8000/v1/books/2 \
--header 'Host: contoso.com' \
--header 'apikey: abcd1234'
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 106 Connection: keep-alive Date: Wed, 02 May 2018 17:12:51 GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.1.13 X-Powered-By: PHP/7.1.13 X-Kong-Upstream-Latency: 26 X-Kong-Proxy-Latency: 5 Via: kong/0.13.1 [ { "id": 2, "title": "Brigitte Bardot - My Life in Fashion", "author": "Henry-Jean Servat and Brigitte Bardot" } ]使用Kong的管理端口8001去删除一个消费者的key
链接http://localhost:8001/consumers/{consumer}/key-auth/{id}其中
{consumer}表示消费者的id或者username,{id}表示生成key时生成id值
[root@contoso ~]# curl -i -X DELETE \
--url http://localhost:8001/consumers/cathy/key-auth/a5595b4d-1de0-4077-8b13-bc1f60614051
HTTP/1.1 204 No Content Date: Wed, 02 May 2018 17:50:55 GMT Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 [root@contoso ~]#消费者的apikey分页
[root@contoso ~]# curl -i -X GET \
--url http://localhost:8001/key-auths
HTTP/1.1 200 OK Date: Wed, 02 May 2018 18:04:38 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 { "total": 1, "data": [ { "id": "a65174e4-70cb-4fc1-b883-85fde4d3d19c", "created_at": 1525279157000, "key": "H1z8iEjayL1yluE34yLxObcUrHdgwfm7", // apikey = key "consumer_id": "2aeb2af4-3cd0-4ca2-86bb-dee75c745163" } ] }通过key或者id来获得消费者
http://localhost:8001/key-auths/{key or id}/consumer
其中{key}是随机生成的key值或者自定义的key值
{id}值与{key}值在同一条数据里
我们使用id = a65174e4-70cb-4fc1-b883-85fde4d3d19c的方式获得消费者
[root@contoso ~]# curl -i -X GET http://localhost:8001/key-auths/a65174e4-70cb-4fc1-b883-85fde4d3d19c/consumer
HTTP/1.1 200 OK Date: Thu, 03 May 2018 05:29:52 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 {"created_at":1525277171000,"username":"cathy","id":"2aeb2af4-3cd0-4ca2-86bb-dee75c745163"}我们使用key = H1z8iEjayL1yluE34yLxObcUrHdgwfm7的方式获得消费者
[root@contoso ~]# curl -i -X GET http://localhost:8001/key-auths/H1z8iEjayL1yluE34yLxObcUrHdgwfm7/consumer
HTTP/1.1 200 OK Date: Thu, 03 May 2018 05:31:13 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Server: kong/0.13.1 {"created_at":1525277171000,"username":"cathy","id":"2aeb2af4-3cd0-4ca2-86bb-dee75c745163"}