jwt-auth插件

jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能,支持从HTTP请求的URL参数、请求头、Cookie字段解析JWT,同时验证该Token是否有权限访问。相较于配置JWT认证鉴权,jwt-auth插件额外提供了调用方身份识别的能力,支持对不同调用方配置不同的JWT凭证。本文介绍如何配置jwt-auth插件。

插件类型

认证鉴权。

配置字段

认证配置

名称

数据类型

填写要求

默认值

描述

consumers

array of object

必填

-

配置服务的调用者,用于对请求进行认证。

global_auth

array of string

选填(仅实例级别配置)

-

只能在实例级别配置,若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制,若不配置则仅当没有域名和路由配置时全局生效(兼容老用户使用习惯)。

子项consumers中的每一项配置字段说明如下。

名称

数据类型

填写要求

默认值

描述

name

string

必填

-

配置该consumer的名称。

jwks

string

选填。jwks和remote_jwks必填一个。

-

JSON Web Key (JWK)指定的JSON格式字符串,是由验证JWT中签名的公钥(或对称密钥)组成的JSON Web Key Set。

remote_jwks

object

选填。jwks和remote_jwks二选一。

{"uri":"http://127.0.0.1/keys","service":"test.static","port":"80","ttl":30000,"timeout":3000}

用于从指定服务的指定URI定时拉取JWKS,和JWKS字段同时配置时,以此字段配置拉取的JWKS优先。

issuer

string

选填

-

JWT的签发者,需要和payload中的iss字段保持一致。

claims

object

选填

-

key/value分别对应payload中的key/value,可以用于校验多个字段是否和payload中一致,例如配置aud: mobile-site,则要求payload中的aud必须是mobile-site。

claims_to_headers

array of object

选填

-

抽取JWT的payload中指定字段,设置到指定的请求头中,然后转发给后端。

from_headers

array of object

选填

[{"name":"Authorization","value_prefix":"Bearer"}]

从指定的请求头中抽取JWT。

from_params

array of string

选填

access_token

从指定的URL参数中抽取JWT。

from_cookies

array of string

选填

-

从指定的cookie中抽取JWT。

clock_skew_seconds

number

选填

60

校验JWT的exp和iat字段时允许的时钟偏移量,单位为秒。

keep_token

bool

选填

true

转发给后端时是否保留JWT。

说明

只有当from_headersfrom_paramsfrom_cookies均未配置时,才会使用默认值。

  • from_headers中每一项的配置字段说明如下。

    名称

    数据类型

    填写要求

    默认值

    描述

    name

    string

    必填

    -

    抽取JWT的请求Header。

    value_prefix

    string

    必填

    -

    对请求Header的value去除此前缀,剩余部分作为JWT。

  • claims_to_headers中每一项的配置字段说明如下。

    名称

    数据类型

    填写要求

    默认值

    描述

    claim

    string

    必填

    -

    JWT payload中的指定字段,要求必须是字符串或无符号整数类型。

    header

    string

    必填

    -

    从payload取出字段的值设置到这个请求头中,转发给后端。

    override

    bool

    选填

    true

    • true时,存在同名请求头会进行覆盖。

    • false时,追加同名请求头。

  • remote_jwks中每一项的配置字段说明如下。

    名称

    数据类型

    填写要求

    默认值

    描述

    uri

    string

    必填

    -

    请求URL。

    service

    string

    必填

    -

    • K8s服务填写示例:foo.default.svc.cluster.local。

    • Nacos服务填写示例:foo.DEFAULT-GROUP.public.nacos。

    • 如果是名为test的DNS服务,则填写test.dns。

    • 如果是名为test的静态IP服务,则填写test.static。

    port

    bool

    必填

    -

    服务端口

    timeout

    bool

    选填

    3000

    服务请求超时时间,单位是毫秒

    ttl

    bool

    选填

    30000

    缓存时间,单位是毫秒。

鉴权配置(非必需)

名称

数据类型

填写要求

默认值

描述

allow

array of string

选填(非实例级别配置)

-

只能在路由或域名等细粒度规则上配置,对于符合匹配条件的请求,配置允许访问的 consumer,从而实现细粒度的权限控制。

重要
  • 在一个规则里,鉴权配置和认证配置不可同时存在。

  • 对于通过认证鉴权的请求,请求的Header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

配置示例

全局配置认证和路由粒度进行鉴权

以下配置将对网关特定路由或域名开启JWT Auth认证和鉴权。

