ARM环境编译Openresty,并通过lua脚本鉴权文件服务

制作Openresty镜像

下载Dockerfile

git地址:https://github.com/openresty/docker-openresty/tree/1.27.1.1-1/alpine
需要把Dockerfile、nginx.conf、nginx.vh.default.conf下载下来

修改Dockerfile

# Dockerfile - alpine
# https://github.com/openresty/docker-openresty
# 这儿修改成自己的alpine arm镜像
# 可从docker hub上拉取
# docker pull alpine:3.21@sha256:757d680068d77be46fd1ea20fb21db16f150468c5e7079a08a2e4705aec096ac
# 推送到自己的docker仓库
ARG RESTY_IMAGE_BASE="alpine"
ARG RESTY_IMAGE_TAG="3.21"

FROM ${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG}

LABEL maintainer="Eugene <925718725@qq.com>"

# Docker Build Arguments
# 这儿同上
ARG RESTY_IMAGE_BASE="alpine"
ARG RESTY_IMAGE_TAG="3.21"
ARG RESTY_VERSION="1.27.1.1"

# https://github.com/openresty/openresty-packaging/blob/master/alpine/openresty-openssl3/APKBUILD
ARG RESTY_OPENSSL_VERSION="3.0.15"
ARG RESTY_OPENSSL_PATCH_VERSION="3.0.15"
# 这儿如果是内网安装可下载下来上传到本地的文件服务中,如果没有文件服务则看下面,直接把文件下载后拷贝到容器中
#ARG RESTY_OPENSSL_URL_BASE="https://github.com/openssl/openssl/releases/download/openssl-${RESTY_OPENSSL_VERSION}"
ARG RESTY_OPENSSL_URL_BASE="https://xxx.cn/group1/M00/4A/73/FDCYBWe1RdWAAazPAOm-abGvJDc8291.gz?filename=openssl-3.0.15.tar.gz"
# LEGACY:  "https://www.openssl.org/source/old/1.1.1"
ARG RESTY_OPENSSL_BUILD_OPTIONS="enable-camellia enable-seed enable-rfc3779 enable-cms enable-md2 enable-rc5 \
        enable-weak-ssl-ciphers enable-ssl3 enable-ssl3-method enable-md2 enable-ktls enable-fips \
        "

# https://github.com/openresty/openresty-packaging/blob/master/alpine/openresty-pcre2/APKBUILD
ARG RESTY_PCRE_VERSION="10.44"
ARG RESTY_PCRE_SHA256="86b9cb0aa3bcb7994faa88018292bc704cdbb708e785f7c74352ff6ea7d3175b"
ARG RESTY_PCRE_BUILD_OPTIONS="--enable-jit --enable-pcre2grep-jit --disable-bsr-anycrlf --disable-coverage --disable-ebcdic --disable-fuzz-support \
    --disable-jit-sealloc --disable-never-backslash-C --enable-newline-is-lf --enable-pcre2-8 --enable-pcre2-16 --enable-pcre2-32 \
    --enable-pcre2grep-callout --enable-pcre2grep-callout-fork --disable-pcre2grep-libbz2 --disable-pcre2grep-libz --disable-pcre2test-libedit \
    --enable-percent-zt --disable-rebuild-chartables --enable-shared --disable-static --disable-silent-rules --enable-unicode --disable-valgrind \
    "
# 根据自己的机器来定义
ARG RESTY_J="4"

# https://github.com/openresty/openresty-packaging/blob/master/alpine/openresty/APKBUILD
# 可禁用或启用nginx的组件
ARG RESTY_CONFIG_OPTIONS="\
    --with-compat \
    --without-mail_pop3_module \
    --without-mail_imap_module \
    --without-mail_smtp_module \
    --with-http_addition_module \
    --with-http_auth_request_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_geoip_module=dynamic \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_image_filter_module=dynamic \
    --with-http_mp4_module \
    --with-http_random_index_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_slice_module \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_sub_module \
    --with-http_v2_module \
    --with-http_v3_module \
    --with-http_xslt_module=dynamic \
    --with-ipv6 \
    --with-mail \
    --with-mail_ssl_module \
    --with-md5-asm \
    --with-sha1-asm \
    --with-stream \
    --with-stream_ssl_module \
    --with-stream_ssl_preread_module \
    --with-threads \
    "
