lua-resty-jwt

适用于 OpenResty 的 JWT

$ opm get toopy/lua-resty-jwt

免责声明

如 https://github.com/SkyLothar/lua-resty-jwt/issues/85 中所述,此项目是 @SkyLothar 的 https://github.com/SkyLothar/lua-resty-jwt 的分支,现已得到所有相关方的采用,包括

---

名称

lua-resty-jwt - ngx_lua 和 LuaJIT 的 JWT

[!构建状态](https://travis-ci.org/cdbattags/lua-resty-jwt)

注意 :exclamation: 这里使用的 hmac 库是 lua-resty-hmac,而不是 luarocks 中的库。

安装

  • opm: opm get cdbattags/lua-resty-jwt

  • luarocks: luarocks install lua-resty-jwt

  • 前往 发布页面 并下载 tar.gz

版本

0.2.3

状态

此库处于积极开发中,但被认为已准备好投入生产。

描述

此库需要使用 OpenSSL 构建的 nginx、ngx_lua 模块LuaJIT 2.0lua-resty-hmaclua-resty-string

概要

        # nginx.conf:
    
        lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";
    
        server {
            default_type text/plain;
            location = /verify {
                content_by_lua '
                    local cjson = require "cjson"
                    local jwt = require "resty.jwt"
    
                    local jwt_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" ..
                        ".eyJmb28iOiJiYXIifQ" ..
                        ".VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY"
                    local jwt_obj = jwt:verify("lua-resty-jwt", jwt_token)
                    ngx.say(cjson.encode(jwt_obj))
                ';
            }
            location = /sign {
                content_by_lua '
                    local cjson = require "cjson"
                    local jwt = require "resty.jwt"
    
                    local jwt_token = jwt:sign(
                        "lua-resty-jwt",
                        {
                            header={typ="JWT", alg="HS256"},
                            payload={foo="bar"}
                        }
                    )
                    ngx.say(jwt_token)
                ';
            }
        }

方法

要加载此库,

  1. 您需要在 ngx_lua 的 lua_package_path 指令中指定此库的路径。例如,lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";

  2. 您可以使用 require 将库加载到本地 Lua 变量中

        local jwt = require "resty.jwt"

签名

语法:local jwt_token = jwt:sign(key, table_of_jwt)

table_of_jwt 签名到 jwt_token

alg 参数指定要使用的哈希算法(HS256HS512RS256)。

table_of_jwt 示例

    {
        "header": {"typ": "JWT", "alg": "HS512"},
        "payload": {"foo": "bar"}
    }

验证

语法:local jwt_obj = jwt:verify(key, jwt_token [, claim_spec [, ...]])

验证 jwt_token 并返回 jwt_obj 表格。key 可以是预共享密钥(作为字符串),是一个函数,该函数接收一个参数(标头中 kid 的值),并为 kid 返回预共享密钥(作为字符串),如果 kid 查找失败则返回 nil。如果尝试为 key 指定一个函数并且标头中不存在 kid,则此调用将失败。

有关 claim_spec 参数格式的详细信息,请参阅 验证

加载和验证

    syntax: local jwt_obj = jwt:load_jwt(jwt_token)
    syntax: local verified = jwt:verify_jwt_obj(key, jwt_obj [, claim_spec [, ...]])


    verify = load_jwt +  verify_jwt_obj

加载 JWT,检查 kid,然后使用正确的密钥进行验证

jwt_obj 示例

    {
        "raw_header": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9",
        "raw_payload: "eyJmb28iOiJiYXIifQ",
        "signature": "wrong-signature",
        "header": {"typ": "JWT", "alg": "HS256"},
        "payload": {"foo": "bar"},
        "verified": false,
        "valid": true,
        "reason": "signature mismatched: wrong-signature"
    }

签名-JWE

语法:local jwt_token = jwt:sign(key, table_of_jwt)

table_of_jwt 签名到 jwt_token

alg 参数指定用于加密密钥的哈希算法(dirRSA-OAEP-256)。enc 参数指定用于加密有效负载的哈希算法(A128CBC-HS256A256CBC-HS512

table_of_jwt 示例

    {
        "header": {"typ": "JWE", "alg": "dir", "enc":"A128CBC-HS256"},
        "payload": {"foo": "bar"}
    }

验证

jwt:loadjwt:verify_jwt_obj 函数都将任何数量的可选 claim_spec 参数作为附加参数。claim_spec 只是一个声明和验证器的 Lua 表格。claim_spec 表格中的每个键都对应于有效负载中的匹配键,并且 validator 是一个将被调用的函数,以确定是否满足声明。

validator 函数的签名为

    function(val, claim, jwt_json)

其中 val 是正在测试的 jwt_obj 中声明的值(如果对象有效负载中不存在则为 nil),claim 是正在验证的声明的名称,jwt_json 是正在验证的对象的 JSON 序列化表示形式。如果函数不需要 claimjwt_json 参数,则可以省略它们。

validator 函数返回 truefalse。任何 validator 可以引发错误,验证将被视为失败,并且引发的错误将放入结果对象的 reason 字段中。如果 validator 没有返回任何内容(即 nil),则该函数被视为已成功 - 假设如果它失败则会引发错误。

可以使用名为 __jwt 的特殊声明,以便如果存在该声明的 validator 函数,则 validator 将使用整个已解析 JWT 对象的深拷贝作为 val 的值进行调用。这样您就可以为可能依赖于一个或多个声明的整个对象编写验证。

可以为 jwt:loadjwt:verify_jwt_obj 指定多个 claim_spec 表格 - 它们将按顺序执行。单个 claim_spec 内的各个 validator 的执行顺序没有保证。如果 claim_spec 失败,则任何后续的 claim_specs 将不会执行。

claim_spec 示例

    {
        sub = function(val) return string.match("^[a-z]+$", val) end,
        iss = function(val)
            for _, value in pairs({ "first", "second" }) do
                if value == val then return true end
            end
            return false
        end,
        __jwt = function(val, claim, jwt_json)
            if val.payload.foo == nil or val.payload.bar == nil then
                error("Need to specify either 'foo' or 'bar'")
            end
        end
    }

JWT 验证器

resty.jwt-validators 中存在一个有用的 validator 函数库。您可以通过包含以下内容来使用此库:

    local validators = require "resty.jwt-validators"

验证器库中当前定义了以下函数。标记为“(opt)”的表示存在名为 opt_<name> 的相同函数,该函数采用相同的参数。“opt”版本的函数如果键不存在于正在验证的 jwt_object 的有效负载中将返回 true,而非“opt”版本的函数如果键不存在于正在验证的 jwt_object 的有效负载中将返回 false。

validators.chain(...)

返回一个验证器,该验证器将给定的函数一个接一个地链接在一起 - 只要它们继续通过检查。

validators.required(chain_function)

返回一个验证器,如果值不存在则返回 false。如果值存在并且指定了 chain_function,则将返回 chain_function(val, claim, jwt_json) 的值,否则将返回 true。这允许指定一个值既是必需的并且必须匹配一些其他检查。

validators.require_one_of(claim_keys)

返回一个验证器,如果没有给定的声明键存在则会报错。预计此函数用于完整的 jwt 对象。claim_keys 必须是非空字符串表格。

validators.check(check_val, check_function, name, check_type) (opt)

返回一个验证器,该验证器检查对测试值和 check_val 调用给定的 check_function 的结果是否返回 true。check_valcheck_function 的值不能为 nil。可选的 name 用于错误消息,默认为“check_value”。可选的 check_type 用于确保检查类型匹配,默认为 type(check_val)。传递给 check_function 的第一个参数永远不会为 nil。如果 check_function 引发错误,则该错误将附加到错误消息中。

validators.equals(check_val) (opt)

返回一个验证器,该验证器检查值是否完全等于(使用 ==)给定的 check_value。check_val 的值不能为 nil。

validators.matches(pattern) (opt)

返回一个验证器,该验证器检查值是否与给定的模式匹配(使用 string.match)。pattern 的值必须是字符串。

validators.any_of(check_values, check_function, name, check_type, table_type) (opt)

返回一个验证器,该验证器对给定的 check_values 和测试值中的每一个调用给定的 check_function。如果这些调用中的任何一个返回 true,则此函数返回 truecheck_values 的值必须是非空表格,所有类型都相同,并且 check_function 的值不能为 nil。可选的 name 用于错误消息,默认为“check_values”。可选的 check_type 用于确保检查类型匹配,默认为 type(check_values[1]) - 表格类型。

validators.equals_any_of(check_values) (opt)

返回一个验证器,该验证器检查值是否完全等于给定的 check_values 中的任何一个。

validators.matches_any_of(patterns) (opt)

返回一个验证器,该验证器检查值是否与给定的 patterns 中的任何一个匹配。

validators.contains_any_of(check_values,name) (opt)

返回一个验证器,该验证器检查预期类型为 string 的值是否存在于给定的 check_values 中的任何一个中。check_values 的值必须是非空表格,所有类型都相同。可选的 name 用于错误消息,默认为 check_values

validators.greater_than(check_val) (opt)

返回一个验证器,该验证器检查值如何与给定的 check_value 进行比较(数值上,使用 >)。check_val 的值不能为 nil 并且必须是数字。

validators.greater_than_or_equal(check_val) (opt)

返回一个验证器,该验证器检查值如何与给定的 check_value 进行比较(数值上,使用 >=)。check_val 的值不能为 nil 并且必须是数字。

validators.less_than(check_val) (opt)

返回一个验证器,该验证器检查值如何与给定的 check_value 进行比较(数值上,使用 <)。check_val 的值不能为 nil 并且必须是数字。

validators.less_than_or_equal(check_val) (opt)

返回一个验证器,该验证器检查值如何与给定的 check_value 进行比较(数值上,使用 <=)。check_val 的值不能为 nil 并且必须是数字。

validators.is_not_before() (opt)

返回一个验证器,该验证器检查当前时间是否不在系统容差范围内之前测试值之前。这意味着

    val <= (system_clock() + system_leeway).

validators.is_not_expired() (opt)

返回一个验证器,该验证器检查当前时间是否不在系统容差范围内等于或在测试值之后。这意味着

    val > (system_clock() - system_leeway).

validators.is_at() (opt)

返回一个验证器,该验证器检查当前时间是否在系统容差范围内与测试值相同。这意味着

    val >= (system_clock() - system_leeway) and val <= (system_clock() + system_leeway).

validators.set_system_leeway(leeway)

用于设置 is_not_beforeis_not_expired 使用的容差(以秒为单位)的函数。默认为使用 0

validators.set_system_clock(clock)

用于设置 is_not_beforeis_not_expired 使用的系统时钟的函数。默认为使用 ngx.now

使用验证器的 claim_spec 示例

    local validators = require "resty.jwt-validators"
    local claim_spec = {
        sub = validators.opt_matches("^[a-z]+$),
        iss = validators.equals_any_of({ "first", "second" }),
        __jwt = validators.require_one_of({ "foo", "bar" })
    }

旧版/时间范围选项

为了支持使用此库的先前版本的代码,以及简化基于时间范围的 claim_specs 的指定,您可以使用 validation_options 表格代替任何单个 claim_spec 参数。参数应表示为键/值表格。表格的每个键都应从以下列表中选择。

使用旧版 validation_options 时,您只能指定这些选项。也就是说,您不能将旧版 validation_options 与其他 claim_spec 验证器混合使用。为了实现这一点,您必须为 jwt:load/jwt:verify_jwt_obj 函数指定多个选项。

  • lifetime_grace_period:定义以秒为单位的容差,以考虑生成 jwt 的服务器和验证它的服务器之间的时钟偏差。值应为零 (0) 或正整数。

**免责声明:**

如 https://github.com/SkyLothar/lua-resty-jwt/issues/85 中所述,此项目是 @SkyLothar 的 https://github.com/SkyLothar/lua-resty-jwt 的分支,现已得到所有相关方的采用,包括: - [zmartzone/lua-resty-openidc](https://github.com/zmartzone/lua-resty-openidc) - 用于 NGINX / OpenResty 的 Lua 中的 OpenID Connect 依赖方和 OAuth 2.0 资源服务器实现

---

# 名称

lua-resty-jwt - ngx_lua 和 LuaJIT 的 [JWT](http://self-issued.info/docs/draft-jones-json-web-token-01.html)

[![构建状态](https://img.shields.io/travis/cdbattags/lua-resty-jwt.svg?style=flat-square)](https://travis-ci.org/cdbattags/lua-resty-jwt)

**注意 :exclamation: 这里使用的hmac库是[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac),而不是luarocks中的库。**

# 安装

- opm: `opm get cdbattags/lua-resty-jwt` - luarocks: `luarocks install lua-resty-jwt` - 前往[发布页面](https://github.com/cdbattags/lua-resty-jwt/releases) 下载 `tar.gz`

# 版本

0.2.3

# 目录

* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [签名](#sign) * [验证](#verify) * [加载和验证](#load--verify) * [签名JWE](#sign-jwe) * [验证](#verification) * [JWT验证器](#jwt-validators) * [遗留/时间范围选项](#legacy-timeframe-options) * [示例](#examples) * [安装](#installation) * [使用Docker进行测试](#testing-with-docker) * [作者](AUTHORS.md) * [另请参阅](#see-also)

# 状态

此库处于积极开发中,但被认为已准备好投入生产。

# 描述

此库需要一个使用OpenSSL构建的nginx,[ngx_lua模块](http://wiki.nginx.org/HttpLuaModule),[LuaJIT 2.0](http://luajit.org/luajit.html),[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac) 和 [lua-resty-string](https://github.com/openresty/lua-resty-string)。

# 概要

```lua # nginx.conf

    lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";

    server {
        default_type text/plain;
        location = /verify {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" ..
                    ".eyJmb28iOiJiYXIifQ" ..
                    ".VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY"
                local jwt_obj = jwt:verify("lua-resty-jwt", jwt_token)
                ngx.say(cjson.encode(jwt_obj))
            ';
        }
        location = /sign {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = jwt:sign(
                    "lua-resty-jwt",
                    {
                        header={typ="JWT", alg="HS256"},
                        payload={foo="bar"}
                    }
                )
                ngx.say(jwt_token)
            ';
        }
    }
```

[返回目录](#table-of-contents)

# 方法

要加载此库,

1. 您需要在ngx_lua的[lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path)指令中指定此库的路径。例如,`lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";`。2. 您使用`require`将库加载到一个本地Lua变量中

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

## 签名

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要使用的哈希算法(`HS256`、`HS512`、`RS256`)。

### jwt_token表格示例 ###

``` { "header": {"typ": "JWT", "alg": "HS512"}, "payload": {"foo": "bar"} } ```

## 验证

`语法: local jwt_obj = jwt:verify(key, jwt_token [, claim_spec [, ...]])`

验证jwt_token并返回一个jwt_obj表格。`key`可以是预共享密钥(作为字符串),*或者*是一个函数,该函数接受单个参数(来自标头的`kid`的值),并返回`kid`的预共享密钥(作为字符串),如果`kid`查找失败则返回`nil`。如果尝试为`key`指定函数且标头中不存在`kid`,则此调用将失败。

有关`claim_spec`参数格式的详细信息,请参阅[验证](#verification)。

## 加载和验证

``` 语法: local jwt_obj = jwt:load_jwt(jwt_token) 语法: local verified = jwt:verify_jwt_obj(key, jwt_obj [, claim_spec [, ...]]) ```

``` verify = load_jwt + verify_jwt_obj ```

加载 JWT,检查 kid,然后使用正确的密钥进行验证

### jwt_obj表格示例 ###

``` { "raw_header": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9", "raw_payload: "eyJmb28iOiJiYXIifQ", "signature": "wrong-signature", "header": {"typ": "JWT", "alg": "HS256"}, "payload": {"foo": "bar"}, "verified": false, "valid": true, "reason": "signature mismatched: wrong-signature" } ```

## 签名JWE

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要用于加密密钥的哈希算法(`dir`、`RSA-OAEP-256`)。`enc`参数指定要用于加密有效载荷的哈希算法(`A128CBC-HS256`、`A256CBC-HS512`)

### jwt_token表格示例 ###

``` { "header": {"typ": "JWE", "alg": "dir", "enc":"A128CBC-HS256"}, "payload": {"foo": "bar"} } ```

[返回目录](#table-of-contents)

# 验证

`jwt:load`和`jwt:verify_jwt_obj`函数都接受任意数量的可选`claim_spec`参数作为附加参数。`claim_spec`只是一个声明和验证器的Lua表格。`claim_spec`表格中的每个键都对应于有效载荷中的匹配键,并且`validator`是一个将被调用的函数,用于确定是否满足声明。

`validator`函数的签名是

``` function(val, claim, jwt_json) ```

其中`val`是从正在测试的`jwt_obj`中获取的声明的值(如果它不存在于对象的有效载荷中则为`nil`),`claim`是正在验证的声明的名称,`jwt_json`是正在验证的对象的JSON序列化表示。如果函数不需要`claim`或`jwt_json`参数,则可以省略它们。

`validator`函数返回`true`或`false`。任何`validator`*可以*引发错误,并且验证将被视为失败,并且引发的错误将被放入结果对象的reason字段中。如果`validator`不返回任何内容(即`nil`),则该函数被视为已成功 - 假设如果它失败,它将引发错误。

可以使用名为`__jwt`的特殊声明,以便如果存在该声明的`validator`函数,则将使用整个已解析jwt对象的深拷贝作为`val`的值调用该`validator`。这样您就可以编写对可能依赖于一个或多个声明的整个对象的验证。

可以向`jwt:load`和`jwt:verify_jwt_obj`指定多个`claim_spec`表格 - 并且它们将按顺序执行。单个`claim_spec`内各个`validator`的执行顺序没有保证。如果`claim_spec`失败,则任何后续的`claim_spec`*将不会*执行。

### `claim_spec`示例 ###

``` { sub = function(val) return string.match("^[a-z]+$", val) end, iss = function(val) for _, value in pairs({ "first", "second" }) do if value == val then return true end end return false end, __jwt = function(val, claim, jwt_json) if val.payload.foo == nil or val.payload.bar == nil then error("Need to specify either 'foo' or 'bar'") end end } ```

## JWT验证器

`resty.jwt-validators`中存在一个有用的`validator`函数库。您可以通过包含以下内容来使用此库:``` local validators = require "resty.jwt-validators" ```

验证器库中当前定义了以下函数。标记为“(opt)”表示存在名为`opt_`的相同函数,它接受相同的参数。“opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`true`,而“非opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`false`。

#### `validators.chain(...)` ####

返回一个验证器,该验证器将给定的函数一个接一个地链接在一起 - 只要它们继续通过检查。

#### `validators.required(chain_function)` ####

返回一个验证器,如果值不存在则返回`false`。如果值存在并且指定了`chain_function`,则将返回`chain_function(val, claim, jwt_json)`的值,否则返回`true`。这允许指定一个值既是必需的*并且*必须匹配某些其他检查。

#### `validators.require_one_of(claim_keys)` ####

返回一个验证器,如果*没有*给定的声明键存在,则会显示一条错误消息。预期此函数用于完整的jwt对象。claim_keys必须是字符串的非空表格。

#### `validators.check(check_val, check_function, name, check_type)` (opt) ####

返回一个验证器,检查对测试值和`check_val`调用给定`check_function`的结果是否返回`true`。`check_val`和`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_value”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_val)`。传递给check_function的第一个参数*永远不会*为`nil`。如果`check_function`引发错误,则将其附加到错误消息中。

#### `validators.equals(check_val)` (opt) ####

返回一个验证器,检查值是否完全等于(使用`==`)给定的check_value。`check_val`的值不能为`nil`。

#### `validators.matches(pattern)` (opt) ####

返回一个验证器,检查值是否与给定的模式匹配(使用`string.match`)。`pattern`的值必须是字符串。

#### `validators.any_of(check_values, check_function, name, check_type, table_type)` (opt) ####

返回一个验证器,它对给定的每个`check_values`和测试值调用给定的`check_function`。如果这些调用中的任何一个返回`true`,则此函数返回`true`。`check_values`的值必须是非空表格,所有类型都相同,并且`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_values”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_values[1])` - 表格类型。

#### `validators.equals_any_of(check_values)` (opt) ####

返回一个验证器,检查值是否完全等于给定的任何`check_values`。

#### `validators.matches_any_of(patterns)` (opt) ####

返回一个验证器,检查值是否与给定的任何`patterns`匹配。

#### `validators.contains_any_of(check_values,name)` (opt) ####

返回一个验证器,检查预期类型为`string`的值是否存在于给定的任何`check_values`中。`check_values`的值必须是非空表格,所有类型都相同。可选的名称用于错误消息,默认为`check_values`。

#### `validators.greater_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.greater_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.is_not_before()` (opt) ####

返回一个验证器,检查当前时间是否不早于系统容差内的测试值。这意味着:``` val <= (system_clock() + system_leeway). ```

#### `validators.is_not_expired()` (opt) ####

返回一个验证器,检查当前时间是否不等于或晚于系统容差内的测试值。这意味着:``` val > (system_clock() - system_leeway). ```

#### `validators.is_at()` (opt) ####

返回一个验证器,检查当前时间是否与系统容差内的测试值相同。这意味着:``` val >= (system_clock() - system_leeway) and val <= (system_clock() + system_leeway). ```

#### `validators.set_system_leeway(leeway)` ####

用于设置`is_not_before`和`is_not_expired`使用的容差(以秒为单位)的函数。默认值为`0`秒

#### `validators.set_system_clock(clock)` ####

用于设置`is_not_before`和`is_not_expired`使用的系统时钟的函数。默认值为`ngx.now`

### 使用验证器的`claim_spec`示例 ###

``` local validators = require "resty.jwt-validators" local claim_spec = { sub = validators.opt_matches("^[a-z]+$), iss = validators.equals_any_of({ "first", "second" }), __jwt = validators.require_one_of({ "foo", "bar" }) } ```

## 遗留/时间范围选项

为了支持使用此库的先前版本的代码,以及简化指定基于时间范围的`claim_spec`,您可以使用`validation_options`表格替换任何单个`claim_spec`参数。参数应表示为键/值表格。表格的每个键都应从以下列表中选择。

使用遗留`validation_options`时,您*只能*指定这些选项。也就是说,您不能将遗留`validation_options`与其他`claim_spec`验证器混合使用。为了实现这一点,您必须向`jwt:load`/`jwt:verify_jwt_obj`函数指定多个选项。

* `lifetime_grace_period`: 定义以秒为单位的容差,以考虑生成jwt的服务器和验证它的服务器之间的时钟偏差。值应为零(`0`)或正整数。

    * When this validation option is specified, the process will ensure that the jwt contains at least one of the two `nbf` or `exp` claim and compare the current clock time against those boundaries. Would the jwt be deemed as expired or not valid yet, verification will fail.

    * When none of the `nbf` and `exp` claims can be found, verification will fail.

    * `nbf` and `exp` claims are expected to be expressed in the jwt as numerical values. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to calling:
      ```
      validators.set_system_leeway(leeway)
      ```

      and specifying as a `claim_spec`:
      ```
      {
        __jwt = validators.require_one_of({ "nbf", "exp" }),
        nbf = validators.opt_is_not_before(),
        exp = validators.opt_is_not_expired()
      }
      ```

* `require_nbf_claim`: 表示`nbf`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        nbf = validators.is_not_before(),
      }
      ```

* `require_exp_claim`: 表示`exp`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        exp = validators.is_not_expired(),
      }
      ```

* `valid_issuers`: 将jwt的已验证发行者列入白名单。值应为字符串数组。

    * When this validation option is specified, the process will compare the jwt `iss` claim against the list of valid issuers. Comparison is done in a case sensitive manner. Would the jwt issuer not be found in the whitelist, verification will fail.

    * `iss` claim is expected to be expressed in the jwt as a string. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        iss = validators.equals_any_of(valid_issuers),
      }
      ```

### `validation_options`使用示例 ###

``` lua local jwt_obj = jwt:verify(key, jwt_token, { lifetime_grace_period = 120, require_exp_claim = true, valid_issuers = { "my-trusted-issuer", "my-other-trusteed-issuer" } } ) ```

# 示例

* [使用查询参数和 Cookie 进行 JWT 认证](examples/README.md#jwt-auth-using-query-and-cookie) * [使用 KID 和在 Redis 中存储密钥进行 JWT 认证](examples/README.md#jwt-auth-with-kid-and-store-keys-in-redis)

[返回目录](#table-of-contents)

# 安装

使用 Luarocks ```bash luarocks install lua-resty-jwt ```

建议直接使用最新的 [ngx_openresty 包](https://openresty.org.cn)。

此外,您需要配置 [lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path) 指令,将您的 lua-resty-jwt 源代码树的路径添加到 ngx_lua 的 Lua 模块搜索路径中,例如:

```nginx # nginx.conf http { lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;"; ... } ```

然后在 Lua 中加载库

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

# 使用 Docker 测试

``` ./ci script ```

[返回目录](#table-of-contents)

# 另请参阅

* ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule

[返回目录](#table-of-contents) 当指定此验证选项时,该过程将确保 jwt 至少包含两个 nbfexp 声明之一,并将当前时钟时间与这些边界进行比较。如果 jwt 被视为已过期或尚未有效,则验证将失败。

        When none of the C<nbf> and C<exp> claims can be found, verification will fail.

        C<nbf> and C<exp> claims are expected to be expressed in the jwt as numerical values. Wouldn't that be the case, verification will fail.

        Specifying this option is equivalent to calling:
C<>`
validators.set_system_leeway(leeway)
C<>`

      and specifying as a `claim_spec`:
      ```
      {
        __jwt = validators.require_one_of({ "nbf", "exp" }),
        nbf = validators.opt_is_not_before(),
        exp = validators.opt_is_not_expired()
      }
      ```
  • require_nbf_claim:表示 nbf 声明是否可选。值应为布尔值。

**免责声明:**

如 https://github.com/SkyLothar/lua-resty-jwt/issues/85 中所述,此项目是 @SkyLothar 的 https://github.com/SkyLothar/lua-resty-jwt 的分支,现已得到所有相关方的采用,包括: - [zmartzone/lua-resty-openidc](https://github.com/zmartzone/lua-resty-openidc) - 用于 NGINX / OpenResty 的 Lua 中的 OpenID Connect 依赖方和 OAuth 2.0 资源服务器实现

---

# 名称

lua-resty-jwt - ngx_lua 和 LuaJIT 的 [JWT](http://self-issued.info/docs/draft-jones-json-web-token-01.html)

[![构建状态](https://img.shields.io/travis/cdbattags/lua-resty-jwt.svg?style=flat-square)](https://travis-ci.org/cdbattags/lua-resty-jwt)

**注意 :exclamation: 这里使用的hmac库是[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac),而不是luarocks中的库。**

# 安装

- opm: `opm get cdbattags/lua-resty-jwt` - luarocks: `luarocks install lua-resty-jwt` - 前往[发布页面](https://github.com/cdbattags/lua-resty-jwt/releases) 下载 `tar.gz`

# 版本

0.2.3

# 目录

* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [签名](#sign) * [验证](#verify) * [加载和验证](#load--verify) * [签名JWE](#sign-jwe) * [验证](#verification) * [JWT验证器](#jwt-validators) * [遗留/时间范围选项](#legacy-timeframe-options) * [示例](#examples) * [安装](#installation) * [使用Docker进行测试](#testing-with-docker) * [作者](AUTHORS.md) * [另请参阅](#see-also)

# 状态

此库处于积极开发中,但被认为已准备好投入生产。

# 描述

此库需要一个使用OpenSSL构建的nginx,[ngx_lua模块](http://wiki.nginx.org/HttpLuaModule),[LuaJIT 2.0](http://luajit.org/luajit.html),[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac) 和 [lua-resty-string](https://github.com/openresty/lua-resty-string)。

# 概要

```lua # nginx.conf

    lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";

    server {
        default_type text/plain;
        location = /verify {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" ..
                    ".eyJmb28iOiJiYXIifQ" ..
                    ".VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY"
                local jwt_obj = jwt:verify("lua-resty-jwt", jwt_token)
                ngx.say(cjson.encode(jwt_obj))
            ';
        }
        location = /sign {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = jwt:sign(
                    "lua-resty-jwt",
                    {
                        header={typ="JWT", alg="HS256"},
                        payload={foo="bar"}
                    }
                )
                ngx.say(jwt_token)
            ';
        }
    }
```

[返回目录](#table-of-contents)

# 方法

要加载此库,

1. 您需要在ngx_lua的[lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path)指令中指定此库的路径。例如,`lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";`。2. 您使用`require`将库加载到一个本地Lua变量中

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

## 签名

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要使用的哈希算法(`HS256`、`HS512`、`RS256`)。

### jwt_token表格示例 ###

``` { "header": {"typ": "JWT", "alg": "HS512"}, "payload": {"foo": "bar"} } ```

## 验证

`语法: local jwt_obj = jwt:verify(key, jwt_token [, claim_spec [, ...]])`

验证jwt_token并返回一个jwt_obj表格。`key`可以是预共享密钥(作为字符串),*或者*是一个函数,该函数接受单个参数(来自标头的`kid`的值),并返回`kid`的预共享密钥(作为字符串),如果`kid`查找失败则返回`nil`。如果尝试为`key`指定函数且标头中不存在`kid`,则此调用将失败。

有关`claim_spec`参数格式的详细信息,请参阅[验证](#verification)。

## 加载和验证

``` 语法: local jwt_obj = jwt:load_jwt(jwt_token) 语法: local verified = jwt:verify_jwt_obj(key, jwt_obj [, claim_spec [, ...]]) ```

``` verify = load_jwt + verify_jwt_obj ```

加载 JWT,检查 kid,然后使用正确的密钥进行验证

### jwt_obj表格示例 ###

``` { "raw_header": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9", "raw_payload: "eyJmb28iOiJiYXIifQ", "signature": "wrong-signature", "header": {"typ": "JWT", "alg": "HS256"}, "payload": {"foo": "bar"}, "verified": false, "valid": true, "reason": "signature mismatched: wrong-signature" } ```

## 签名JWE

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要用于加密密钥的哈希算法(`dir`、`RSA-OAEP-256`)。`enc`参数指定要用于加密有效载荷的哈希算法(`A128CBC-HS256`、`A256CBC-HS512`)

### jwt_token表格示例 ###

``` { "header": {"typ": "JWE", "alg": "dir", "enc":"A128CBC-HS256"}, "payload": {"foo": "bar"} } ```

[返回目录](#table-of-contents)

# 验证

`jwt:load`和`jwt:verify_jwt_obj`函数都接受任意数量的可选`claim_spec`参数作为附加参数。`claim_spec`只是一个声明和验证器的Lua表格。`claim_spec`表格中的每个键都对应于有效载荷中的匹配键,并且`validator`是一个将被调用的函数,用于确定是否满足声明。

`validator`函数的签名是

``` function(val, claim, jwt_json) ```

其中`val`是从正在测试的`jwt_obj`中获取的声明的值(如果它不存在于对象的有效载荷中则为`nil`),`claim`是正在验证的声明的名称,`jwt_json`是正在验证的对象的JSON序列化表示。如果函数不需要`claim`或`jwt_json`参数,则可以省略它们。

`validator`函数返回`true`或`false`。任何`validator`*可以*引发错误,并且验证将被视为失败,并且引发的错误将被放入结果对象的reason字段中。如果`validator`不返回任何内容(即`nil`),则该函数被视为已成功 - 假设如果它失败,它将引发错误。

可以使用名为`__jwt`的特殊声明,以便如果存在该声明的`validator`函数,则将使用整个已解析jwt对象的深拷贝作为`val`的值调用该`validator`。这样您就可以编写对可能依赖于一个或多个声明的整个对象的验证。

可以向`jwt:load`和`jwt:verify_jwt_obj`指定多个`claim_spec`表格 - 并且它们将按顺序执行。单个`claim_spec`内各个`validator`的执行顺序没有保证。如果`claim_spec`失败,则任何后续的`claim_spec`*将不会*执行。

### `claim_spec`示例 ###

``` { sub = function(val) return string.match("^[a-z]+$", val) end, iss = function(val) for _, value in pairs({ "first", "second" }) do if value == val then return true end end return false end, __jwt = function(val, claim, jwt_json) if val.payload.foo == nil or val.payload.bar == nil then error("Need to specify either 'foo' or 'bar'") end end } ```

## JWT验证器

`resty.jwt-validators`中存在一个有用的`validator`函数库。您可以通过包含以下内容来使用此库:``` local validators = require "resty.jwt-validators" ```

验证器库中当前定义了以下函数。标记为“(opt)”表示存在名为`opt_`的相同函数,它接受相同的参数。“opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`true`,而“非opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`false`。

#### `validators.chain(...)` ####

返回一个验证器,该验证器将给定的函数一个接一个地链接在一起 - 只要它们继续通过检查。

#### `validators.required(chain_function)` ####

返回一个验证器,如果值不存在则返回`false`。如果值存在并且指定了`chain_function`,则将返回`chain_function(val, claim, jwt_json)`的值,否则返回`true`。这允许指定一个值既是必需的*并且*必须匹配某些其他检查。

#### `validators.require_one_of(claim_keys)` ####

返回一个验证器,如果*没有*给定的声明键存在,则会显示一条错误消息。预期此函数用于完整的jwt对象。claim_keys必须是字符串的非空表格。

#### `validators.check(check_val, check_function, name, check_type)` (opt) ####

返回一个验证器,检查对测试值和`check_val`调用给定`check_function`的结果是否返回`true`。`check_val`和`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_value”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_val)`。传递给check_function的第一个参数*永远不会*为`nil`。如果`check_function`引发错误,则将其附加到错误消息中。

#### `validators.equals(check_val)` (opt) ####

返回一个验证器,检查值是否完全等于(使用`==`)给定的check_value。`check_val`的值不能为`nil`。

#### `validators.matches(pattern)` (opt) ####

返回一个验证器,检查值是否与给定的模式匹配(使用`string.match`)。`pattern`的值必须是字符串。

#### `validators.any_of(check_values, check_function, name, check_type, table_type)` (opt) ####

返回一个验证器,它对给定的每个`check_values`和测试值调用给定的`check_function`。如果这些调用中的任何一个返回`true`,则此函数返回`true`。`check_values`的值必须是非空表格,所有类型都相同,并且`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_values”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_values[1])` - 表格类型。

#### `validators.equals_any_of(check_values)` (opt) ####

返回一个验证器,检查值是否完全等于给定的任何`check_values`。

#### `validators.matches_any_of(patterns)` (opt) ####

返回一个验证器,检查值是否与给定的任何`patterns`匹配。

#### `validators.contains_any_of(check_values,name)` (opt) ####

返回一个验证器,检查预期类型为`string`的值是否存在于给定的任何`check_values`中。`check_values`的值必须是非空表格,所有类型都相同。可选的名称用于错误消息,默认为`check_values`。

#### `validators.greater_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.greater_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.is_not_before()` (opt) ####

返回一个验证器,检查当前时间是否不早于系统容差内的测试值。这意味着:``` val <= (system_clock() + system_leeway). ```

#### `validators.is_not_expired()` (opt) ####

返回一个验证器,检查当前时间是否不等于或晚于系统容差内的测试值。这意味着:``` val > (system_clock() - system_leeway). ```

#### `validators.is_at()` (opt) ####

返回一个验证器,检查当前时间是否与系统容差内的测试值相同。这意味着:``` val >= (system_clock() - system_leeway) and val <= (system_clock() + system_leeway). ```

#### `validators.set_system_leeway(leeway)` ####

用于设置`is_not_before`和`is_not_expired`使用的容差(以秒为单位)的函数。默认值为`0`秒

#### `validators.set_system_clock(clock)` ####

用于设置`is_not_before`和`is_not_expired`使用的系统时钟的函数。默认值为`ngx.now`

### 使用验证器的`claim_spec`示例 ###

``` local validators = require "resty.jwt-validators" local claim_spec = { sub = validators.opt_matches("^[a-z]+$), iss = validators.equals_any_of({ "first", "second" }), __jwt = validators.require_one_of({ "foo", "bar" }) } ```

## 遗留/时间范围选项

为了支持使用此库的先前版本的代码,以及简化指定基于时间范围的`claim_spec`,您可以使用`validation_options`表格替换任何单个`claim_spec`参数。参数应表示为键/值表格。表格的每个键都应从以下列表中选择。

使用遗留`validation_options`时,您*只能*指定这些选项。也就是说,您不能将遗留`validation_options`与其他`claim_spec`验证器混合使用。为了实现这一点,您必须向`jwt:load`/`jwt:verify_jwt_obj`函数指定多个选项。

* `lifetime_grace_period`: 定义以秒为单位的容差,以考虑生成jwt的服务器和验证它的服务器之间的时钟偏差。值应为零(`0`)或正整数。

    * When this validation option is specified, the process will ensure that the jwt contains at least one of the two `nbf` or `exp` claim and compare the current clock time against those boundaries. Would the jwt be deemed as expired or not valid yet, verification will fail.

    * When none of the `nbf` and `exp` claims can be found, verification will fail.

    * `nbf` and `exp` claims are expected to be expressed in the jwt as numerical values. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to calling:
      ```
      validators.set_system_leeway(leeway)
      ```

      and specifying as a `claim_spec`:
      ```
      {
        __jwt = validators.require_one_of({ "nbf", "exp" }),
        nbf = validators.opt_is_not_before(),
        exp = validators.opt_is_not_expired()
      }
      ```

* `require_nbf_claim`: 表示`nbf`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        nbf = validators.is_not_before(),
      }
      ```

* `require_exp_claim`: 表示`exp`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        exp = validators.is_not_expired(),
      }
      ```

* `valid_issuers`: 将jwt的已验证发行者列入白名单。值应为字符串数组。

    * When this validation option is specified, the process will compare the jwt `iss` claim against the list of valid issuers. Comparison is done in a case sensitive manner. Would the jwt issuer not be found in the whitelist, verification will fail.

    * `iss` claim is expected to be expressed in the jwt as a string. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        iss = validators.equals_any_of(valid_issuers),
      }
      ```

### `validation_options`使用示例 ###

``` lua local jwt_obj = jwt:verify(key, jwt_token, { lifetime_grace_period = 120, require_exp_claim = true, valid_issuers = { "my-trusted-issuer", "my-other-trusteed-issuer" } } ) ```

# 示例

* [使用查询参数和 Cookie 进行 JWT 认证](examples/README.md#jwt-auth-using-query-and-cookie) * [使用 KID 和在 Redis 中存储密钥进行 JWT 认证](examples/README.md#jwt-auth-with-kid-and-store-keys-in-redis)

[返回目录](#table-of-contents)

# 安装

使用 Luarocks ```bash luarocks install lua-resty-jwt ```

建议直接使用最新的 [ngx_openresty 包](https://openresty.org.cn)。

此外,您需要配置 [lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path) 指令,将您的 lua-resty-jwt 源代码树的路径添加到 ngx_lua 的 Lua 模块搜索路径中,例如:

```nginx # nginx.conf http { lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;"; ... } ```

然后在 Lua 中加载库

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

# 使用 Docker 测试

``` ./ci script ```

[返回目录](#table-of-contents)

# 另请参阅

* ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule

[返回目录](#table-of-contents) 当此验证选项设置为 true 且未指定 lifetime_grace_period 时,将隐含零 (0) 宽限期。

        Specifying this option is equivalent to specifying as a C<claim_spec>:
C<>`
{
nbf = validators.is_not_before(),
}
C<>`
  • require_exp_claim:表示 exp 声明是否可选。值应为布尔值。

**免责声明:**

如 https://github.com/SkyLothar/lua-resty-jwt/issues/85 中所述,此项目是 @SkyLothar 的 https://github.com/SkyLothar/lua-resty-jwt 的分支,现已得到所有相关方的采用,包括: - [zmartzone/lua-resty-openidc](https://github.com/zmartzone/lua-resty-openidc) - 用于 NGINX / OpenResty 的 Lua 中的 OpenID Connect 依赖方和 OAuth 2.0 资源服务器实现

---

# 名称

lua-resty-jwt - ngx_lua 和 LuaJIT 的 [JWT](http://self-issued.info/docs/draft-jones-json-web-token-01.html)

[![构建状态](https://img.shields.io/travis/cdbattags/lua-resty-jwt.svg?style=flat-square)](https://travis-ci.org/cdbattags/lua-resty-jwt)

**注意 :exclamation: 这里使用的hmac库是[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac),而不是luarocks中的库。**

# 安装

- opm: `opm get cdbattags/lua-resty-jwt` - luarocks: `luarocks install lua-resty-jwt` - 前往[发布页面](https://github.com/cdbattags/lua-resty-jwt/releases) 下载 `tar.gz`

# 版本

0.2.3

# 目录

* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [签名](#sign) * [验证](#verify) * [加载和验证](#load--verify) * [签名JWE](#sign-jwe) * [验证](#verification) * [JWT验证器](#jwt-validators) * [遗留/时间范围选项](#legacy-timeframe-options) * [示例](#examples) * [安装](#installation) * [使用Docker进行测试](#testing-with-docker) * [作者](AUTHORS.md) * [另请参阅](#see-also)

# 状态

此库处于积极开发中,但被认为已准备好投入生产。

# 描述

此库需要一个使用OpenSSL构建的nginx,[ngx_lua模块](http://wiki.nginx.org/HttpLuaModule),[LuaJIT 2.0](http://luajit.org/luajit.html),[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac) 和 [lua-resty-string](https://github.com/openresty/lua-resty-string)。

# 概要

```lua # nginx.conf

    lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";

    server {
        default_type text/plain;
        location = /verify {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" ..
                    ".eyJmb28iOiJiYXIifQ" ..
                    ".VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY"
                local jwt_obj = jwt:verify("lua-resty-jwt", jwt_token)
                ngx.say(cjson.encode(jwt_obj))
            ';
        }
        location = /sign {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = jwt:sign(
                    "lua-resty-jwt",
                    {
                        header={typ="JWT", alg="HS256"},
                        payload={foo="bar"}
                    }
                )
                ngx.say(jwt_token)
            ';
        }
    }
```

[返回目录](#table-of-contents)

# 方法

要加载此库,

1. 您需要在ngx_lua的[lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path)指令中指定此库的路径。例如,`lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";`。2. 您使用`require`将库加载到一个本地Lua变量中

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

## 签名

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要使用的哈希算法(`HS256`、`HS512`、`RS256`)。

### jwt_token表格示例 ###

``` { "header": {"typ": "JWT", "alg": "HS512"}, "payload": {"foo": "bar"} } ```

## 验证

`语法: local jwt_obj = jwt:verify(key, jwt_token [, claim_spec [, ...]])`

验证jwt_token并返回一个jwt_obj表格。`key`可以是预共享密钥(作为字符串),*或者*是一个函数,该函数接受单个参数(来自标头的`kid`的值),并返回`kid`的预共享密钥(作为字符串),如果`kid`查找失败则返回`nil`。如果尝试为`key`指定函数且标头中不存在`kid`,则此调用将失败。

有关`claim_spec`参数格式的详细信息,请参阅[验证](#verification)。

## 加载和验证

``` 语法: local jwt_obj = jwt:load_jwt(jwt_token) 语法: local verified = jwt:verify_jwt_obj(key, jwt_obj [, claim_spec [, ...]]) ```

``` verify = load_jwt + verify_jwt_obj ```

加载 JWT,检查 kid,然后使用正确的密钥进行验证

### jwt_obj表格示例 ###

``` { "raw_header": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9", "raw_payload: "eyJmb28iOiJiYXIifQ", "signature": "wrong-signature", "header": {"typ": "JWT", "alg": "HS256"}, "payload": {"foo": "bar"}, "verified": false, "valid": true, "reason": "signature mismatched: wrong-signature" } ```

## 签名JWE

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要用于加密密钥的哈希算法(`dir`、`RSA-OAEP-256`)。`enc`参数指定要用于加密有效载荷的哈希算法(`A128CBC-HS256`、`A256CBC-HS512`)

### jwt_token表格示例 ###

``` { "header": {"typ": "JWE", "alg": "dir", "enc":"A128CBC-HS256"}, "payload": {"foo": "bar"} } ```

[返回目录](#table-of-contents)

# 验证

`jwt:load`和`jwt:verify_jwt_obj`函数都接受任意数量的可选`claim_spec`参数作为附加参数。`claim_spec`只是一个声明和验证器的Lua表格。`claim_spec`表格中的每个键都对应于有效载荷中的匹配键,并且`validator`是一个将被调用的函数,用于确定是否满足声明。

`validator`函数的签名是

``` function(val, claim, jwt_json) ```

其中`val`是从正在测试的`jwt_obj`中获取的声明的值(如果它不存在于对象的有效载荷中则为`nil`),`claim`是正在验证的声明的名称,`jwt_json`是正在验证的对象的JSON序列化表示。如果函数不需要`claim`或`jwt_json`参数,则可以省略它们。

`validator`函数返回`true`或`false`。任何`validator`*可以*引发错误,并且验证将被视为失败,并且引发的错误将被放入结果对象的reason字段中。如果`validator`不返回任何内容(即`nil`),则该函数被视为已成功 - 假设如果它失败,它将引发错误。

可以使用名为`__jwt`的特殊声明,以便如果存在该声明的`validator`函数,则将使用整个已解析jwt对象的深拷贝作为`val`的值调用该`validator`。这样您就可以编写对可能依赖于一个或多个声明的整个对象的验证。

可以向`jwt:load`和`jwt:verify_jwt_obj`指定多个`claim_spec`表格 - 并且它们将按顺序执行。单个`claim_spec`内各个`validator`的执行顺序没有保证。如果`claim_spec`失败,则任何后续的`claim_spec`*将不会*执行。

### `claim_spec`示例 ###

``` { sub = function(val) return string.match("^[a-z]+$", val) end, iss = function(val) for _, value in pairs({ "first", "second" }) do if value == val then return true end end return false end, __jwt = function(val, claim, jwt_json) if val.payload.foo == nil or val.payload.bar == nil then error("Need to specify either 'foo' or 'bar'") end end } ```

## JWT验证器

`resty.jwt-validators`中存在一个有用的`validator`函数库。您可以通过包含以下内容来使用此库:``` local validators = require "resty.jwt-validators" ```

验证器库中当前定义了以下函数。标记为“(opt)”表示存在名为`opt_`的相同函数,它接受相同的参数。“opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`true`,而“非opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`false`。

#### `validators.chain(...)` ####

返回一个验证器,该验证器将给定的函数一个接一个地链接在一起 - 只要它们继续通过检查。

#### `validators.required(chain_function)` ####

返回一个验证器,如果值不存在则返回`false`。如果值存在并且指定了`chain_function`,则将返回`chain_function(val, claim, jwt_json)`的值,否则返回`true`。这允许指定一个值既是必需的*并且*必须匹配某些其他检查。

#### `validators.require_one_of(claim_keys)` ####

返回一个验证器,如果*没有*给定的声明键存在,则会显示一条错误消息。预期此函数用于完整的jwt对象。claim_keys必须是字符串的非空表格。

#### `validators.check(check_val, check_function, name, check_type)` (opt) ####

返回一个验证器,检查对测试值和`check_val`调用给定`check_function`的结果是否返回`true`。`check_val`和`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_value”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_val)`。传递给check_function的第一个参数*永远不会*为`nil`。如果`check_function`引发错误,则将其附加到错误消息中。

#### `validators.equals(check_val)` (opt) ####

返回一个验证器,检查值是否完全等于(使用`==`)给定的check_value。`check_val`的值不能为`nil`。

#### `validators.matches(pattern)` (opt) ####

返回一个验证器,检查值是否与给定的模式匹配(使用`string.match`)。`pattern`的值必须是字符串。

#### `validators.any_of(check_values, check_function, name, check_type, table_type)` (opt) ####

返回一个验证器,它对给定的每个`check_values`和测试值调用给定的`check_function`。如果这些调用中的任何一个返回`true`,则此函数返回`true`。`check_values`的值必须是非空表格,所有类型都相同,并且`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_values”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_values[1])` - 表格类型。

#### `validators.equals_any_of(check_values)` (opt) ####

返回一个验证器,检查值是否完全等于给定的任何`check_values`。

#### `validators.matches_any_of(patterns)` (opt) ####

返回一个验证器,检查值是否与给定的任何`patterns`匹配。

#### `validators.contains_any_of(check_values,name)` (opt) ####

返回一个验证器,检查预期类型为`string`的值是否存在于给定的任何`check_values`中。`check_values`的值必须是非空表格,所有类型都相同。可选的名称用于错误消息,默认为`check_values`。

#### `validators.greater_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.greater_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.is_not_before()` (opt) ####

返回一个验证器,检查当前时间是否不早于系统容差内的测试值。这意味着:``` val <= (system_clock() + system_leeway). ```

#### `validators.is_not_expired()` (opt) ####

返回一个验证器,检查当前时间是否不等于或晚于系统容差内的测试值。这意味着:``` val > (system_clock() - system_leeway). ```

#### `validators.is_at()` (opt) ####

返回一个验证器,检查当前时间是否与系统容差内的测试值相同。这意味着:``` val >= (system_clock() - system_leeway) and val <= (system_clock() + system_leeway). ```

#### `validators.set_system_leeway(leeway)` ####

用于设置`is_not_before`和`is_not_expired`使用的容差(以秒为单位)的函数。默认值为`0`秒

#### `validators.set_system_clock(clock)` ####

用于设置`is_not_before`和`is_not_expired`使用的系统时钟的函数。默认值为`ngx.now`

### 使用验证器的`claim_spec`示例 ###

``` local validators = require "resty.jwt-validators" local claim_spec = { sub = validators.opt_matches("^[a-z]+$), iss = validators.equals_any_of({ "first", "second" }), __jwt = validators.require_one_of({ "foo", "bar" }) } ```

## 遗留/时间范围选项

为了支持使用此库的先前版本的代码,以及简化指定基于时间范围的`claim_spec`,您可以使用`validation_options`表格替换任何单个`claim_spec`参数。参数应表示为键/值表格。表格的每个键都应从以下列表中选择。

使用遗留`validation_options`时,您*只能*指定这些选项。也就是说,您不能将遗留`validation_options`与其他`claim_spec`验证器混合使用。为了实现这一点,您必须向`jwt:load`/`jwt:verify_jwt_obj`函数指定多个选项。

* `lifetime_grace_period`: 定义以秒为单位的容差,以考虑生成jwt的服务器和验证它的服务器之间的时钟偏差。值应为零(`0`)或正整数。

    * When this validation option is specified, the process will ensure that the jwt contains at least one of the two `nbf` or `exp` claim and compare the current clock time against those boundaries. Would the jwt be deemed as expired or not valid yet, verification will fail.

    * When none of the `nbf` and `exp` claims can be found, verification will fail.

    * `nbf` and `exp` claims are expected to be expressed in the jwt as numerical values. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to calling:
      ```
      validators.set_system_leeway(leeway)
      ```

      and specifying as a `claim_spec`:
      ```
      {
        __jwt = validators.require_one_of({ "nbf", "exp" }),
        nbf = validators.opt_is_not_before(),
        exp = validators.opt_is_not_expired()
      }
      ```

* `require_nbf_claim`: 表示`nbf`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        nbf = validators.is_not_before(),
      }
      ```

* `require_exp_claim`: 表示`exp`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        exp = validators.is_not_expired(),
      }
      ```

* `valid_issuers`: 将jwt的已验证发行者列入白名单。值应为字符串数组。

    * When this validation option is specified, the process will compare the jwt `iss` claim against the list of valid issuers. Comparison is done in a case sensitive manner. Would the jwt issuer not be found in the whitelist, verification will fail.

    * `iss` claim is expected to be expressed in the jwt as a string. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        iss = validators.equals_any_of(valid_issuers),
      }
      ```

### `validation_options`使用示例 ###

``` lua local jwt_obj = jwt:verify(key, jwt_token, { lifetime_grace_period = 120, require_exp_claim = true, valid_issuers = { "my-trusted-issuer", "my-other-trusteed-issuer" } } ) ```

# 示例

* [使用查询参数和 Cookie 进行 JWT 认证](examples/README.md#jwt-auth-using-query-and-cookie) * [使用 KID 和在 Redis 中存储密钥进行 JWT 认证](examples/README.md#jwt-auth-with-kid-and-store-keys-in-redis)

[返回目录](#table-of-contents)

# 安装

使用 Luarocks ```bash luarocks install lua-resty-jwt ```

建议直接使用最新的 [ngx_openresty 包](https://openresty.org.cn)。

此外,您需要配置 [lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path) 指令,将您的 lua-resty-jwt 源代码树的路径添加到 ngx_lua 的 Lua 模块搜索路径中,例如:

```nginx # nginx.conf http { lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;"; ... } ```

然后在 Lua 中加载库

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

# 使用 Docker 测试

``` ./ci script ```

[返回目录](#table-of-contents)

# 另请参阅

* ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule

[返回目录](#table-of-contents) 当此验证选项设置为 true 且未指定 lifetime_grace_period 时,将隐含零 (0) 宽限期。

        Specifying this option is equivalent to specifying as a C<claim_spec>:
C<>`
{
exp = validators.is_not_expired(),
}
C<>`
  • valid_issuers:将 jwt 的已验证发行者列入白名单。值应为字符串数组。

**免责声明:**

如 https://github.com/SkyLothar/lua-resty-jwt/issues/85 中所述,此项目是 @SkyLothar 的 https://github.com/SkyLothar/lua-resty-jwt 的分支,现已得到所有相关方的采用,包括: - [zmartzone/lua-resty-openidc](https://github.com/zmartzone/lua-resty-openidc) - 用于 NGINX / OpenResty 的 Lua 中的 OpenID Connect 依赖方和 OAuth 2.0 资源服务器实现

---

# 名称

lua-resty-jwt - ngx_lua 和 LuaJIT 的 [JWT](http://self-issued.info/docs/draft-jones-json-web-token-01.html)

[![构建状态](https://img.shields.io/travis/cdbattags/lua-resty-jwt.svg?style=flat-square)](https://travis-ci.org/cdbattags/lua-resty-jwt)

**注意 :exclamation: 这里使用的hmac库是[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac),而不是luarocks中的库。**

# 安装

- opm: `opm get cdbattags/lua-resty-jwt` - luarocks: `luarocks install lua-resty-jwt` - 前往[发布页面](https://github.com/cdbattags/lua-resty-jwt/releases) 下载 `tar.gz`

# 版本

0.2.3

# 目录

* [名称](#name) * [状态](#status) * [描述](#description) * [概要](#synopsis) * [方法](#methods) * [签名](#sign) * [验证](#verify) * [加载和验证](#load--verify) * [签名JWE](#sign-jwe) * [验证](#verification) * [JWT验证器](#jwt-validators) * [遗留/时间范围选项](#legacy-timeframe-options) * [示例](#examples) * [安装](#installation) * [使用Docker进行测试](#testing-with-docker) * [作者](AUTHORS.md) * [另请参阅](#see-also)

# 状态

此库处于积极开发中,但被认为已准备好投入生产。

# 描述

此库需要一个使用OpenSSL构建的nginx,[ngx_lua模块](http://wiki.nginx.org/HttpLuaModule),[LuaJIT 2.0](http://luajit.org/luajit.html),[lua-resty-hmac](https://github.com/jkeys089/lua-resty-hmac) 和 [lua-resty-string](https://github.com/openresty/lua-resty-string)。

# 概要

```lua # nginx.conf

    lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";

    server {
        default_type text/plain;
        location = /verify {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" ..
                    ".eyJmb28iOiJiYXIifQ" ..
                    ".VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY"
                local jwt_obj = jwt:verify("lua-resty-jwt", jwt_token)
                ngx.say(cjson.encode(jwt_obj))
            ';
        }
        location = /sign {
            content_by_lua '
                local cjson = require "cjson"
                local jwt = require "resty.jwt"

                local jwt_token = jwt:sign(
                    "lua-resty-jwt",
                    {
                        header={typ="JWT", alg="HS256"},
                        payload={foo="bar"}
                    }
                )
                ngx.say(jwt_token)
            ';
        }
    }
```

[返回目录](#table-of-contents)

# 方法

要加载此库,

1. 您需要在ngx_lua的[lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path)指令中指定此库的路径。例如,`lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";`。2. 您使用`require`将库加载到一个本地Lua变量中

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

## 签名

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要使用的哈希算法(`HS256`、`HS512`、`RS256`)。

### jwt_token表格示例 ###

``` { "header": {"typ": "JWT", "alg": "HS512"}, "payload": {"foo": "bar"} } ```

## 验证

`语法: local jwt_obj = jwt:verify(key, jwt_token [, claim_spec [, ...]])`

验证jwt_token并返回一个jwt_obj表格。`key`可以是预共享密钥(作为字符串),*或者*是一个函数,该函数接受单个参数(来自标头的`kid`的值),并返回`kid`的预共享密钥(作为字符串),如果`kid`查找失败则返回`nil`。如果尝试为`key`指定函数且标头中不存在`kid`,则此调用将失败。

有关`claim_spec`参数格式的详细信息,请参阅[验证](#verification)。

## 加载和验证

``` 语法: local jwt_obj = jwt:load_jwt(jwt_token) 语法: local verified = jwt:verify_jwt_obj(key, jwt_obj [, claim_spec [, ...]]) ```

``` verify = load_jwt + verify_jwt_obj ```

加载 JWT,检查 kid,然后使用正确的密钥进行验证

### jwt_obj表格示例 ###

``` { "raw_header": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9", "raw_payload: "eyJmb28iOiJiYXIifQ", "signature": "wrong-signature", "header": {"typ": "JWT", "alg": "HS256"}, "payload": {"foo": "bar"}, "verified": false, "valid": true, "reason": "signature mismatched: wrong-signature" } ```

## 签名JWE

`语法: local jwt_token = jwt:sign(key, table_of_jwt)`

table_of_jwt 签名到 jwt_token

`alg`参数指定要用于加密密钥的哈希算法(`dir`、`RSA-OAEP-256`)。`enc`参数指定要用于加密有效载荷的哈希算法(`A128CBC-HS256`、`A256CBC-HS512`)

### jwt_token表格示例 ###

``` { "header": {"typ": "JWE", "alg": "dir", "enc":"A128CBC-HS256"}, "payload": {"foo": "bar"} } ```

[返回目录](#table-of-contents)

# 验证

`jwt:load`和`jwt:verify_jwt_obj`函数都接受任意数量的可选`claim_spec`参数作为附加参数。`claim_spec`只是一个声明和验证器的Lua表格。`claim_spec`表格中的每个键都对应于有效载荷中的匹配键,并且`validator`是一个将被调用的函数,用于确定是否满足声明。

`validator`函数的签名是

``` function(val, claim, jwt_json) ```

其中`val`是从正在测试的`jwt_obj`中获取的声明的值(如果它不存在于对象的有效载荷中则为`nil`),`claim`是正在验证的声明的名称,`jwt_json`是正在验证的对象的JSON序列化表示。如果函数不需要`claim`或`jwt_json`参数,则可以省略它们。

`validator`函数返回`true`或`false`。任何`validator`*可以*引发错误,并且验证将被视为失败,并且引发的错误将被放入结果对象的reason字段中。如果`validator`不返回任何内容(即`nil`),则该函数被视为已成功 - 假设如果它失败,它将引发错误。

可以使用名为`__jwt`的特殊声明,以便如果存在该声明的`validator`函数,则将使用整个已解析jwt对象的深拷贝作为`val`的值调用该`validator`。这样您就可以编写对可能依赖于一个或多个声明的整个对象的验证。

可以向`jwt:load`和`jwt:verify_jwt_obj`指定多个`claim_spec`表格 - 并且它们将按顺序执行。单个`claim_spec`内各个`validator`的执行顺序没有保证。如果`claim_spec`失败,则任何后续的`claim_spec`*将不会*执行。

### `claim_spec`示例 ###

``` { sub = function(val) return string.match("^[a-z]+$", val) end, iss = function(val) for _, value in pairs({ "first", "second" }) do if value == val then return true end end return false end, __jwt = function(val, claim, jwt_json) if val.payload.foo == nil or val.payload.bar == nil then error("Need to specify either 'foo' or 'bar'") end end } ```

## JWT验证器

`resty.jwt-validators`中存在一个有用的`validator`函数库。您可以通过包含以下内容来使用此库:``` local validators = require "resty.jwt-validators" ```

验证器库中当前定义了以下函数。标记为“(opt)”表示存在名为`opt_`的相同函数,它接受相同的参数。“opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`true`,而“非opt”版本的函数如果jwt_object被验证的有效载荷中不存在键,则返回`false`。

#### `validators.chain(...)` ####

返回一个验证器,该验证器将给定的函数一个接一个地链接在一起 - 只要它们继续通过检查。

#### `validators.required(chain_function)` ####

返回一个验证器,如果值不存在则返回`false`。如果值存在并且指定了`chain_function`,则将返回`chain_function(val, claim, jwt_json)`的值,否则返回`true`。这允许指定一个值既是必需的*并且*必须匹配某些其他检查。

#### `validators.require_one_of(claim_keys)` ####

返回一个验证器,如果*没有*给定的声明键存在,则会显示一条错误消息。预期此函数用于完整的jwt对象。claim_keys必须是字符串的非空表格。

#### `validators.check(check_val, check_function, name, check_type)` (opt) ####

返回一个验证器,检查对测试值和`check_val`调用给定`check_function`的结果是否返回`true`。`check_val`和`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_value”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_val)`。传递给check_function的第一个参数*永远不会*为`nil`。如果`check_function`引发错误,则将其附加到错误消息中。

#### `validators.equals(check_val)` (opt) ####

返回一个验证器,检查值是否完全等于(使用`==`)给定的check_value。`check_val`的值不能为`nil`。

#### `validators.matches(pattern)` (opt) ####

返回一个验证器,检查值是否与给定的模式匹配(使用`string.match`)。`pattern`的值必须是字符串。

#### `validators.any_of(check_values, check_function, name, check_type, table_type)` (opt) ####

返回一个验证器,它对给定的每个`check_values`和测试值调用给定的`check_function`。如果这些调用中的任何一个返回`true`,则此函数返回`true`。`check_values`的值必须是非空表格,所有类型都相同,并且`check_function`的值不能为`nil`。可选的`name`用于错误消息,默认为“check_values”。可选的`check_type`用于确保检查类型匹配,默认为`type(check_values[1])` - 表格类型。

#### `validators.equals_any_of(check_values)` (opt) ####

返回一个验证器,检查值是否完全等于给定的任何`check_values`。

#### `validators.matches_any_of(patterns)` (opt) ####

返回一个验证器,检查值是否与给定的任何`patterns`匹配。

#### `validators.contains_any_of(check_values,name)` (opt) ####

返回一个验证器,检查预期类型为`string`的值是否存在于给定的任何`check_values`中。`check_values`的值必须是非空表格,所有类型都相同。可选的名称用于错误消息,默认为`check_values`。

#### `validators.greater_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.greater_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`>=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.less_than_or_equal(check_val)` (opt) ####

返回一个验证器,检查值如何与(数值上,使用`<=`)给定的`check_value`进行比较。`check_val`的值不能为`nil`,并且必须是数字。

#### `validators.is_not_before()` (opt) ####

返回一个验证器,检查当前时间是否不早于系统容差内的测试值。这意味着:``` val <= (system_clock() + system_leeway). ```

#### `validators.is_not_expired()` (opt) ####

返回一个验证器,检查当前时间是否不等于或晚于系统容差内的测试值。这意味着:``` val > (system_clock() - system_leeway). ```

#### `validators.is_at()` (opt) ####

返回一个验证器,检查当前时间是否与系统容差内的测试值相同。这意味着:``` val >= (system_clock() - system_leeway) and val <= (system_clock() + system_leeway). ```

#### `validators.set_system_leeway(leeway)` ####

用于设置`is_not_before`和`is_not_expired`使用的容差(以秒为单位)的函数。默认值为`0`秒

#### `validators.set_system_clock(clock)` ####

用于设置`is_not_before`和`is_not_expired`使用的系统时钟的函数。默认值为`ngx.now`

### 使用验证器的`claim_spec`示例 ###

``` local validators = require "resty.jwt-validators" local claim_spec = { sub = validators.opt_matches("^[a-z]+$), iss = validators.equals_any_of({ "first", "second" }), __jwt = validators.require_one_of({ "foo", "bar" }) } ```

## 遗留/时间范围选项

为了支持使用此库的先前版本的代码,以及简化指定基于时间范围的`claim_spec`,您可以使用`validation_options`表格替换任何单个`claim_spec`参数。参数应表示为键/值表格。表格的每个键都应从以下列表中选择。

使用遗留`validation_options`时,您*只能*指定这些选项。也就是说,您不能将遗留`validation_options`与其他`claim_spec`验证器混合使用。为了实现这一点,您必须向`jwt:load`/`jwt:verify_jwt_obj`函数指定多个选项。

* `lifetime_grace_period`: 定义以秒为单位的容差,以考虑生成jwt的服务器和验证它的服务器之间的时钟偏差。值应为零(`0`)或正整数。

    * When this validation option is specified, the process will ensure that the jwt contains at least one of the two `nbf` or `exp` claim and compare the current clock time against those boundaries. Would the jwt be deemed as expired or not valid yet, verification will fail.

    * When none of the `nbf` and `exp` claims can be found, verification will fail.

    * `nbf` and `exp` claims are expected to be expressed in the jwt as numerical values. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to calling:
      ```
      validators.set_system_leeway(leeway)
      ```

      and specifying as a `claim_spec`:
      ```
      {
        __jwt = validators.require_one_of({ "nbf", "exp" }),
        nbf = validators.opt_is_not_before(),
        exp = validators.opt_is_not_expired()
      }
      ```

* `require_nbf_claim`: 表示`nbf`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        nbf = validators.is_not_before(),
      }
      ```

* `require_exp_claim`: 表示`exp`声明是可选的还是必需的。值应为布尔值。

    * When this validation option is set to `true` and no `lifetime_grace_period` has been specified, a zero (`0`) leeway is implied.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        exp = validators.is_not_expired(),
      }
      ```

* `valid_issuers`: 将jwt的已验证发行者列入白名单。值应为字符串数组。

    * When this validation option is specified, the process will compare the jwt `iss` claim against the list of valid issuers. Comparison is done in a case sensitive manner. Would the jwt issuer not be found in the whitelist, verification will fail.

    * `iss` claim is expected to be expressed in the jwt as a string. Wouldn't that be the case, verification will fail.

    * Specifying this option is equivalent to specifying as a `claim_spec`:
      ```
      {
        iss = validators.equals_any_of(valid_issuers),
      }
      ```

### `validation_options`使用示例 ###

``` lua local jwt_obj = jwt:verify(key, jwt_token, { lifetime_grace_period = 120, require_exp_claim = true, valid_issuers = { "my-trusted-issuer", "my-other-trusteed-issuer" } } ) ```

# 示例

* [使用查询参数和 Cookie 进行 JWT 认证](examples/README.md#jwt-auth-using-query-and-cookie) * [使用 KID 和在 Redis 中存储密钥进行 JWT 认证](examples/README.md#jwt-auth-with-kid-and-store-keys-in-redis)

[返回目录](#table-of-contents)

# 安装

使用 Luarocks ```bash luarocks install lua-resty-jwt ```

建议直接使用最新的 [ngx_openresty 包](https://openresty.org.cn)。

此外,您需要配置 [lua_package_path](https://github.com/openresty/lua-nginx-module#lua_package_path) 指令,将您的 lua-resty-jwt 源代码树的路径添加到 ngx_lua 的 Lua 模块搜索路径中,例如:

```nginx # nginx.conf http { lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;"; ... } ```

然后在 Lua 中加载库

```lua local jwt = require "resty.jwt" ```

[返回目录](#table-of-contents)

# 使用 Docker 测试

``` ./ci script ```

[返回目录](#table-of-contents)

# 另请参阅

* ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule

[返回目录](#table-of-contents) 当指定此验证选项时,该过程将 jwt 的 iss 声明与有效发行者列表进行比较。比较区分大小写。如果在白名单中找不到 jwt 发行者,则验证将失败。

        C<iss> claim is expected to be expressed in the jwt as a string. Wouldn't that be the case, verification will fail.

        Specifying this option is equivalent to specifying as a C<claim_spec>:
C<>`
{
iss = validators.equals_any_of(valid_issuers),
}
C<>`

validation_options 用法的示例

    local jwt_obj = jwt:verify(key, jwt_token,
        {
            lifetime_grace_period = 120,
            require_exp_claim = true,
            valid_issuers = { "my-trusted-issuer", "my-other-trusteed-issuer" }
        }
    )

示例

安装

使用 Luarocks

    luarocks install lua-resty-jwt

建议直接使用最新的 ngx_openresty 包

此外,您需要配置 lua_package_path 指令,将您的 lua-resty-jwt 源代码树的路径添加到 ngx_lua 的 Lua 模块搜索路径中,例如:

        # nginx.conf
        http {
            lua_package_path "/path/to/lua-resty-jwt/lib/?.lua;;";
            ...
        }

然后在 Lua 中加载库

        local jwt = require "resty.jwt"

使用 Docker 测试

    ./ci script

另请参阅

  • ngx_lua 模块:http://wiki.nginx.org/HttpLuaModule

作者

Christian Battaglia (cdbattags) 由 toopy 临时分叉

许可证

apache2

依赖项

jkeys089/lua-resty-hmac >= 0.02, luajit

版本