採用lua指令碼獲取mysql、redis資料以及jwt的校驗

MXC肖某某發表於2021-02-27

一、安裝配置Openresty

1,安裝

wget https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz   # 下載
tar xzvf ngx_openresty-1.9.7.1.tar.gz       # 解壓
cd ngx_openresty-1.9.7.1/ 
./configure
make 
make install

2,配置nginx.conf

  按照上一步安裝的預設路徑為:/usr/local/openresty/nginx/conf 中。

worker_processes  1;
#配置日誌級別為info存放在logs/error.log中
error_log  logs/error.log  info;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    #配置lua指令碼,包括/usr/local/openresty/nginx/lua/?.lua自定義指令碼位置
    lua_package_path "/usr/local/openresty/lualib/?.lua;/usr/local/openresty/nginx/lua/?.lua;;";
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}

二、lua讀取Mysql中資料

1,編寫lua指令碼

  儲存地址(nginx中能載入的路徑)為: /usr/local/openresty/nginx/lua

--指定文字輸出的檔案型別為json型別
ngx.header.content_type="application/json;charset=utf-8"
--引入庫檔案json
local cjson = require "cjson"
--引入依賴庫mysql
local mysql = require "resty.mysql"

--配置資料庫連線資訊
local props = {
        host = "127.0.0.1",
        port = 3306,
        database = "test",
        user = "root",
        password = "123456"
}

--建立連線、設定超時時間、編碼格式
local db,err = mysql:new()

db:set_timeout(10000)
db:connect(props)
db:query("SET NAMES utf8")

--SQL語句 (讀取引數中id的值)
local id = ngx.req.get_uri_args()["id"]
local sql = "select * from t_user where id="..id

ngx.log(ngx.INFO,"sql語句為:",sql)

--執行SQL語句
res, err, errno, sqlstate = db:query(sql)

--關閉連線
db:close()
--響應資料->json ngx.say(cjson.encode(res))

2,配置nginx讀取lua指令碼

  在nginx.conf的server中新增

#配置mysql
location /mysql {        
    content_by_lua_file /usr/local/openresty/nginx/lua/mysql.lua;
}

3,啟動openresty

  如果配置了/etc/profile的環境變數,直接使用命令:nginx 或 nginx -s reload

三、lua操作redis(單機)

1,編寫lua指令碼

a)redis_basic.lua

local redis = require "resty.redis"

local config = {
    host = "127.0.0.1",
    port = 6379,
    pass = "123456"  -- redis 密碼,沒有密碼的話,把這行註釋掉
}

local _M = {}

function _M.new(self)
    local red = redis:new()
    red:set_timeout(1000) -- 1 second
    local res = red:connect(config['host'], config['port'])
    ngx.log(ngx.INFO,"red的連線為::",res)
    if not res then
        return nil
    end
    if config['pass'] ~= nil then
        res = red:auth(config['pass'])
        if not res then
            return nil
        end
    end
    red.close = close
    return red
end

local function close(self)
    local sock = self.sock
    if not sock then
        return nil, "not initialized"
    end
    if self.subscribed then
        return nil, "subscribed state"
    end
    return sock:setkeepalive(10000, 50)
end

return _M

b)redis.lua

--定義redis操作的封裝
local redis_basic = require "redis_basic"

--定義一個模組
local lredis={}

--定義一個方法,Redis叢集增加資料、查詢資料、刪除資料
--增加資料
function lredis.set(key,val)
        local red = redis_basic:new()
        red:set(key,val)
        red:close()
end

--根據key查詢資料
function lredis.get(key)
        local red = redis_basic:new()
        local value = red:get(key)
        red:close()
        --返回資料
        return value
end

--根據key刪除資料
function lredis.del(key)
        local red = redis_basic:new()
        red:del(key)
        red:close()
end

return lredis

2,配置nginx讀取lua指令碼

  在nginx.conf的server中新增

#配置redis
location /redis {
    content_by_lua '
    --指定文字輸出的檔案型別為json型別
    ngx.header.content_type="application/json;charset=utf-8"
    --引入redis.lua指令碼庫
    local cjson = require "cjson"
    --在http中配置了相應的lua讀取地址,這裡實際是讀取/usr/local/openresty/nginx/lua/redis.lua
    local rredis = require "redis"
    
    --獲取前端運算元據 key value method=1(增加) 2(修改) 3(刪除)
    local args = ngx.req.get_uri_args()
    local key = args["id"]
    local value = args["value"]
    local method = args["method"]

    --根據method的值執行不同操作
    if method == "1" then
        ngx.log(ngx.INFO,"接收的key為:",key)
        ngx.log(ngx.INFO,"接收的val為:",value)
        --增加資料
        rredis.set(key,value)
        --響應資料
        ngx.say("set success!")
    elseif method=="2" then
        --執行查詢
        local result = rredis.get(key)
        ngx.say(cjson.encode(result))
    else
        --刪除
        rredis.del(key)
        ngx.say("del success!")
    end
     ';
}

3,啟動openresty

  如果配置了/etc/profile的環境變數,直接使用命令:nginx 或 nginx -s reload

4,測試

#新增資料
http://hadoop103/redis?method=1&id=key&value=111
#查詢資料
http://hadoop103/redis?method=2&id=key
#刪除資料
http://hadoop103/redis?method=3&id=key

四、lua完成jwt的校驗