ARG RESTY_CONFIG_OPTIONS_MORE=""
ARG RESTY_LUAJIT_OPTIONS="--with-luajit-xcflags='-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT'"
ARG RESTY_PCRE_OPTIONS="--with-pcre-jit"

ARG RESTY_ADD_PACKAGE_BUILDDEPS=""
ARG RESTY_ADD_PACKAGE_RUNDEPS=""
ARG RESTY_EVAL_PRE_CONFIGURE=""
ARG RESTY_EVAL_POST_DOWNLOAD_PRE_CONFIGURE=""
ARG RESTY_EVAL_POST_MAKE=""

# These are not intended to be user-specified
ARG _RESTY_CONFIG_DEPS="--with-pcre \
    --with-cc-opt='-DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/pcre2/include -I/usr/local/openresty/openssl3/include' \
    --with-ld-opt='-L/usr/local/openresty/pcre2/lib -L/usr/local/openresty/openssl3/lib -Wl,-rpath,/usr/local/openresty/pcre2/lib:/usr/local/openresty/openssl3/lib' \
    "

LABEL resty_image_base="${RESTY_IMAGE_BASE}"
LABEL resty_image_tag="${RESTY_IMAGE_TAG}"
LABEL resty_version="${RESTY_VERSION}"
LABEL resty_openssl_version="${RESTY_OPENSSL_VERSION}"
LABEL resty_openssl_patch_version="${RESTY_OPENSSL_PATCH_VERSION}"
LABEL resty_openssl_url_base="${RESTY_OPENSSL_URL_BASE}"
LABEL resty_openssl_build_options="${RESTY_OPENSSL_BUILD_OPTIONS}"
LABEL resty_pcre_version="${RESTY_PCRE_VERSION}"
LABEL resty_pcre_build_options="${RESTY_PCRE_BUILD_OPTIONS}"
LABEL resty_pcre_sha256="${RESTY_PCRE_SHA256}"
LABEL resty_config_options="${RESTY_CONFIG_OPTIONS}"
LABEL resty_config_options_more="${RESTY_CONFIG_OPTIONS_MORE}"
LABEL resty_config_deps="${_RESTY_CONFIG_DEPS}"
LABEL resty_add_package_builddeps="${RESTY_ADD_PACKAGE_BUILDDEPS}"
LABEL resty_add_package_rundeps="${RESTY_ADD_PACKAGE_RUNDEPS}"
LABEL resty_eval_pre_configure="${RESTY_EVAL_PRE_CONFIGURE}"
LABEL resty_eval_post_download_pre_configure="${RESTY_EVAL_POST_DOWNLOAD_PRE_CONFIGURE}"
LABEL resty_eval_post_make="${RESTY_EVAL_POST_MAKE}"
LABEL resty_luajit_options="${RESTY_LUAJIT_OPTIONS}"
LABEL resty_pcre_options="${RESTY_PCRE_OPTIONS}"

# 这儿拷贝一些需要用到的文件到容器内,如果没有文件服务,也可从这儿直接下载拷贝到容器中
COPY hosts /etc/hosts
COPY openresty-1.27.1.1.tar.gz /openresty-1.27.1.1.tar.gz
COPY openssl-3.0.15.tar.gz /openssl-3.0.15.tar.gz
COPY pcre2-10.44.tar.gz /pcre2-10.44.tar.gz


