使用Kong的JWT插件

Kong的JWT插件介绍

官方文档: https://docs.konghq.com/hub/kong-inc/jwt/

需要先详细阅读该文档.

需要注意的几点:

  • 用户的基础信息和权限信息存储在kong本地的数据库中, 我们可以写一个后台系统通过调用kong提供的管理api来管理这些用户信息.

  • 每个用户都有keyseceret字段, key表示JWTpayload字段中的签发者, seceret表示用于生成JWT第三个字段(签名)的密钥.

  • JWT插件只验证JWT合法性, 不签发JWT, 但是提供用于签发JWT所需的seceret、 签发者(key)、用户信息等的API.

    # {consumer}可以是用户名或者是用户ID
    curl -X GET http://kong:8001/consumers/{consumer}/jwt

    输出:

    {
    "data": [
        {
            "consumer_id": "39f52333-9741-48a7-9450-495960d91684",
            "id": "3239880d-1de5-4dbc-bccf-78f7a4280f33",
            "created_at": 1491430568000,
            "key": "c5a55906cc244f483226e02bcff2b5e",
            "algorithm": "RS256",
            "secret": "b0970f7fc9564e65xklfn48930b5d08b1"
        }
    ],
    "total": 1
    }
  • 签发JWT的环节我们可以自己选择:

    • 可以在kong上写一个插件用于签发JWT
    • 可以在后端签发JWT
    • 可以在前端签发JWT(安全问题, 不推荐)

JWT鉴权方案

企业内部管理系统

VUE -> LDAP -> KONG -> 各种后端API

签发JWT的环节可以在KONG上, 也可以在后端服务上.

大概流程介绍:

  1. 用户输入用户名和密码, VUE通过LDAP进行认证, 成功则拿到用户基础信息, 表明基础认证成功.

  2. 然后携带用户信息请求:

    • KONG上的用于签发JWT的接口(lua插件实现).
    • 或者某个后端接口, 该接口也可以接入kong, 但kong不做鉴权.
  3. 签发JWT和返回用户目录权限信息:

    • 签发JWT的环节在KONG上的情况: 该Lua接口从kong的数据库中取出用户的key(签发者)和secret(密钥), 结合用户名、过期时间等信息签发JWT, 同时该接口从数据库中拿到用户的目录权限等信息, 以JSON格式统一响应给VUE.
    • 签发JWT的环节在后端服务的情况: 后端从KONG提供的接口获取上述信息, 以JSON格式统一响应给VUE.
  4. VUE拿到JWT, 将JWT写入到浏览器本地的localstoragecookie, 同时根据拿到的用户目录权限信息展示该用户拥有权限的前端页面.

  5. VUE在请求其他后端接口的时候可以通过url参数和Authorization头携带JWT, 也可以通过cookie来携带JWT(KONG默认没有开启从cookie读取jwt, 可配置).

  6. Kong接收到请求, 如果请求的api开启了JWT, 则会进行jwt校验, 签名校验和过期时间校验都通过后将转发该api到相应的后端服务.

注意:

  1. 不管KONG上是否签发JWT, KONG上的用户信息和权限管理都应该由我们的企业内部管理系统上的用户权限模块管理. 简单方便, 相当于我们使用KONG提供的管理api重新写了一个用户权限管理系统前端, 操作的还是KONG的数据库.

  2. 验证JWT是否过期也可以在VUE处先做了, 但还是建议在后端做, 因为可以加入一些其他的逻辑, 比如额外引入Redis来做用户登录过期判断, 从而可以将JWT的过期时间设置的比较短, 提高安全性.

对外Web应用

VUE -> KONG -> 各种后端API

整体流程和上述一致, 说一下不一样的地方.

  • 不需要LDAP认证, 多了一个用户注册环节.

  • 用户管理在后端服务上做(操作的还是KONG的数据), 包括签发JWT.