一、啥是 JWT 认证

JWT 就是 JSON Web Token 的缩写,简单来说,它是一种用于在网络应用间传递声明的安全方式。打个比方,你去一个高档小区,保安会给你一张临时通行证,这个通行证就好比 JWT。小区居民(客户端)拿着这张通行证(JWT),就能在小区里自由活动(访问 API)。

JWT 一般由三部分组成,分别是头部(Header)、载荷(Payload)和签名(Signature)。头部主要说明这个 JWT 用的是什么算法;载荷就是包含一些用户信息,像用户名、角色啥的;签名则是用来验证这个 JWT 的真实性。

二、OpenResty 是个啥

OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,它把很多 Nginx 模块集成在一起,让开发者能轻松地用 Lua 脚本扩展 Nginx 的功能。就好比你有一把普通的菜刀,OpenResty 给这把菜刀装上了各种不同的刀头,让它能切菜、切肉还能雕花。

OpenResty 有很多优点,它性能高,能处理大量并发请求;开发起来也方便,用 Lua 脚本就能快速实现各种功能。

三、为啥要用 OpenResty 实现 JWT 认证

应用场景

在很多 Web 应用里,API 的安全访问控制非常重要。比如说一个电商平台,用户登录后要访问自己的订单信息、修改个人资料等,这些操作都需要进行身份验证。用 OpenResty 实现 JWT 认证,就能很好地控制用户对 API 的访问。

技术优缺点

优点

  • 高性能:OpenResty 基于 Nginx,能处理大量并发请求,响应速度快。就像一个高效的交通指挥系统,能让车辆(请求)快速通过。
  • 灵活性:用 Lua 脚本可以灵活地实现各种认证逻辑,开发者可以根据自己的需求定制。
  • 跨平台:可以在不同的操作系统上运行,兼容性好。

缺点

  • 学习成本:对于没有 Lua 基础的开发者来说,可能需要花一些时间学习 Lua 语言。
  • 调试难度:由于涉及到 Nginx 和 Lua,调试起来可能会比较复杂。

注意事项

  • 要妥善保管好 JWT 的密钥,一旦密钥泄露,整个认证体系就会变得不安全。
  • 要设置合理的 JWT 过期时间,避免过期时间过长导致安全风险,也不能过短影响用户体验。

四、动手实现 JWT 认证

安装 OpenResty

首先得安装 OpenResty,不同的操作系统安装方法不太一样。以 Ubuntu 为例,我们可以用下面的命令来安装:

# 导入 OpenResty 的 GPG 密钥
wget -qO - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
# 添加 OpenResty 的软件源
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
# 更新软件源
sudo apt-get update
# 安装 OpenResty
sudo apt-get install openresty

生成 JWT

我们用 Lua 脚本来生成 JWT。这里要用到 lua-resty-jwt 这个库,它可以方便地生成和验证 JWT。

-- 技术栈:Lua
-- 引入 lua-resty-jwt 库
local jwt = require "resty.jwt"

-- 定义 JWT 的密钥
local secret = "your_secret_key"

-- 定义 JWT 的载荷
local payload = {
    sub = "user123",
    name = "John Doe",
    role = "admin"
}

-- 生成 JWT
local jwt_obj = jwt:sign(secret, {
    header = { typ = "JWT", alg = "HS256" },
    payload = payload
})

-- 打印生成的 JWT
ngx.say("Generated JWT: ", jwt_obj)

在这个示例中,我们首先引入了 lua-resty-jwt 库,然后定义了 JWT 的密钥和载荷。接着用 jwt:sign 方法生成 JWT,并把生成的 JWT 打印出来。

验证 JWT

下面我们来写一个 Lua 脚本来验证 JWT:

-- 技术栈:Lua
-- 引入 lua-resty-jwt 库
local jwt = require "resty.jwt"

-- 定义 JWT 的密钥
local secret = "your_secret_key"

-- 获取请求头中的 Authorization 字段
local auth_header = ngx.var.http_authorization
if not auth_header then
    ngx.status = ngx.HTTP_UNAUTHORIZED
    ngx.say("Authorization header missing")
    return
end

-- 提取 JWT
local _, _, token = string.find(auth_header, "Bearer%s+(.+)")
if not token then
    ngx.status = ngx.HTTP_UNAUTHORIZED
    ngx.say("Invalid Authorization header")
    return
end

-- 验证 JWT
local jwt_obj = jwt:verify(secret, token)
if not jwt_obj.verified then
    ngx.status = ngx.HTTP_UNAUTHORIZED
    ngx.say("Invalid JWT")
    return
end

-- JWT 验证通过
ngx.say("JWT verified successfully")

在这个示例中,我们首先获取请求头中的 Authorization 字段,然后提取出 JWT。接着用 jwt:verify 方法验证 JWT,如果验证通过,就输出 JWT verified successfully,否则返回 Invalid JWT

配置 Nginx

我们要在 Nginx 的配置文件里配置 JWT 认证。假设我们有一个 API 接口 /api/user,只有通过 JWT 认证的用户才能访问。

http {
    # 加载 lua-resty-jwt 库
    lua_package_path "/path/to/lua-resty-jwt/?.lua;;";

    server {
        listen 80;
        server_name example.com;

        location /api/user {
            # 执行 Lua 脚本进行 JWT 验证
            access_by_lua_file /path/to/verify_jwt.lua;

            # 处理请求
            proxy_pass http://backend_server;
        }
    }
}

在这个配置文件中,我们首先加载了 lua-resty-jwt 库,然后在 /api/user 这个接口的配置里,用 access_by_lua_file 指令执行 verify_jwt.lua 脚本来验证 JWT。如果验证通过,就把请求转发到后端服务器。

五、总结

通过 OpenResty 实现 JWT 认证,我们可以构建一个安全的 API 访问控制体系。OpenResty 的高性能和灵活性让我们能轻松地实现各种认证逻辑,而 JWT 则提供了一种安全、便捷的身份验证方式。在实际应用中,我们要注意保管好 JWT 的密钥,设置合理的过期时间,确保认证体系的安全性。