RUN apk add --no-cache --virtual .build-deps \
        build-base \
        coreutils \
        curl \
        gd-dev \
        geoip-dev \
        libxslt-dev \
        linux-headers \
        make \
        perl-dev \
        readline-dev \
        zlib-dev \
        ${RESTY_ADD_PACKAGE_BUILDDEPS} \
    && apk add --no-cache \
        gd \
        geoip \
        libgcc \
        libxslt \
        tzdata \
        zlib \
        ${RESTY_ADD_PACKAGE_RUNDEPS} \
    && cd /tmp \
    && if [ -n "${RESTY_EVAL_PRE_CONFIGURE}" ]; then eval $(echo ${RESTY_EVAL_PRE_CONFIGURE}); fi \
    && cd /tmp \
    # 没有文件服务则使用下面的把文件拷贝到/tmp中
    #&& curl -fSL "${RESTY_OPENSSL_URL_BASE}" -o openssl-${RESTY_OPENSSL_VERSION}.tar.gz \
    && mv /openssl-${RESTY_OPENSSL_VERSION}.tar.gz  /tmp/openssl-${RESTY_OPENSSL_VERSION}.tar.gz \
    && tar xzf openssl-${RESTY_OPENSSL_VERSION}.tar.gz \
    && cd openssl-${RESTY_OPENSSL_VERSION} \
    && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "3.0.15" ] ; then \
        echo 'patching OpenSSL 3.0.15 for OpenResty' \
        # 这儿使用了国内代理加速,前面加上https://hub.gitmirror.com/
        && curl -s         https://hub.gitmirror.com/https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \
    fi \
    && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.1" ] ; then \
        echo 'patching OpenSSL 1.1.1 for OpenResty' \
        # 这儿使用了国内代理加速,前面加上https://hub.gitmirror.com/
        && curl -s https://hub.gitmirror.com/https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \
    fi \
    && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.0" ] ; then \
        echo 'patching OpenSSL 1.1.0 for OpenResty' \
        # 这儿使用了国内代理加速,前面加上https://hub.gitmirror.com/
        && curl -s https://hub.gitmirror.com/https://raw.githubusercontent.com/openresty/openresty/ed328977028c3ec3033bc25873ee360056e247cd/patches/openssl-1.1.0j-parallel_build_fix.patch | patch -p1 \
        # 这儿使用了国内代理加速,前面加上https://hub.gitmirror.com/
        && curl -s https://hub.gitmirror.com/https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \
    fi \
    && ./config \
      shared zlib -g \
      --prefix=/usr/local/openresty/openssl3 \
      --libdir=lib \
      -Wl,-rpath,/usr/local/openresty/openssl3/lib \
      ${RESTY_OPENSSL_BUILD_OPTIONS} \
    && make -j${RESTY_J} \
    && make -j${RESTY_J} install_sw \
    && cd /tmp \
    # 没有文件服务则使用下面的把文件拷贝到/tmp中
    #&& curl -fSL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-${RESTY_PCRE_VERSION}/pcre2-${RESTY_PCRE_VERSION}.tar.gz" -o pcre2-${RESTY_PCRE_VERSION}.tar.gz \
    #&& curl -fSL "https://xxx.cn/group1/M00/4A/73/FDCYBWe1RkyAFxyPACbz2DejUDQ2905.gz?filename=pcre2-10.44.tar.gz" -o pcre2-${RESTY_PCRE_VERSION}.tar.gz \
    && mv /pcre2-${RESTY_PCRE_VERSION}.tar.gz /tmp/pcre2-${RESTY_PCRE_VERSION}.tar.gz \
    && echo "${RESTY_PCRE_SHA256}  pcre2-${RESTY_PCRE_VERSION}.tar.gz" | shasum -a 256 --check \
    && tar xzf pcre2-${RESTY_PCRE_VERSION}.tar.gz \
    && cd /tmp/pcre2-${RESTY_PCRE_VERSION} \
    && CFLAGS="-g -O3" ./configure \
        --prefix=/usr/local/openresty/pcre2 \
        --libdir=/usr/local/openresty/pcre2/lib \
        ${RESTY_PCRE_BUILD_OPTIONS} \
    && CFLAGS="-g -O3" make -j${RESTY_J} \
    && CFLAGS="-g -O3" make -j${RESTY_J} install \
    && cd /tmp \
    # 没有文件服务则使用下面的把文件拷贝到/tmp中
    #&& curl -fSL https://openresty.org/download/openresty-${RESTY_VERSION}.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \
    #&& curl -fSL https://xxx.cn/group1/M00/4A/73/FDCYBWe1SgyAF70MAFrqvT8TigE1077.gz?filename=openresty-1.27.1.1.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \
    && mv /openresty-${RESTY_VERSION}.tar.gz /tmp/openresty-${RESTY_VERSION}.tar.gz \
    && tar xzf openresty-${RESTY_VERSION}.tar.gz \
    && cd /tmp/openresty-${RESTY_VERSION} \
    && if [ -n "${RESTY_EVAL_POST_DOWNLOAD_PRE_CONFIGURE}" ]; then eval $(echo ${RESTY_EVAL_POST_DOWNLOAD_PRE_CONFIGURE}); fi \
    && eval ./configure -j${RESTY_J} ${_RESTY_CONFIG_DEPS} ${RESTY_CONFIG_OPTIONS} ${RESTY_CONFIG_OPTIONS_MORE} ${RESTY_LUAJIT_OPTIONS} ${RESTY_PCRE_OPTIONS} \
    && make -j${RESTY_J} \
    && make -j${RESTY_J} install \
    && cd /tmp \
    && if [ -n "${RESTY_EVAL_POST_MAKE}" ]; then eval $(echo ${RESTY_EVAL_POST_MAKE}); fi \
    && rm -rf \
        openssl-${RESTY_OPENSSL_VERSION}.tar.gz openssl-${RESTY_OPENSSL_VERSION} \
        pcre2-${RESTY_PCRE_VERSION}.tar.gz pcre2-${RESTY_PCRE_VERSION} \
        openresty-${RESTY_VERSION}.tar.gz openresty-${RESTY_VERSION} \
    && apk del .build-deps \
    && mkdir -p /var/run/openresty \
    && ln -sf /dev/stdout /usr/local/openresty/nginx/logs/access.log \
    && ln -sf /dev/stderr /usr/local/openresty/nginx/logs/error.log

