通过lua进行nginx的权限控制

Posted marility

tags:

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

nginx_lua的安装

  1. nginx使用luajit进行编译安装

  2. 使用openresty进行yum安装

openresty中将lua和nginx进行封装,详情可查看openresty官网

openresty相关启动命令service openresty start

ngx_lua的相关api使用说明及相关使用

  1. ngx_lua github地址
  2. lua基本语法
  3. openrestry最佳实践

ngx_lua的日常使用场景

ngx_lua的执行顺序,可以看这张图
技术分享图片

  1. 通过nginx直接进行一些值的显示,此处用到的一般是content_by_lua模块,lua 1.9.5版本中是content_by_lua_block

  2. 通过nginx作访问权限控制,包括重写等,不过nginx也可以直接重写

ngx_lua的实例

业务场景

老板要求访问一个url时进行用户时作权限控制,有权限者可以查看url,无权限者则直接返回错误

其中开发人员写了一个接口,能通过传入的两个参数(报表名和用户名),返回对应的值

其中实现过程如下

1.登陆入系统lebi.letv.cn中
2.用户需要访问报表链接,其中报表链接均为http://xxx/views/xxx模式
3.访问报表时,nginx先通过lua进行控制,先向开发人员提供的接口http://10.58.91.84:8080/m/api/permission/getSchedulePermission传递报表名和用户名,其中报表名从报表访问链接中获取,用户名从cookie中获取
4.ngx_lua控制访问请求,同时作相关的处理

开发接口返回值说明

开发接口返回值设置三种:

http状态码403为没权限
http状态码200为通过验证
http状态码500为服务错误

相关curl测试状态如下

http 403:

[[email protected] conf.d]# curl -i ‘http://10.58.91.84:8080/m/api/permission/getSchedulePermission?username=marility&url=http://a/b/c‘
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 01 Mar 2018 08:26:05 GMT

{"success":false,"errorMsg":"没有权限,请联系管理员"}



http 200:

[[email protected] conf.d]# curl -i ‘http://10.58.91.84:8080/m/api/permission/getSchedulePermission?username=letv&url=http://a/b/c‘
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 01 Mar 2018 09:45:24 GMT

{"Msg":"有权限查看","success"}


http 500:

[[email protected] conf.d]# curl -i ‘http://10.58.91.84:8080/m/api/permission/getSchedulePermission?username=letv&url=‘
HTTP/1.1 500 Internal Server Error
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked
Date: Thu, 01 Mar 2018 10:07:03 GMT
Connection: close

{"errorMsg":"java.lang.ArrayIndexOutOfBoundsException: 2","success":false}

以上测试中url中直接传入测试url=http://a/b/c, 实际中应该动态传入访问报表的链接

ngx_lua中的控制
        location ~ ^/views {
            access_by_lua ‘
                local res = ngx.location.capture("/matrix_proxy/m/api/permission/getSchedulePermission", {args={username=ngx.var.cookie_example , url=ngx.var.request_uri}})
                if res.status == ngx.HTTP_FORBIDDEN then
                    ngx.exec("@hello")
                elseif res.status == ngx.HTTP_OK then
                    ngx.exec("@/")
                elseif res.status == ngx.HTTP_INTERNAL_SERVER_ERROR then
                    ngx.exec("@servererror")
                else
                    ngx.exec("@error")
                end
        ‘;}
  1. access_by_lua因为要实现权限控制,所以只能选择access_by_lua,而不能使用content_by_lua

  2. nginx中的lua全文以单引号‘ ‘进行囊括

  3. local res, lua中使用local定义一个变量res

  4. 向一个接口发送参数,有两种方法,一种是使用ngx.location.capture方法,另外一种是httpc:request_urihttpc.request_uri为openresty的第三方模块。 httpc.request_url的api使用说明 , openresty加载第三方模块说明 , 本例中使用capture方法

  5. ngx.location.capture方法不能象httpc:request_uri方法一样直接传入url,而只能是$request_uri,所以此处先进行一层的/matrix_proxy/的封装,而/matrix_proxy通过pass_proxy,将请求反代至接口的服务器ip 10.58.91.84:8080

  6. ngx.location.capture api的使用说明

  7. 此处向接口url传递两个参数,因为要传入变量,所以要以{args={ }}的形式来完成。如果使用httpc.request_uri方法的话,应该可以使用lua的..拼接符进行变量与uri的拼接,有兴趣的同学可以自行测试

  8. lua的http状态码与ngx_lua状态对应表

  9. ngx.var.cookie_COOKIE_KEY 获取用户的cookie的value值,上实例中cookie的key为examplengx.var.request_uri 获取nginx中的$request_uri值

  10. 从api说明中可以看到ngx.location.capture有4个slots,其中一个是res.status

  11. 判断res.status的结果与http状态码是否相等,lua中等于判断使用==

  12. lua中多重if判断使用elseif

  13. lua中if完整的语句为 if..else..end

  14. 将四种结果均返回进行执行,ngx.exec表示执行后面的location,@hello 中的 @表示nginx内部的传递,不会进行外部的跳转

完整的ngx_lua配制实例
[[email protected] conf.d]# cat tableau.conf
upstream backend_lebiTableau {
        server 10.110.150.217;
        keepalive 100;
}

upstream matrix_proxy_backend {
        server 10.58.91.84:8080;
        keepalive 100;
}

server {
        listen       82;
        server_name  lebi.letv.cn;
        resolver 10.110.220.231;

        access_log /tmp/lebitableau.a.log main;
        error_log /tmp/lebitableau.error.log ;

        location = /favicon.ico {
            log_not_found off;
            log_subrequest off;
        }

        location / {
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_pass              http://backend_lebiTableau;
            proxy_send_timeout    18000;
            proxy_read_timeout    18000;
            proxy_next_upstream     error timeout invalid_header http_500;
            proxy_connect_timeout 20;
        }

        location ~ /matrix_proxy/(.*) {
            internal;
            proxy_pass http://matrix_proxy_backend/$1$is_args$args;
        }

        location @/ {
            proxy_pass  http://backend_lebiTableau;
        }

        location @error {
            return 403;
        }

        location @servererror {
            default_type ‘text/plain‘;
            content_by_lua ‘ngx.say("server error")‘;
        }

        location @hello {
            rewrite ^(.*)$ http://matrix.lebi.letv.cn/#/error break; ##没有权限的用户全部rewrite至系统错误页面
        }
        
        location @ok {
            default_type ‘text/plain‘;
            content_by_lua ‘ngx.say("authorized ok, cookie=", ngx.var.cookie_78bdfe11ce353909cb210160a76c330b)‘;
        }

        location ~ ^/views {
            access_by_lua ‘
                local res = ngx.location.capture("/matrix_proxy/m/api/permission/getSchedulePermission", {args={username=ngx.var.cookie_example , url=ngx.var.request_uri}})
                if res.status == ngx.HTTP_FORBIDDEN then
                    ngx.exec("@hello")
                elseif res.status == ngx.HTTP_OK then
                    ngx.exec("@/")
                elseif res.status == ngx.HTTP_INTERNAL_SERVER_ERROR then
                    ngx.exec("@servererror")
                else
                    ngx.exec("@error")
                end
        ‘;}
    }

以上是关于通过lua进行nginx的权限控制的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 nginx 将路径参数传递给 lua 代码?

《springcloud 二》SrpingCloud Zuul 微服务网关搭建

[nginx]lua控制响应头

NGINX + LUA实现复杂的控制 --源自http://outofmemory.cn/code-snippet/14396/nginx-and-lua

Nginx + Lua + Cookie 控制灰度发布

Nginx结合Lua实现限流