Nginx系列-12 Nginx使用Lua脚本进行JWT校验

news2024/11/19 19:46:00

背景

本文介绍Nginx中Lua模块使用方式,并结合案例进行介绍。案例介绍通过lua脚本提取HTTP请求头中的token字段,经过JWT校验并提取id和name信息,设置到http请求头中发向后段服务器。
默认情况下,Nginx自身不携带lua模块,即不支持通过lua脚本进行功能扩展。需要在编译Nginx时手动引入lua模块,或者直接使用openresty,本文结合后者进行介绍。

1.openresty安装流程

1.1 安装包下载

wget https://openresty.org/download/openresty-1.25.3.1.tar.gz
tar -zxvf openresty-1.25.3.1.tar.gz
cd openresty-1.25.3.1/

1.2 配置

./configure --prefix=/usr/local/ewen/nginx --with-luajit --without-http_redis2_module --with-http_ssl_module --with-http_sub_module --with-http_stub_status_module --with-http_dav_module --with-http_mp4_module --with-http_v2_module 

由于案例不涉及使用Redis,因此可以在configure阶段通过–without-http_redis2_module以最小化安装。
执行结果如下:

platform: linux (linux)

...

Type the following commands to build and install:
    gmake
    gmake install

1.3 编译和安装

gmake
gmake install

1.4 案例测试

1.4.1 测试nginx正常工作

修改配置,添加一个location:

location /test {
    return 200 "test success";
}

运行nginx后:

[root@124 sbin]# curl http://localhost:8765/test
test success

1.4.2 测试nginx的lua插件正常工作

修改配置,添加一个location:

location /lua{
    content_by_lua 'ngx.say("<h1>HELLO,Lua</h1>")';
}

运行nginx后:

[root@124 sbin]# curl http://localhost:8765/lua
<h1>HELLO,Lua</h1>

2.lua介绍

参考: Lua使用方式介绍

3.http处理流程与lua模块

如Nginx系列-12 HTTP消息处理流程文中介绍,Nginx处理HTTP消息的流程可以分为如下11个阶段:
在这里插入图片描述
Lua模块可以参与rewrite、access、content、log阶段,流程和对应指令如下所示:
在这里插入图片描述

当使用lua生成HTTP响应内容时,在content阶段处理对应content_by_lua指令,而进行请求校验时在access阶段处理,对应access_by_lua_block或者access_by_lua_file指令。

4.案例介绍

案例介绍通过lua实现校验请求是否合法:请求头中带有合法的token, 则通过校验,否则返回401响应。
案例使用jwt解析token,因此需要引入jwt依赖(lua-resty-jwt库),包括hmac.lua、evp.lua、jwt.lua、jwt-validators.lua; hmac.lua来源于lua-resty-jwt\vendor\resty,evp.lua、jwt.lua、jwt-validators.lua来源于lua-resty-jwt\lib\resty.
可以通过access_by_lua_block块的形式或者access_by_lua_file文件形式引入lua文件,本文选择后者。

4.1 lua文件介绍

ewen.lua文件内容如下:

local white_url_list = {'/open'};

-- 修改为自己的jwt密钥
public_key = "......";

function startsWith(str, prefix)
    return string.sub(str, 1, string.len(prefix)) == prefix;
end

local function exit_with_code_msg(code, msg)
    ngx.status = code;
    ngx.say(msg);
    ngx.exit(code);
end

local function get_jwt_claims(token, public_key)
    local jwt = require("resty.jwt");
    local jwt_obj, err = jwt:verify(public_key, token);
    if not jwt_obj then
        ngx.say("Failed to verify JWT: ", err);
        return nil;
    end
    return jwt_obj["payload"];
end

local function check_token_and_fill_head()
    local token = ngx.req.get_headers()["token"];
    if not token then
        exit_with_code_msg(ngx.HTTP_UNAUTHORIZED, "401 Unauthorized: Token not found or invalid");
    end

    local payload = get_jwt_claims(token, public_key)
    if not payload then
        exit_with_code_msg(ngx.HTTP_UNAUTHORIZED, "401 Unauthorized: Token not found or invalid");
    end
    ngx.req.set_header("id", tostring(payload["id"]));
    ngx.req.set_header("name", tostring(payload["name"]));
    ngx.req.set_header("role", tostring(payload["role"]));
end

local function need_check()
    for _, path in ipairs(white_url_list) do
        if startsWith(ngx.var.request_uri, path) then
            return true;
        end
    end
    return false;
end

if not need_check() then
    ngx.log(ngx.INFO, "JWT: " .. tostring(ngx.var.request_uri) .. "  check.");
    check_token_and_fill_head()
else
    ngx.log(ngx.INFO, "JWT: " .. tostring(ngx.var.request_uri) .. " not need to check.");
end