# Add additional binaries into PATH for convenience
ENV PATH=$PATH:/usr/local/openresty/luajit/bin:/usr/local/openresty/nginx/sbin:/usr/local/openresty/bin

# Copy nginx configuration files
COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf

CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]

# Use SIGQUIT instead of default SIGTERM to cleanly drain requests
# See https://github.com/openresty/docker-openresty/blob/master/README.md#tips--pitfalls
STOPSIGNAL SIGQUIT

制作openresty镜像

docker build -t openresty:alpine-aarch64-eugene .

鉴权

运行openresty

docker run --privileged -u root -d --name openresty  --restart=always --network=host   -v /data/openresty/conf:/usr/local/openresty/nginx/conf  -v /data/openresty/logs:/usr/local/openresty/nginx/logs -v /data/openresty/ssl:/usr/local/openresty/nginx/ssl  -v /usr/local/openresty/nginx/html  -v /data/openresty/lua:/usr/local/openresty/nginx/lua -v /etc/localtime:/etc/localtime openresty:alpine-aarch64-eugene

编写lua脚本

nginx-jwt.lua

-- nginx-jwt.lua


local cjson = require "cjson"
local jwt = require "resty.jwt"

--your secret
local public_key = [[
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpsshjCcEKvc+J3HQcO2
i+cu8blV6T9Lh8YhKGuYOevu3Tqj/Yc9G2UrxC/xFLmj5zYAYtKfy1KB7lGhpZRM
47GnPm/RoP4ozXaaFxjDCmqM+Y345eeusQtbbPXvUHCVLMSTgpEBYI9T5Atg90bm
5uBZgDSsn2rXoJCijsuqXUoE3Glmt/SacVY7yNigG9X+e1zd/C/nveBQdI+QY5A4
fyXCJcw1sdLe+nc27Sh86PtX8J4s3+mG4ElQkwHzMSTE4cf8ffRR/jwrFT+NVUii
gavJG/mF4v8XU8yN1LvoSnak8lc+LS6nHmnI1vSZdYKD3u9i3RAW5lTIpCCrsf7G
yQIDAQAB
-----END PUBLIC KEY-----
]]
--无需鉴权api清单
local no_need_token_api_list = {'/api/register', '/api/login'}
local no_need_ip = {'127.0.0.1'}

local function ignore_url (val)
    for index, value in ipairs(no_need_token_api_list) do
        if (value == val) then
            return true
        end
    end

    return false
end

local function ignore_ip (val)
    for index,value in ipairs(no_need_ip) do
	if(value == val) then
	   return true
        end
    end
    return false
end

local M = {}


