nginx+openResty

Posted qq_40707462

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nginx+openResty相关的知识,希望对你有一定的参考价值。

一、nginx

1、好处

1、处理响应请求很快

2、高并发连接。理论上,Nginx 支持的并发连接上限取决于你的内存,10 万远未封顶。

3、低的内存消耗。10000 个非活跃的 HTTP Keep-Alive 连接在 Nginx 中仅消耗 2.5MB 的内存

4、具有很高的可靠性:

5、高扩展性。各模块耦合度极低。这种设计造就了 Nginx 庞大的第三方模块。

6、热部署。master 管理进程与 worker 工作进程的分离设计,可以在 7 × 24 小时不间断服务的前提下,升级 Nginx 的可执行文件。也可以在不停止服务的情况下修改配置文件,更换日志文件等功能。

2、安装

3、配置

nginx.conf 是主配置文件

worker_process      # 表示工作进程的数量,一般设置为cpu的核数

worker_connections  # 表示每个工作进程的最大连接数

server            # 块定义了虚拟主机

    listen          # 监听端口

    server_name     # 监听域名

    location      # 是用来为匹配的 URI 进行配置,URI 即语法中的“/uri/”

    location /    # 匹配任何查询,因为所有请求都以 / 开头

        root        # 指定对应uri的资源查找路径,这里html为相对路径,完整路径为
                    # /opt/nginx-1.7.7/html/

        index       # 指定首页index文件的名称,可以配置多个,以空格分开。如有多
                    # 个,按配置顺序查找。

示例

从配置可以看出,Nginx 监听了 80 端口、域名为 localhost、根路径为 html 文件夹(如果安装路径为 /opt/nginx-1.7.7,所以完整根路径为 /opt/nginx-1.7.7/html)、默认 index 文件为 index.htmlindex.htm 服务器错误重定向到 50x.html 页面。

可以看到 /opt/nginx-1.7.7/html/ 有以下文件:

ubuntu:/opt/nginx-1.7.7/html$ ls
50x.html  index.html

这也是上面在浏览器中输入 http://localhost,能够显示欢迎页面的原因。实际上访问的是 /opt/nginx-1.7.7/html/index.html 文件。

4、location匹配

匹配规则

模式含义
location = /uri =表示精确匹配,只有完全匹配上才能生效
location ^~ /uri ^~开头对URL路径进行前缀匹配,并且在正则之前。
location ~ pattern开头表示区分大小写的正则匹配
location ~* pattern开头表示不区分大小写的正则匹配
location /uri不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
location /通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default

5、反向代理

反向代理
反向代理服务器,对于客户端而言它就像是原始服务器,客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样

  • 反向代理还可以为后端的多台服务器提供负载均衡,或为后端较慢的服务器提供缓冲服务。
  • 反向代理还可以启用高级 URL 策略和管理技术,从而使处于不同 web 服务器系统的 web 页面同时存在于同一个 URL 空间下。

二、openResty+jwt

参考
参考

1、安装

添加仓库

# add the yum repo:
wget https://openresty.org/package/centos/openresty.repo
sudo mv openresty.repo /etc/yum.repos.d/

# update the yum index:
sudo yum check-update

安装

# 安装 OpenResty
$ sudo yum install -y openresty

# 安装命令行工具 resty
$ sudo yum install -y openresty-resty

# 安装命令行工具 opm
$ sudo yum install -y openresty-opm

列出所有 openresty 仓库里头的软件包:

sudo yum --disablerepo="*" --enablerepo="openresty" list available

路径,系统默认安装在 /usr/local/openresty

[wjy@localhost ~]$ whereis openresty
openresty: /usr/bin/openresty /usr/local/openresty
[wjy@localhost ~]$ cd /usr/local/openresty
[wjy@localhost openresty]$ ls
bin        luajit  nginx       pcre  resty.index  zlib
COPYRIGHT  lualib  openssl111  pod   site
[wjy@localhost openresty]$ cd bin
[wjy@localhost bin]$ ./openresty -v
nginx version: openresty/1.21.4.1