1,新增jwt的指令碼

  拷貝github中的lua指令碼到本地'/usr/local/openresty/lualib/resty'中:

#拷貝檔案為hmac.lua 到 /usr/local/openresty/lualib/resty
https://github.com/jkeys089/lua-resty-hmac/blob/master/lib/resty/hmac.lua
#拷貝檔案為evp.lua jwt-validators.lua 和 jwt.lua 到 /usr/local/openresty/lualib/resty
https://github.com/SkyLothar/lua-resty-jwt/tree/master/lib/resty

  

2,編寫lua指令碼

a)jwt_token

--引入依賴庫
local jwt = require "resty.jwt"

--定義一個模組
local jwttoken={}

--定義一個校驗jwt令牌的方法
--auth_token:令牌 Bearer XXXdsafaf
--secret: 金鑰
function jwttoken.check(auth_token,secret)
    --校驗格式,去掉'Bearer '
    local _,_,token=string.find(auth_token,"Bearer%s+(.+)")
    
    --通過jwt模組校驗令牌
    local result = jwt:verify(secret,token)
    
    return result
end

return jwttoken

b)jwt_check

--呼叫jwt_token.lua中的令牌校驗方法
ngx.header.content_type="application/json;charset=utf-8"

--引入依賴庫,根據檔名
local jwttoken = require "jwt_token"
--引入json依賴庫
local cjson = require "cjson"

--響應資料
local response = {}

--獲取請求頭中的令牌
local auth_token = ngx.var.http_Authorization

--準備金鑰
local secret = "5pil6aOO5YaN576O5Lmf5q+U5LiN5LiK5bCP6ZuF55qE56yR"

--呼叫校驗方法
local result = jwttoken.check(auth_token,secret)

--組裝響應結果
response["code"]=200
response["body"]=result
response["message"]="完成校驗,請檢視body校驗結果!"

ngx.say(cjson.encode(response))

3,配置nginx讀取lua指令碼

  在nginx.conf的server中新增

#配置jwt
location /jwt {
     content_by_lua_file /usr/local/openresty/nginx/lua/jwt_check.lua;
}

4,配置java生成jwt

a)新增maven依賴

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.6.0</version>
</dependency>

b)新增java生成程式碼

採用lua指令碼獲取mysql、redis資料以及jwt的校驗
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JWTDemo {

    public static final String SECRET="5pil6aOO5YaN576O5Lmf5q+U5LiN5LiK5bCP6ZuF55qE56yR";

    public static String createJWT(String uid, long ttlMillis) throws Exception {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        Key signingKey = new SecretKeySpec(SECRET.getBytes(), signatureAlgorithm.getJcaName());

        Map<String,Object> header=new HashMap<String,Object>();
        header.put("typ","JWT");
        header.put("alg","HS256");
        JwtBuilder builder = Jwts.builder().setId(uid)
                .setIssuedAt(now)
                .setIssuer(uid)
                .setSubject(uid)
                .setHeader(header)
                .signWith(signatureAlgorithm, signingKey);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exp));
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    public static void main(String[]cmd) throws Exception {
        String s=createJWT("yaya",36000000);
        System.out.println("Bearer "+s);
    }

}
View Code

5,測試驗證效果

  採用lua指令碼獲取mysql、redis資料以及jwt的校驗

五、總結

1,nginx.conf配置

採用lua指令碼獲取mysql、redis資料以及jwt的校驗
worker_processes  1;

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

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    lua_shared_dict redis_cluster_slot_locks 100k;

    sendfile        on;

    keepalive_timeout  65;

    #配置lua指令碼,包括lua/?.lua自定義指令碼位置
    lua_package_path "/usr/local/openresty/lualib/?.lua;/usr/local/openresty/nginx/lua/?.lua;;";
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";

    server {
        listen       80;
        server_name  localhost;


        location / {
            root   html;
            index  index.html index.htm;
        }

    #配置mysql
    location /mysql {
         content_by_lua_file /usr/local/openresty/nginx/lua/mysql.lua;
    }
    
    #配置jwt
    location /jwt {
         content_by_lua_file /usr/local/openresty/nginx/lua/jwt_check.lua;
    }

    #配置redis
    location /redis {
         content_by_lua '
        --指定文字輸出的檔案型別為json型別
        ngx.header.content_type="application/json;charset=utf-8"
        --引入redis.lua指令碼庫
        local cjson = require "cjson"
        --在http中配置了相應的lua讀取地址,這裡實際是讀取/usr/local/openresty/nginx/lua/redis.lua
        local rredis = require "redis"
        
        --獲取前端運算元據 key value method=1(增加) 2(修改) 3(刪除)
        local args = ngx.req.get_uri_args()
        local key = args["id"]
        local value = args["value"]
        local method = args["method"]

        --根據method的值執行不同操作
        if method == "1" then
            ngx.log(ngx.INFO,"接收的key為:",key)
            ngx.log(ngx.INFO,"接收的val為:",value)
            --增加資料
            rredis.set(key,value)
            --響應資料
            ngx.say("set success!")
        elseif method=="2" then
            --執行查詢
            local result = rredis.get(key)
            ngx.say(cjson.encode(result))
        else
            --刪除
            rredis.del(key)
            ngx.say("del success!")
        end
         ';
    }
    }
}
View Code

2,自定義lua指令碼

  

 

相關文章