function M.auth()

    if ignore_url(ngx.var.request_uri) then
        return
    else
    end
    if ignore_ip(ngx.var.remote_addr) then
	return
    else
    end
	
    -- require Authorization request header
    local auth_header = ngx.var.http_Authorization
    local headers = ngx.req.get_headers()
    local reqUri = ngx.var.request_uri
    local reqList = {}
    string.gsub(reqUri,'[^/]+',function (w)
	table.insert(reqList,w)	
    end)
    local urlSiteId = reqList[2]

    if headers["xtenant"] == nil then
	ngx.log(ngx.WARN, "No xtenant header")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end
    if urlSiteId ~= headers["xtenant"]  then
        ngx.log(ngx.WARN, "No Authorization header")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

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

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

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

    --jwt:set_alg_whitelist({ RS256 = 1 })
    local jwt_obj = jwt:verify(public_key,token)
    
    if ""..jwt_obj.payload.site_id ~= ""..headers["xtenant"] then
        ngx.log(ngx.ERR, "No Authorization header"..jwt_obj.payload.site_id)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

    local httpc = require("resty.http").new()
    -- 改成自己的鉴权接口
    local res, err = httpc:request_uri("https://xxx.cn/gateway/service/api/v1/file/auth", {
        ssl_verify = ssl_verify or false,
        method = "GET",
        headers = {
            ["Authorization"] = "Bearer "..token,
        },
    })
    if  not res then
        ngx.log(ngx.ERR, "request failed: "..err)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
        return
    end
    if res.body ~= "true" then
        ngx.log(ngx.ERR, "Invalid token2: ".. res.body)
        ngx.status = ngx.HTTP_UNAUTHORIZED
        ngx.say("Invalid token22: ".. res.body)
        ngx.header.content_type = "application/json; charset=utf-8"
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end 
    

end

return M

nginx-jwt-src.lua

-- nginx-jwt.lua


local cjson = require "cjson"
local jwt = require "resty.jwt"
local redis = require "resty.redis"
--your secret
local public_key = [[
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpsshjCcEKvc+J3HQcO2
i+cu8blV6T9Lh8YhKGuYOevu3Tqj/Yc9G2UrxC/xFLmj5zYAYtKfy1KB7lGhpZRM
47GnPm/RoP4ozXaaFxjDCmqM+Y345eeusQtbbPXvUHCVLMSTgpEBYI9T5Atg90bm
5uBZgDSsn2rXoJCijsuqXUoE3Glmt/SacVY7yNigG9X+e1zd/C/nveBQdI+QY5A4
fyXCJcw1sdLe+nc27Sh86PtX8J4s3+mG4ElQkwHzMSTE4cf8ffRR/jwrFT+NVUii
gavJG/mF4v8XU8yN1LvoSnak8lc+LS6nHmnI1vSZdYKD3u9i3RAW5lTIpCCrsf7G
yQIDAQAB
-----END PUBLIC KEY-----
]]
--无需鉴权api清单
local no_need_token_api_list = {'/api/register', '/api/login',}

local function ignore_url (val)
    for index, value in ipairs(no_need_token_api_list) do
        if (value == val) then
            return true
        end
    end
    if (string.sub(val,1,17)=="/group1/100/medal") then
	return true
    end

    return false
end

local M = {}