其中: ngx.status属性表示HTTP响应状态码;ngx.say方法用于设置响应体内容;ngx.exit(code)用于设置状态码并直接返回给客户端(结束请求);ngx.req.set_header方法用于设置请求头;require(“resty.jwt”)表示引入jwt库,之后jwt:verify方法用于对token进行JWT校验和Claim信息提取。

4.2 配置lua文件

在nginx.conf文件的http块或者server块中添加:

access_by_lua_file ./lua/jwt.lua;

4.3 案例测试

分别使用带token和不带token进行测试:

[root@124 conf]# curl -X GET http://localhost:8765/lua
401 Unauthorized: Token not found or invalid

[root@124 conf]# curl -X GET -H "token:eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3MTk5NzkyMjEsInV1aWQiOiI1Y2M4OGYwZC1hNGM5LTQyNTItODdkMC1hNzZkNmQxNzEzZTEiLCJncmFudFR5cGUiOiJzYWMiLCJidXNpbmVzcyI6ImVjaGF0OnVlOjE5NjAwMDEwMDk4Iiwic2NvcGUiOiJlY2hhdDpldHMtY2FyZXRha2VyIGVjaGF0OmV0cy1lbXBsb3llZSBlY2hhdDplZXAiLCJsb2dpbkluZm8iOiJlY2hhdDp1ZToxOTYwMDAxMDA5OCIsInVzZXJJZCI6LTEsInZlcnNpb24iOiIxLjAuMCJ9.augjMcBV7BKXOb4_JjIcZK4RGuYDoVf73DksFVR8o49F1yQWZiRn07ZH_xmt2RnJmpwRtg-fUmIGn7tNv3Q7Dg" http://localhost:8765/lua
<h1>HELLO,Lua</h1>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1955092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Transformer中的Multi-head Attention机制解析——从单一到多元的关注效益最大化

Transformer中的Multi-head Attention机制解析——从单一到多元的关注效益最大化 Multi-head Attention的核心作用 组件/步骤描述多头注意力机制&#xff08;Multi-head Attention&#xff09;Transformer模型中的关键组件&#xff0c;用于处理序列数据功能允许模型同时关注到…

Vue2从基础到实战(指令篇)

Vue中的常用指令&#xff01; 概念&#xff1a;指令&#xff08;Directives&#xff09;是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。 vue 中的指令按照不同的用途可以分为如下 6 大类&#xff1a; 内容渲染指令&#xff08;v-html、v-text&#xff09; 条件渲染指令&…

昇思25天学习打卡营第1天|快速入门-构建基于MNIST数据集的手写数字识别模型

非常感谢华为昇思大模型平台和CSDN邀请体验昇思大模型&#xff01;从今天起&#xff0c;我将以打卡的方式&#xff0c;结合原文搬运和个人思考&#xff0c;分享25天的学习内容与成果。为了提升文章质量和阅读体验&#xff0c;我会将思考部分放在最后&#xff0c;供大家探索讨论…

04 | 深入浅出索引(上)

此系列文章为极客时间课程《MySQL 实战 45 讲》的学习笔记&#xff01; 索引的常见模型 可以提供查询效率的数据结构有很多&#xff0c;常见的有三种&#xff1a;哈希表、有序数组、搜索数。 哈希表是一种以 key-value 形式存储的数据结构。输入一个 key&#xff0c;通过固定…

Markdown使用~~pandoc插件安装

目录 1.两大秘密武器 2.vscode创作 3.Typora的安装 4.pandoc安装 4.1百度网盘 4.2按照说明安装 4.3到达github里面下载 4.4选择对应版本 4.5进入偏好设置 4.6对于导出的路径进行配置 5.Typora和vscode的对比 6.如何正确的学习这个Typora软件 7.一点相关的说明 1.两…

做一个能和你互动玩耍的智能机器人之三

内容节选自英特尔的开源项目openbot的body目录下diy下的readme&#xff0c;这是一个组装和连线方式的说明文档&#xff0c;接线需要配合firmware固件使用&#xff0c;固件代码的接线柱是对应的。 body目录内部十分丰富&#xff0c;主要介绍了这个项目的背景和硬件以及如何让他…

datawhale逻辑推理赛题01

跟着datawhale参加了逻辑推理赛题&#xff0c;这个是一个大模型比赛入门非常好的比赛&#xff0c;可以帮助我们更快的上手大模型相关的业务 我参加的是天池的这个比赛&#xff0c;跟着datawhale官方的baseline01已经上分0.6498&#xff0c;是一个非常好的开始 后续我讲继续跟着…

java项目中添加SDK项目作为依赖使用(无需上传Maven)

需求&#xff1a; 当需要多次调用某个函数或算法时&#xff0c;不想每次调用接口都自己编写&#xff0c;可以将该项目打包&#xff0c;以添加依赖的方式实现调用 适用于&#xff1a; 无需上线的项目&#xff0c;仅公司或团队内部使用的项目 操作步骤&#xff1a; 以下面这…

Linux---进程(2)

目录 查看进程 查看进程pid 系统目录查看 理解当前工作目录用途 fork创建进程 存在问题 问题解决 问题一 问题二 本文介绍进程标识符的相关知识以及创建子进程。 查看进程 指令就是可执行程序&#xff0c;每次运行时&#xff0c;都需要被加载到内存&#xff0c;运行…

动物之森-小红书2024笔试(codefun2000)

题目链接 动物之森-小红书2024笔试(codefun2000) 题目内容 塔子哥最近在玩一款叫做“动物之森”的四字开放游戏世界。由于塔子哥氪金了&#xff0c;所以他在游戏中拥有很多个宝箱&#xff0c;每个宝箱里都装着一些他收集的宝石。每一种类型的宝石都有不同的作用。 有一天&…

java--jvm虚拟机(都是要点)

请带着以下问题&#xff0c;学习并理解jvm 问题一&#xff1a; 为什么fullGC会对系统性能有影响&#xff1f;youngGC却几乎没有&#xff1f; 问题二&#xff1a; outofmemory是什么异常&#xff1f;什么时候会出现&#xff1f;如何处理&#xff1f; 问题三&#xff1a; 线程…

鸿蒙 HarmonyOS NEXT端云一体化开发-云函数篇

前言 TODO&#xff1a;新建项目和应用&#xff0c;开通云函数服务&#xff08;AGC&#xff09;端侧开发&#xff1a;Arkts界面开发云测开发&#xff1a;云函数、认证服务、云存储、云数据库 一、登录 地址&#xff1a;https://id1.cloud.huawei.com/CAS/portal/loginAuth.htm…

Nginx周末部署

背景 Nginx是本人学习的一类中间件&#xff0c;上次完成了vue的搭建&#xff0c;所以顺便把项目加入Nginx吧 1. 镜像拉取与测试 查询dockerHub&#xff0c;选择最新最稳定的版本 docker pull nginx:stable-perl 执行下载 docker run -d --name mynginx -p 8080:80 -v D:\IM…

【Kubernetes】配置管理(一):ConfigMap

配置管理&#xff08;一&#xff09;&#xff1a;ConfigMap 1.配置管理2.使用 ConfigMap 管理 Pod 的配置信息2.1 创建 ConfigMap2.1.1 在命令行中通过指定 ConfigMap 的参数进行创建2.1.2 通过指定的配置文件创建 ConfigMap2.1.3 通过一个文件内的多个键值对创建 ConfigMap2.1…

C++数据结构重要知识点(3)(红黑树及其插入操作)

1.红黑树和AVL树的区别 红黑树和AVL树都是平衡树&#xff0c;都是为了解决二叉搜索树的劣势。其中&#xff0c;AVL树的左右子树的高度差不超过1&#xff0c;而红黑树的最长路径不超过最短路径的二倍&#xff0c;也就是说&#xff0c;红黑树是一种近似平衡&#xff0c;而AVL树是…

【设计模式】(万字总结)深入理解Java中的创建型设计模式

1. 前言 在软件开发的世界里&#xff0c;设计模式是一种被广泛接受并应用的解决方案。它们不仅仅是代码的设计&#xff0c;更是对问题的思考和解决的方法论。在Java开发中&#xff0c;特别是在面向对象的编程中&#xff0c;设计模式尤为重要。创建型设计模式&#xff0c;作为设…

JavaScript安全编程宝典【万字详解】

文章目录 简介基本说明特点两种使用方式在script中写使用script标签引入JS文件 数据类型介绍特殊值 运算符算数运算符赋值运算符逻辑运算符&#xff1a;条件运算符 数组的定义基本使用数组的遍历 函数含义函数定义方式基本语法代码示例 细节和注意事项 自定义对象Object形式{} …

解决mysql数据库表读取中文乱码问题

本文目录 0、省流1、问题出现2、问题排查3、结论 0、省流 在服务器上创建数据库服务时&#xff0c;使用的sql脚本加载的数据库表&#xff0c;其中脚本中有一些预设的测试数据包含中文汉字&#xff0c;由于linxu服务器控制台默认编码是lantin1&#xff0c;导致中文通过该编码方…

鸿蒙HarmonyOS开发:多种内置弹窗及自定义弹窗的详细使用指南

文章目录 一、消息提示框&#xff08;showToast&#xff09;1、导入模块2、语法3、参数4、示例5、效果 二、对话框&#xff08;showDialog&#xff09;1、导入模块2、语法3、参数4、示例5、效果 三、警告弹窗&#xff08;AlertDialog&#xff09;1、语法2、参数3、AlertDialogP…

JDBC(Java访问数据库)

Java Database Connectivity&#xff1a;Java访问数据库的解决方案 JDBC定义了一套标准接口&#xff0c;即访问数据库的通用API&#xff0c; 不同的数据库厂商根据各自数据库的特点去实现这些接口。 JDBC希望用相同的方式访问不同的数据库&#xff0c;让具体的数据库操作与数…