文档

jwt-auth插件

更新时间:

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

插件类型

认证鉴权。

配置字段

名称

数据类型

填写要求

默认值

描述

consumers

array of object

必填。

-

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

_rules_

array of object

选填。

-

配置特定路由或域名的访问权限列表,用于对请求进行鉴权。

子项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_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

    缓存时间,单位是毫秒

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

名称

数据类型

填写要求

默认值

描述

_match_route_

array of string

选填。_match_route__match_domain_选填一项。

-

配置要匹配的路由名称。

_match_domain_

array of string

选填。_match_route__match_domain_选填一项。

-

配置要匹配的域名。

_disable_

bool

选填

false

默认插件功能启用。当设置为true时,插件功能不启用。

allow

array of string

必填。

-

对于符合匹配条件的请求,配置允许访问的consumer名称。

说明
  • 若不配置_rules_字段,则默认对当前网关实例的所有路由开启认证。

  • 对于通过认证鉴权的请求,请求的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"
        }
      ]
    }
# 使用 _rules_ 字段进行细粒度规则配置
_rules_:
# 规则一:按路由名称匹配生效
- _match_route_:
  - route-a
  - route-b
  allow:
  - consumer1
# 规则二:按域名匹配生效
- _match_domain_:
  - "*.example.com"
  - test.com
  allow:
  - consumer2
说明
  • _match_route_中指定的route-aroute-b即在创建网关路由时填写的路由名称,当匹配到这两个路由时,将允许nameconsumer1的调用者访问,其他调用者不允许访问。

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

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

    • 将JWT设置在URL参数中。

      curl  'http://xxx.hello.com/test?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.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"
        }
      ]
    }
# 使用 _rules_ 字段进行细粒度规则配置
_rules_:
# 按路由名称匹配,关闭插件功能
- _match_route_:
  - route-b
  _disable_: true

此例_match_route_中指定的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"
        }
      ]
    }
# 使用 _rules_ 字段进行细粒度规则配置
_rules_:
# 规则一:按路由名称匹配,关闭插件功能
- _match_route_:
  - route-b
  _disable_: true
# 规则二:按域名匹配生效
- _match_domain_:
  - "*.example.com"
  allow:
  - consumer1
  - consumer2

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

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

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

相关错误码

HTTP状态码

出错信息

原因说明

401

Jwt missing

请求头未提供JWT。

401

Jwt expired

JWT已经过期。

401

Jwt verification fails

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

403

Access Denied

无权限访问当前路由。