function M.auth()

    if ignore_url(ngx.var.request_uri) then
        return
    else
    end
	
    -- require Authorization request header
    local auth_header = ngx.var.http_Authorization
    local headers = ngx.req.get_headers()
    local reqUri = ngx.var.request_uri
    local reqArgs = ngx.req.get_uri_args()
    local reqList = {}
    string.gsub(reqUri,'[^/]+',function (w)
	table.insert(reqList,w)	
    end)
    local urlSiteId = reqList[2]
    local red = redis:new() 
    -- 自己的redis
    local redisok,err = red:connect("127.0.0.1",6379)
    if not redisok then
    	ngx.log(ngx.ERR,"redis Cannot connect, host: ")
    	--return nil, err
    end
    red:auth("Qwer1234")
    local acckey = ngx.var.arg_accessKey
    if acckey == nil then
        ngx.log(ngx.ERR, "Missing acckey error: ")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end
    local redisToken,rediserror = red:get(acckey)
    if not redisToken or type(redisToken) == "userdata" then
        ngx.log(ngx.ERR, "redis error: ")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end
    local token = redisToken

    local jwt_obj = jwt:verify(public_key,token)
   
    if ""..jwt_obj.payload.client_id == "platform-manage" then
         return
    end

 
    if ""..jwt_obj.payload.site_id ~= urlSiteId then
        
        ngx.log(ngx.ERR, "No Authorization header"..jwt_obj.payload.site_id)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

    local httpc = require("resty.http").new()
    -- 改成自己的鉴权接口
    local res, err = httpc:request_uri("https://xxx.cn/gateway/service/api/v1/file/auth", {
        ssl_verify = ssl_verify or false,
        method = "GET",
        headers = {
            ["Authorization"] = "Bearer "..token,
        },
    })
    if  not res then
        ngx.log(ngx.ERR, "request failed: "..err)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
        return
    end
    if res.body ~= "true" then
        ngx.log(ngx.ERR, "Invalid token2: ".. res.body)
        ngx.status = ngx.HTTP_UNAUTHORIZED
        ngx.say("Invalid token22: ".. res.body)
        ngx.header.content_type = "application/json; charset=utf-8"
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end 
    

end

return M

nginx-upload-auth.lua

-- nginx-jwt.lua


local cjson = require "cjson"
local jwt = require "resty.jwt"

--your secret
local public_key = [[
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpsshjCcEKvc+J3HQcO2
i+cu8blV6T9Lh8YhKGuYOevu3Tqj/Yc9G2UrxC/xFLmj5zYAYtKfy1KB7lGhpZRM
47GnPm/RoP4ozXaaFxjDCmqM+Y345eeusQtbbPXvUHCVLMSTgpEBYI9T5Atg90bm
5uBZgDSsn2rXoJCijsuqXUoE3Glmt/SacVY7yNigG9X+e1zd/C/nveBQdI+QY5A4
fyXCJcw1sdLe+nc27Sh86PtX8J4s3+mG4ElQkwHzMSTE4cf8ffRR/jwrFT+NVUii
gavJG/mF4v8XU8yN1LvoSnak8lc+LS6nHmnI1vSZdYKD3u9i3RAW5lTIpCCrsf7G
yQIDAQAB
-----END PUBLIC KEY-----
]]
--无需鉴权api清单
local no_need_token_api_list = {'/api/register', '/api/login'}

local function ignore_url (val)
    for index, value in ipairs(no_need_token_api_list) do
        if (value == val) then
            return true
        end
    end

    return false
end

local M = {}


function M.auth()

    if ignore_url(ngx.var.request_uri) then
        return
    else
    end
	
    -- require Authorization request header
    local auth_header = ngx.var.http_Authorization
    local headers = ngx.req.get_headers()
    local reqUri = ngx.var.request_uri
    local reqList = {}
    string.gsub(reqUri,'[^/]+',function (w)
	table.insert(reqList,w)	
    end)
    local urlSiteId = reqList[2]

    if headers["xtenant"] == nil then
	ngx.log(ngx.WARN, "No xtenant header")
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

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

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

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

    --jwt:set_alg_whitelist({ RS256 = 1 })
    local jwt_obj = jwt:verify(public_key,token)

    if ""..jwt_obj.payload.client_id == "platform-manage" then
        return;
    end

   
    if ""..jwt_obj.payload.site_id ~= ""..headers["xtenant"] then
	ngx.log(ngx.ERR, "No Authorization header"..jwt_obj.payload.site_id)
        ngx.say("Invalid token: ".. cjson.encode(jwt_obj).."headSiteId:"..headers["xtenant"].."tokenSiteId:"..jwt_obj.payload.site_id)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end      

    local httpc = require("resty.http").new()
    -- 改成自己的鉴权接口
    local res, err = httpc:request_uri("https://xxx.cn/gateway/service/api/v1/file/auth", {
        ssl_verify = ssl_verify or false,
	method = "GET",
        headers = {
            ["Authorization"] = "Bearer "..token,
        },
    })
    if  not res then
        ngx.log(ngx.ERR, "request failed: "..err)
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
        return
    end
    if res.body ~= "true" then
        ngx.log(ngx.ERR, "Invalid token2: ".. res.body)
        ngx.status = ngx.HTTP_UNAUTHORIZED
        ngx.say("Invalid token22: ".. res.body)
        ngx.header.content_type = "application/json; charset=utf-8"
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end 
     