说明

如果一个JWT能匹配多个jwks,则按照配置顺序命中第一个匹配的consumer。

在实例级别做如下插件配置:

consumers:
- name: consumer1
  issuer: abcd
  jwks: |
    {
      "keys": [
        {
          "kty": "oct",
          "kid": "123",
          "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
          "alg": "HS256"
        }
      ]
    }
- name: consumer2
  issuer: abc
  jwks: |
    {
      "keys": [
        {
          "kty": "RSA",
          "e": "AQAB",
          "use": "sig",
          "kid": "123",
          "alg": "RS256",
          "n": "i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw"
        }
      ]
    }

route-aroute-b两个路由做如下插件配置:

allow:
- consumer1

*.example.comtest.com两个域名做如下插件配置:

allow:
- consumer2
说明
  • 此例指定的route-aroute-b即在创建网关路由时填写的路由名称,当匹配到这两个路由时,将允许nameconsumer1的调用者访问,其他调用者不被允许访问。

  • 此例指定的*.example.comtest.com用于匹配请求的域名,当发现域名匹配时,将允许nameconsumer2的调用者访问,其他调用者不被允许访问。

根据该配置,允许访问以下请求。假设以下请求会匹配到route-a这条路由。

  • 将JWT设置在URL参数中。

    curl  'http://xxx.hello.com/test?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEy****.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'
  • 将JWT设置在HTTP请求头中。

    curl  http://xxx.hello.com/test -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

认证鉴权通过后,请求的Header中会被添加一个X-Mse-Consumer字段,在此例中其值为consumer1,用以标识调用方的名称。

下列请求将拒绝访问。

  • 请求未提供JWT,返回401。

    curl  http://xxx.hello.com/test
  • 根据请求提供的JWT匹配到的调用者无访问权限,返回403。

    # consumer1不在*.example.com的allow列表里
    curl  'http://xxx.example.com/test' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

网关实例级别开启,但特定路由关闭

在实例级别做如下插件配置:

global_auth: true
consumers:
- name: consumer1
  issuer: abcd
  jwks: |
    {
      "keys": [
        {
          "kty": "oct",
          "kid": "123",
          "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
          "alg": "HS256"
        }
      ]
    }
- name: consumer2
  issuer: abc
  jwks: |
    {
      "keys": [
        {
          "kty": "RSA",
          "e": "AQAB",
          "use": "sig",
          "kid": "123",
          "alg": "RS256",
          "n": "i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw"
        }
      ]
    }

route-b路由做如下插件配置:

_disable_: true

此例route-b即在创建网关路由时填写的路由名称。因为_disable_设置为true,当匹配到这个路由时,将关闭此插件功能,不进行JWT认证,所有人均可访问。

当没有匹配到route-b路由时,因为全局配置中global_auth设置为了true,表明对所有请求开启认证,所以将进行JWT认证,并且允许consumer1consumer2都能访问。

域名级别开启,但特定路由关闭

在实例级别做如下插件配置:

consumers:
- name: consumer1
  issuer: abcd
  jwks: |
    {
      "keys": [
        {
          "kty": "oct",
          "kid": "123",
          "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
          "alg": "HS256"
        }
      ]
    }
- name: consumer2
  issuer: abc
  jwks: |
    {
      "keys": [
        {
          "kty": "RSA",
          "e": "AQAB",
          "use": "sig",
          "kid": "123",
          "alg": "RS256",
          "n": "i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw"
        }
      ]
    }

route-b路由做如下插件配置:

_disable_: true

*.example.com域名做如下插件配置:

allow:
- consumer1
- consumer2

此例中route-b即在创建网关路由时填写的路由名称。因为_disable_设置为true,当匹配到这个路由时,将关闭此插件功能,不进行JWT认证,所有人均可访问。

此例中指定的*.example.com用于匹配请求的域名。当发现域名匹配时,将允许nameconsumer1consumer2的调用者访问,其他调用者不允许访问。

配置规则顺序会依次执行匹配,有任一规则匹配到,就会执行对应配置,不再匹配其他规则。因为这里配置路由匹配优先级高于域名,即对当前配置的域名生效,而对域名下的特定路由关闭。

相关错误码

HTTP状态码

出错信息

原因说明

401

Jwt missing

请求头未提供JWT。

401

Jwt expired

JWT已经过期。

401

Jwt verification fails

JWT payload校验失败,如iss不匹配。

403

Access Denied

无权限访问当前路由。