百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Nginx鉴权,验证token

off999 2025-01-17 12:35 15 浏览 0 评论

背景

最近公司安全组给我们提了一个安全问题,说我们的静态资源图片没有做权限限制,拿到URL谁都可以访问,我们的静态资源都是由Nginx这个服务器直接做的映射,只有拿到对的URL确实可以随便访问,无奈,网上百度了下,问了下同事,那就做token验证吧,在有效期内验证通过才可以访问。
要做token验证,Nginx首先需要支持lua这个脚本语言。

Lua是一个嵌入式脚本语言,Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。 一个完整的Lua解释器不过200k,在所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择. 这个描述来着百度百科。
https://baike.baidu.com/item/lua/7570719?fr=aladdin

我们的Nginx默认是不支持的Lua脚本的,需要重新编译安装。

1. 安装Lua

cd  /root/server/nginx2
wget -c http://luajit.org/download/LuaJIT-2.0.4.tar.gz
tar xzvf LuaJIT-2.0.4.tar.gz
# 编译安装并指定安装目录
make install PREFIX=/root/server/install/luajit
# 建立一个软连接,虽然我也没明白为啥要这么做,但是不这么做,后面可能会报错
ln -s /root/server/install/luajit/lib/libluajit-5.1.so.2  /lib64/libluajit-5.1.so.2

安装完成之后,需要添加到环境变量中:

vim /etc/profile
export LUAJIT_LIB=/root/server/install/luajit/lib
export LUAJIT_INC=/root/server/install/luajit/include/luajit-2.0
# 是环境变量生效
source /etc/profile

2. 下载安装NDK

ngx_devel_kit简称NDK,提供函数和宏处理一些基本任务,减轻第三方模块开发的代码量。
wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
tar -zxvf v0.3.0.tar.gz

下载解压即可,无需安装,后面编译ng的时候指定到这个目录即可。

3. 下载Nginx的扩展模块 lua-nginx-module

 同样不需要编译,解压即可
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz

tar -zxvf v0.10.9rc7.tar.gz 

4. 下载安装Nginx

# 安装依赖
yum install -y openssl openssl-devel zlib zlib-devel pcre-devel
wget https://nginx.org/download/nginx-1.14.2.tar.gz
tar -zxvf nginx-1.14.2.tar.gz 
# 配置安装的目录,和前面提到的依赖模块,指定到自己下载的模块目录
./configure --prefix=/root/server/nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --add-module=/root/server/soft/lua-nginx-module-0.10.9rc7 --add-module=/root/server/soft/ngx_devel_kit-0.3.0 --with-stream

make
make install

到这儿nginx就安装完成了,启动下nginx就可以在浏览器输入ip和80端口就可以访问了。

5. 下载jwt模块

wget https://github.com/SkyLothar/lua-resty-jwt

这个实际上用到的只是里面的lib/rest这个里面的脚本文件,其他的要不要无所谓。

然后在nginx.conf配置jwt

 lua_package_path "/root/server/install/luajit/share/lua/5.1/lua-resty-jwt-0.1.11/lib/?.lua;;";
server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            root   html;
            index  index.html index.htm;
        }
           location = /verify {
            default_type text/html;
            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))
            ';
        }

重启ng之后,你会发现是不行的,会有各种错误等着你,去error.log中

2022/06/13 09:53:37 [error] 45509#0: *1 lua entry thread aborted: runtime error: content_by_lua(nginx.conf:53):4: attempt to call field 'sya' (a nil value)
stack traceback:
coroutine 0:
        content_by_lua(nginx.conf:53): in function <content_by_lua(nginx.conf:53):1>, client: 192.168.78.1, server: localhost, request: "GET /lua_test HTTP/1.1", host: "192.168.78.103"
2022/06/13 10:05:27 [error] 45683#0: *1 lua entry thread aborted: runtime error: content_by_lua(nginx.conf:66):2: module 'cjson' not found:
        no field package.preload['cjson']
        no file '/root/server/install/luajit/share/lua/5.1/lua-resty-jwt-0.1.11/lib/cjson.lua'
        no file './cjson.lua'
        no file '/root/server/install/luajit/share/luajit-2.0.4/cjson.lua'
        no file '/usr/local/share/lua/5.1/cjson.lua'
        no file '/usr/local/share/lua/5.1/cjson/init.lua'
        no file '/root/server/install/luajit/share/lua/5.1/cjson.lua'
        no file '/root/server/install/luajit/share/lua/5.1/cjson/init.lua'
        no file './cjson.so'
        no file '/usr/local/lib/lua/5.1/cjson.so'
        no file '/root/server/install/luajit/lib/lua/5.1/cjson.so'
        no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:

首先是cjon 找不到,所以这个时候你需要安装cjson, 可以在这下载
https://download.csdn.net/download/u010741032/85676192,也可以去github去下载

下载好CJSON之后,需要编译,修改Makefile文件,将LUA_INCLUDE_DIR 改为lua安装的目录