end

return M

下载lua插件并安装

下载 lua-resty-jwt 、 lua-resty-hmac 、lua-resty-http插件:
lua-resty-jwt: https://github.com/SkyLothar/lua-resty-jwt
lua-resty-hmac: https://github.com/jkeys089/lua-resty-hmac
lua-resty-http:https://github.com/ledgetech/lua-resty-http
拷贝三个插件的 lib/resty 下的文件拷贝到一个文件夹中
找到 evp.lua,进入 evp.lua 文件,将 EVP_MD_CTX_create () 全部替换为 EVP_MD_CTX_new,将 EVP_MD_CTX_destroy 全部替换为 EVP_MD_CTX_free

注意:报错module ‘resty.http‘ not found是因为没有lua-resty-http插件
报这个错是因为上面这个函数名没有替换

evp.lua:216: dlsym(RTLD_DEFAULT, EVP_MD_CTX_create): symbol not found

进入容器

docker exec -it openresty bash

创建文件夹

mkdir -p /usr/local/openresty/lualib-extend/resty

然后把刚刚的插件和之前写的lua脚本拷贝到容器中,结构如下
在这里插入图片描述

配置nginx

nginx.conf

# nginx.conf  --  docker-openresty
#
# This file is installed to:
#   `/usr/local/openresty/nginx/conf/nginx.conf`
# and is the file loaded by nginx at startup,
# unless the user specifies otherwise.
#
# It tracks the upstream OpenResty's `nginx.conf`, but removes the `server`
# section and adds this directive:
#     `include /etc/nginx/conf.d/*.conf;`
#
# The `docker-openresty` file `nginx.vh.default.conf` is copied to
# `/etc/nginx/conf.d/default.conf`.  It contains the `server section
# of the upstream `nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#

#user  nobody;
#worker_processes 1;

# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;
events {
    worker_connections  65535;
}
http {
 limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
  #注意在这儿配置的是刚刚插件的路径
  lua_package_path "usr/local/openresty/lualib-extend/?.lua;;";
    #include       mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
        access_log  /usr/local/openresty/nginx/logs/access.log  main;
        error_log  /usr/local/openresty/nginx/logs/error.log  error;
        sendfile        on;
        server_tokens off;
        keepalive_timeout  600s;
        client_header_timeout 600s;
        client_body_timeout 600s;
        send_timeout 600s;
        client_max_body_size 1024m;
       #指定nginx与后端fastcgi server连接超时时间
       fastcgi_connect_timeout 600s;
       #指定nginx向后端传送请求超时时间(指已完成两次握手后向fastcgi传送请求超时时间)
       fastcgi_send_timeout 600s;
       #指定nginx向后端传送响应超时时间(指已完成两次握手后向fastcgi传送响应超时时间)
       fastcgi_read_timeout 600s;

        proxy_redirect ~/big/upload/(.*) /big/upload/$1;  #继点续传一定要设置(注意)


    # Enables or disables the use of underscores in client request header fields.
    # When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive.
    # underscores_in_headers off;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

        # Log in JSON Format
        # log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", '
        # '"remote_addr": "$remote_addr", '
        #  '"body_bytes_sent": $body_bytes_sent, '
        #  '"request_time": $request_time, '
        #  '"response_status": $status, '
        #  '"request": "$request", '
        #  '"request_method": "$request_method", '
        #  '"host": "$host",'
        #  '"upstream_addr": "$upstream_addr",'
        #  '"http_x_forwarded_for": "$http_x_forwarded_for",'
        #  '"http_referrer": "$http_referer", '
        #  '"http_user_agent": "$http_user_agent", '
        #  '"http_version": "$server_protocol", '
        #  '"nginx_access": true }';
        # access_log /dev/stdout nginxlog_json;

    # See Move default writable paths to a dedicated directory (#119)
    # https://github.com/openresty/docker-openresty/issues/119
    client_body_temp_path /var/run/openresty/nginx-client-body;
    proxy_temp_path       /var/run/openresty/nginx-proxy;
    fastcgi_temp_path     /var/run/openresty/nginx-fastcgi;
    uwsgi_temp_path       /var/run/openresty/nginx-uwsgi;
    scgi_temp_path        /var/run/openresty/nginx-scgi;

    #sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    #keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
    include /usr/local/openresty/nginx/conf/conf.d/*.conf;

    # Don't reveal OpenResty version to clients.
    # server_tokens off;
}

include /etc/nginx/conf.d/*.main;

conf/conf.d/file.conf


  upstream file
  {
    server 127.0.0.1:8080;
    ip_hash;
  }
  
  access_log /usr/local/openresty/nginx/logs/nginx_access.log;
  error_log /usr/local/openresty/nginx/logs/nginx_error.log;
  resolver 114.114.114.114;
  server
  {
    listen 80;
    listen 443 ssl ;
    server_name  xxx.cn;
    ssl_certificate      /usr/local/openresty/nginx/ssl/xxx.cn.pem;
    ssl_certificate_key  /usr/local/openresty/nginx/ssl/xxx.cn.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_protocols    TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:!RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH;
    ssl_prefer_server_ciphers on;

    client_header_buffer_size 16k;
    large_client_header_buffers 4 16k;
    #proxy_ssl_session_reuse off;

    location /group1 {
      #ssl_preread on;
      limit_req zone=allips burst=5 nodelay;
      add_header Access-Control-Expose-Headers Content-Disposition;
      add_header Cache-Control max-age=360000;
      if ($request_method = 'OPTIONS') {
      add_header Access-Control-Allow-Origin * always;
      add_header Access-Control-Allow-Headers "access_token, Content-Type, X-Client-Id, Authorization, X-Domain, xtenant, clientid" always;
      add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;
      add_header Access-Control-Max-Age 86400 always; 
      	return 204;
      }
      ## 这儿就可以使用lua脚本进行鉴权了。
       access_by_lua_block {
        local obj = require('nginx-jwt')
        obj.auth()
      }
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      #proxy_ssl_session_reuse off;
      #proxy_ssl_server_name off;
      proxy_pass http://file;
    }
   location ~*\.(doc|docx|xls|xlsx|ppt|pptx|pdf)$ {
      add_header Access-Control-Expose-Headers "Content-Disposition";
      if ($arg_accesskey != "") {
           access_by_lua_block {
                local obj = require('nginx-jwt-src')
                obj.auth()
           }
      }
      if ($arg_accesskey = "") {
           access_by_lua_block
           {
                local obj = require('nginx-jwt')
                obj.auth()
           }
      }

      if ($request_method = 'OPTIONS') {
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Headers "access_token, Content-Type, X-Client-Id, Authorization, X-Domain, xtenant, clientid" always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;
        add_header Access-Control-Max-Age 86400 always;
                return 204;
      }
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      #proxy_ssl_session_reuse off;
      #proxy_ssl_server_name off;
      proxy_pass http://file;

    }

    location ~*\.(apk|jpg|png|gif|jpeg|heic)$ {
      access_by_lua_block {
        local obj = require('nginx-jwt-src')
        obj.auth()
      }

      if ($request_method = 'OPTIONS') {
	add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Headers "access_token, Content-Type, X-Client-Id, Authorization, X-Domain, xtenant, clientid" always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;
        add_header Access-Control-Max-Age 86400 always;
                return 204;
      }
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://file;
    }
    location ~*\.(mp3|mp4)$ {
      limit_req zone=allips burst=5 nodelay;
      add_header Access-Control-Allow-Origin * always;
      add_header Access-Control-Allow-Headers "access_token, Content-Type, X-Client-Id, Authorization, X-Domain, xtenant, clientid" always;
      add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;
      add_header Access-Control-Max-Age 86400 always;
      limit_rate_after 20m;
      limit_rate 100k;
      access_by_lua_block {
        local obj = require('nginx-jwt-src')
        obj.auth()
      }
      if ($request_method = 'OPTIONS') {
                return 204;
      }
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://file;
    }
  }

重启openresty

文件服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值