在profile中添加到path
(记得切换root,不然保存会报错profile" E212: 无法打开并写入文件,这样的话保存时用 w ! sudo tee %

vim /etc/profile
PATH=/usr/local/openresty/nginx/sbin:$PATH
export PATH

重新加载环境

source /etc/profile

2、测试

/usr/local/openresty/nginx/conf里,修改nginx.conf,在合适的位置
修改完conf要重新启动一下nginx -s reload

worker_processes  1;
error_log logs/error.log;
events 
    worker_connections 1024;

http 
    server 
        listen 8081;
        location / 
            default_type text/html;
            content_by_lua_block 
                ngx.say("<p>hello, world</p>")
            
        
    

未避免权限问题,尽量su root,或者在nginx.conf加入:

启动nginx

nginx -t
nginx -c conf/nginx.conf

查看是否启动

[root@localhost nginx]# ps aux|grep nginx
root       5731  0.0  0.0  27580  1576 ?        Ss   10:40   0:00 nginx: master process nginx
nobody     5732  0.0  0.1  30112  2388 ?        S    10:40   0:00 nginx: worker process
root       6046  0.0  0.0  27580  1588 ?        Ss   10:50   0:00 nginx: master process nginx
nobody     6047  0.0  0.1  30112  2876 ?        S    10:50   0:00 nginx: worker process
root       6095  0.0  0.0 112664   956 pts/0    S+   10:54   0:00 grep --color=auto nginx

测试:curl http://localhost:8081/

<p>hello, world</p>

错误消息会发送到当前工作目录的 stderr 设备或默认错误日志文件 log/Error.log

3、安装 jwt 插件

jwt-github

sudo opm get SkyLothar/lua-resty-jwt

默认安装在/usr/local/openresty/site

4、测试 jwt

修改 nginx.conf

里面"lua-resty-jwt"算是一个密钥,可以自己设置,保证verifysign的一样就行

kid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥


    "alg" : "HS256",
    "typ" : "jwt",
    "kid" : "/home/jwt/.ssh/pem"

# nginx.conf

lua_package_path "/usr/local/openresty/lualib/mylua/?.lua;;";

server 
    default_type text/plain;

    location = /verify 

        content_by_lua_block 
            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_block 
            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)
        
    

lua_package_path:指定 Lua 脚本位置。搜寻规则

首先会在/usr/local/openresty/site/lualib中搜寻

例如:lua_package_path "/foo/bar/?.lua;/blah/?.lua;;";

最后出现了 ;; 两个半角分号,代表的是 LuaJIT 安装时的原始搜索路径,如果在前面的搜索路径里面无法搜索到需要的模块,就会依次搜索后面的路径。

default_type:指定输出为纯文本,无实际作用,只是为了在浏览器中方便查看换行等符号。

测试:

curl http://localhost:8081/verify

  "signature": "VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY",
  "reason": "everything is awesome~ :p",
  "valid": true,
  "raw_header": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9",
  "payload": 
    "foo": "bar"
  ,
  "header": 
    "alg": "HS256",
    "typ": "JWT"
  ,
  "verified": true,
  "raw_payload": "eyJmb28iOiJiYXIifQ"

curl http://localhost:8081/sign
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.VxhQcGihWyHuJeHhpUiq2FU7aW2s_3ZJlY6h1kdlmJY

5、例子

在对应位置mylua里写对应的脚本

lua_package_path "/usr/local/openresty/lualib/mylua/?.lua;;";

jwttest.lua

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

--your secret
local secret = "secretkey"

local M = 


function M.auth()
    -- 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.status = ngx.HTTP_UNAUTHORIZED
        ngx.header.content_type = "application/json; charset=utf-8"
        ngx.say(cjson.encode(jwt_obj))
        ngx.exit(ngx.HTTP_UNAUTHORIZED)
    end

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

end

return M

nginx.conf

location /checkjwt 
    access_by_lua_block 
        local obj = require('jwttest')
        obj.auth()
        ngx.say("aaaaa")
   

不带token,401

curl http://localhost:8081/checkjwt
HTTP/1.1 401 Unauthorized
Server: openresty/1.21.4.1
Date: Fri, 19 Aug 2022 02:22:53 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive

<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>openresty/1.21.4.1</center>
</body>
</html>

指定token请求(token是事先自己sign的)

curl -i http://localhost:8081/checkjwt  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.VlM9f1OK5gpYtEtOdnuIqxATcnP7ulALjGqsKhjk58Y'
[root@localhost openresty]# curl -i http://localhost:8081/checkjwt  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.VlM9f1OK5gpYtEtOdnuIqxATcnP7ulALjGqsKhjk58Y'
HTTP/1.1 200 OK
Server: openresty/1.21.4.1
Date: Fri, 19 Aug 2022 02:19:34 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.VlM9f1OK5gpYtEtOdnuIqxATcnP7ulALjGqsKhjk58Y
aaaaa

三、

每次登录,客户端向后端发送请求,后端返回一个有过期时间的token给客户端,后端把这个token保存在redis里,之后每次客户端发送请求的时候都带上这个token(放在header里或者cookie里),后端校验

载荷(payload)
该部分一般存放一些有效的信息。jwt的标准定义包含五个字段:

iss:该JWT的签发者
sub: 该JWT所面向的用户
aud: 接收该JWT的一方
exp(expires): 什么时候过期,这里是一个Unix时间戳
iat(issued at): 在什么时候签发的
这个只是JWT的定义标准,不强制使用。另外自己也可以添加一些公开的不涉及安全的方面的信息。

以上是关于nginx+openResty的主要内容,如果未能解决你的问题,请参考以下文章

OpenResty:特性与动态处理

Nginx+lua+openresty系列 | 第一篇:openresty介绍

Nginx平滑升级至OpenResty

openresty如何完美替换nginx

nginx实战 OpenResty 安装

OpenResty与nginx结合执行lua脚本