LUA_VERSION =       luajit-2.0
TARGET =            cjson.so
PREFIX =            /root/server/install/luajit
#CFLAGS =            -g -Wall -pedantic -fno-inline
CFLAGS =            -O3 -Wall -pedantic -DNDEBUG
CJSON_CFLAGS =      -fpic
CJSON_LDFLAGS =     -shared
LUA_INCLUDE_DIR =   /root/server/install/luajit/include/luajit-2.0
LUA_CMODULE_DIR =   $(PREFIX)/lib/lua/$(LUA_VERSION)
LUA_MODULE_DIR =    $(PREFIX)/share/lua/$(LUA_VERSION)
LUA_BIN_DIR =       $(PREFIX)/bin

修改好之后,就可以编译了

[root@node03 lua-cjson-2.1.0]# make && make install
make: Nothing to be done for `all'.
mkdir -p //root/server/install/luajit/lib/lua/luajit-2.0
cp cjson.so //root/server/install/luajit/lib/lua/luajit-2.0
chmod 755 //root/server/install/luajit/lib/lua/luajit-2.0/cjson.so

编译安装之后会生成一个cjson.so文件,复制到了这个
//root/server/install/luajit/lib/lua/luajit-2.0 目录下,

需要把这个添加到环境变量中去:

export LUA_CPATH=/root/server/install/luajit/lib/lua/luajit-2.0/?.so

source /etc/profile生效之后,再访问token,还是报错

        [C]: in function 'require'
        content_by_lua(nginx.conf:65):2: in function <content_by_lua(nginx.conf:65):1>, client: 192.168.78.1, server: localhost, request: "GET /verify HTTP/1.1", host: "192.168.78.103"
2022/06/13 12:11:58 [error] 55127#0: *1 open() "/root/server/nginx/html/verfiy" failed (2: No such file or directory), client: 192.168.78.1, server: localhost, request: "GET /verfiy HTTP/1.1", host: "192.168.78.103"
2022/06/13 12:12:10 [error] 55127#0: *1 lua entry thread aborted: runtime error: ...jit/share/lua/5.1/lua-resty-jwt-0.1.11/lib/resty/jwt.lua:1: module 'cjson.safe' not found:
        no field package.preload['cjson.safe']
        no file '/root/server/install/luajit/share/lua/5.1/lua-resty-jwt-0.1.11/lib/cjson/safe.lua'
        no file './cjson/safe.lua'
        no file '/root/server/install/luajit/share/luajit-2.0.4/cjson/safe.lua'
        no file '/usr/local/share/lua/5.1/cjson/safe.lua'
        no file '/usr/local/share/lua/5.1/cjson/safe/init.lua'
        no file '/root/server/install/luajit/share/lua/5.1/cjson/safe.lua'
        no file '/root/server/install/luajit/share/lua/5.1/cjson/safe/init.lua'
        no file './cjson/safe.so'
        no file '/usr/local/lib/lua/5.1/cjson/safe.so'
        no file '/root/server/install/luajit/lib/lua/5.1/cjson/safe.so'
        no file '/usr/local/lib/lua/5.1/loadall.so'
        no file './cjson.so'
        no file '/usr/local/lib/lua/5.1/cjson.so'
        no file '/root/server/install/luajit/lib/lua/5.1/cjson.so'
        no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:

这个时候其实是缺少脚本文件了,缺少的是jwt依赖的文件

https://github.com/jkeys089/lua-resty-hmac/tree/master/lib/resty
https://github.com/openresty/lua-resty-string/tree/master/lib/resty

将这里面的lua文件copy到jwt的那个resty目录下,也可以直接下载jwt文件
https://download.csdn.net/download/u010741032/85676043

所以需要的lua文件如下:

这个时候是可以的了。
现在我们就可以写我们的脚本了 nginx-jwt.lua

local jwt = require "resty.jwt"
local cjson = require "cjson"
--your secret
local secret = "5pil6aOO5YaN576O5Lmf5q+U5LiN5LiK5bCP6ZuF55qE56yR"

local M = {}

function M.auth(claim_specs)
    -- require Authorization request header
    local auth_header = ngx.var.http_Authorization

    if auth_header == nil then
        ngx.log(ngx.WARN, "No Authorization header")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

    ngx.log(ngx.INFO, "Authorization: " .. auth_header)

    -- require Bearer token
    local _, _, token = string.find(auth_header, "Bearer%s+(.+)")

    if token == nil then
        ngx.log(ngx.WARN, "Missing token")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

    ngx.log(ngx.INFO, "Token: " .. token)

    local jwt_obj = jwt:verify(secret, token)
    if jwt_obj.verified == false then
        ngx.log(ngx.WARN, "Invalid token: ".. jwt_obj.reason)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

    ngx.log(ngx.INFO, "JWT: " .. cjson.encode(jwt_obj))

    -- write the uid variable
    ngx.var.uid = jwt_obj.payload.sub
end

return M

secret 这个秘钥需要转为base64即可。

然后配置nginx.con文件:

 lua_package_path "/root/server/install/luajit/share/lua/5.1/lua-resty-jwt-0.1.11/lib/?.lua;;";
server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            root   html;
            index  index.html index.htm;
        }

       location /logo {
             access_by_lua_block {
        local obj = require('nginx-jwt')
        obj.auth()
      }
        root   /root/server/data/;
            index  index.html index.htm;
        }

6. openresty

这么安装实际上太麻烦了,可以直接用openresty 这个集成了各种库的软件来搞,因为它本身就已经集成了很多库,比如cjson,加解密模块sha256等,这么安装要简单的多:

wget https://openresty.org/download/openresty-1.19.3.1.tar.gz

//配置安装目录,
./configure  --prefix=/root/server/nginx/openresty
make
make install

然后再配置下jwt 就完了,简单得多了。

参考连接:

https://www.base64encode.org/
https://www.cnblogs.com/lgj8/p/12065909.html?share_token=60565328-6d91-473b-bd2c-67aabf8105eb
https://wiki.jikexueyuan.com/project/openresty/lua/class.html
https://github.com/SkyLothar/lua-resty-jwt/releases

相关推荐

30s带你使用Python打包exe文件,并修改其图标

在Python中,我们可以使用PyInstaller或cx_Freeze等工具将Python脚本打包成可执行文件(.exe),并且能够修改生成的.exe文件的图标。使用PyInstaller...

Python一键打包为windows的exe文件,无需安装python环境即可执行

一、为什么要将Python打包为exe?在实际应用中,我们希望Python程序能在没有安装Python环境的电脑上直接运行。将Python代码打包为exe可执行文件,不仅能解决环境依赖问题,还便于程...

py2exe实现python文件打包为.exe可执行程序(上篇)

今天分享的内容为:python程序实现发送、读取邮件来控制电脑的关机与重启(作为py2exe打包成.exe可执行程序的基础文件)一、说明:本文介绍的是使用新浪邮箱作为例子进行讲解,代码实现如下:#c...

如何将python程序文件打包生成一个可执行文件(exe文件)

在开发Python程序后,有时我们希望将其打包成一个可执行的exe文件,方便在没有Python环境的计算机上运行。下面将详细介绍使用常见工具实现这一目标的方法。安装PyInstaller...

Python程序打包为EXE的全面指南:从入门到精通

引言在Python开发中,将程序打包成可执行文件(EXE)是分发应用程序的重要环节。通过打包,我们可以创建独立的可执行文件,让没有安装Python环境的用户也能运行我们的程序。本篇文章将详细介绍如何使...

10个你没有充分利用的令人惊叹的 Python 特性

Python的简单性和多功能性使其成为全球开发人员的最爱。每天有超过1000万开发者使用Python进行从网络开发、机器学习到网络脚本等各种开发,Python的功能非常强大。然而,我们中的...

编程语言可以用来做什么

1.web前端你每天浏览的网页,所看到的页面特效,均是由web前端工程师来实现的2.Java大型购物网站有关通信及网络企业大型企业级应用管理系统大型网游后台数据3.C++嵌入式三维游戏领域人工智能领域...

用Python进行机器学习(16)-内容总结

对于用Python进行机器学习的内容,到这里就要做一个阶段性总结啦,后续再写的文章就是关于深度学习的了,算是对该部分内容的进阶版。对于机器学习,我们主要介绍了五个方面的内容:第一个就是分类算法,主要包...

普通人如何利用python做自媒体赚收益

普通人利用Python做自媒体赚收益,最简单的方式是下载某些网站的视频,并利用剪影编辑视频,最后导出发布,每天可以制作个10几条,并设置好定时发布,每天如此坚持下去,一定会有所收获的...

AI能写什么做什么?这些技能已经颠覆你的认知!

在ChatGPT、文心一言等AI工具爆火的今天,人工智能早已不再是科幻电影里的概念,而是实实在在地渗透进我们的生活。**AI到底能写什么?能做什么?它的边界在哪里?**让我们一探究竟!---**1....

Python 3.14 新特性盘点,更新了些什么?

Python3.14.0稳定版将于2025年10月正式发布,目前已进入beta测试阶段。这意味着在往后的几个月里,3.14的新功能已冻结,不再合入新功能(除了修复问题和完善文档)。3...

每天一个Python库:sys模块的5个高频用法(建议收藏)

很多人学Python,一直卡在“写不了实用脚本”。其实,会用标准库,效率直接翻倍。今天分享的是:sys模块。这个模块虽然基础,但非常实用,下面是我亲测常用的5个功能1.获取命令行参数(自动化脚...

Python除了做爬虫抓数据还能做什么?其实还能监视和衡量网站性能

  借助这份对初学者友好的指南,您可以构建自己的自定义Python脚本来自动测量网站的关键速度和性能指标。  在过去的一个月中,Google宣布了许多通过关键速度和性能指标来衡量用户体验的方法。  巧...

python究竟可以用来做些什么

这里就不撰述python的一些像什么“高级语言”之类的比较常规的介绍了,还是老样子,说说一些比较常用的东西吧。python是什么python,一款可编程的开源软件,很多第三方库、框架也是开源的,比如强...

Python 实现 dubbo 协议接口自动化测试

前言python语言也可以实现对dubbo协议的接口进行调用与测试,可以使用python+hessian结合的方式,也可以使用python+telnet结合的方式模拟命令行的模式来实现对...

取消回复欢迎 发表评论: