• 通过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的执行顺序,可以看这张图
    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:
    
    [root@10-110-157-48 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:
    
    [root@10-110-157-48 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:
    
    [root@10-110-157-48 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配制实例
    [root@vm-10-112-42-12 conf.d]# cat matrix-tu.conf
    upstream matrix.lebi.letv.cn {
    	ip_hash;
    	server 10.112.42.140:8080;
    	server 10.112.42.141:8080;
    	server 10.112.42.142:8080;
            keepalive 100;
    }
    
    upstream matrix-tu.lebi.letv.cn {
            server 10.110.150.217;
            keepalive 100;
    }
    
    
    server {
    	    listen	80;
    	    server_name  matrix-tu.lebi.letv.cn;
    
    	    access_log /letv/nginx/logs/lebitableau.a.log main;
    	    error_log /letv/nginx/logs/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://matrix-tu.lebi.letv.cn;
    	        proxy_send_timeout	18000;
    	        proxy_read_timeout	18000;
    	        proxy_next_upstream	error timeout invalid_header http_500;
    	        proxy_connect_timeout 20;
    	    }
    		
    		location = / {
    		return 403;
    		}
    		
    		location ~ /authoring/ {
    		return 403;
    		}
    
    		location @/ {
    	        proxy_pass	http://matrix-tu.lebi.letv.cn;
    		}
    
    	    location ~ /matrix_proxy/(.*) {
    	        internal;
    	        proxy_pass http://matrix.lebi.letv.cn/$1$is_args$args;
    	    }
    
    	    location /m/resource/tableauLogin {
                    proxy_http_version 1.1;
                    proxy_set_header Connection "";
                    proxy_set_header Host $host;
                    proxy_pass      http://matrix.lebi.letv.cn;
                    proxy_send_timeout      18000;
                    proxy_read_timeout      18000;
                    proxy_next_upstream     error timeout invalid_header http_500;
                    proxy_connect_timeout 20;
    		add_header Access-Control-Allow-Origin "http://matrix.lebi.letv.cn";
      		add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
      		add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    		add_header Access-Control-Allow-Credentials true;
                }
    
    		location @error {
                            default_type 'text/plain';
                            content_by_lua 'ngx.say("lua error")';
    
    		}
    		location ~ /wenz_img.png$ {
    			root /etc/nginx/forbidden;
    		}
    
    		location ~ /beierx_img.png$ {
    			root /etc/nginx/forbidden;
    		}
    
    
    		location ~ /error_bg.png$ {
    			root /etc/nginx/forbidden;
    		}
    
    
    
    		location @servererror {
    			default_type 'text/plain';
    			content_by_lua 'ngx.say("server error")';
    		}
    
    		location @forbidden {
    			return 403;
    		}
    		
    		location @nousername {
    			rewrite ^(.*)$ http://matrix.lebi.letv.cn/#/index break;         ##所有页面跳转到登录页面
    		}
    		
    		#proxy_intercept_errors on;
    		error_page 403 /403.html;
    
    		location = /403.html {
    		root /etc/nginx/forbidden;
    		#internal;
    		}
    
    
    		proxy_intercept_errors on;         ##加入将http反代错误拦截并以nginx的错误状态码显示
    		error_page 404 /404.html;        ##自定义nginx的404错误显示页面
    		location = /404.html {
    		root /etc/nginx/forbidden;
    		}
    
    		location @ok {
    			default_type 'text/plain';
    			content_by_lua 'ngx.say("authorized ok, cookie=", ngx.var.cookie_78bdfe11ce353909cb210160a76c330b)';
    		}
    
    		location ~ ^/views/ {
    			#default_type 'text/plain';
    			access_by_lua '
    			--local cookie_value = ngx.var.cookie_78bdfe11ce353909cb210160a76c330b
    			--ngx.say("cookie= ", cookie_value)
    			local res = ngx.var.cookie_78bdfe11ce353909cb210160a76c330b
    			if not res then
    				ngx.exec("@nousername")                ##判断是否能获取到用户的cookie,如果不能获取,则直接执行nousername规则,进行用户登录页面的跳转
    			else
    				local res = ngx.location.capture("/matrix_proxy/m/api/permission/getSchedulePermission", {args={username=ngx.var.cookie_78bdfe11ce353909cb210160a76c330b , url=ngx.var.request_uri}})
    				if res.status == ngx.HTTP_FORBIDDEN then
    					ngx.exec("@forbidden")
    				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
    			end
    		';}
    }
    
  • 相关阅读:
    活动Activity——Activity的生命周期&各状态之间的切换过程——重点
    app简单控件了解——同时展示文本与图像
    app简单控件了解——按钮——第三种按钮点击方式——MainActivity 实现 View.OnClickListener 接口
    app的活动页面——创建方式二 ——快速生成页面源码——以及页面跳转示例
    app简单控件了解——图像按钮——图像按钮ImageButton
    app简单控件了解——按钮——书本示例——采用了匿名内部类与MainActivity 实现 View.OnClickListener 接口——两种方式
    app简单控件了解——图像显示——图像视图ImageView
    app简单控件了解——按钮——禁用与恢复按钮
    活动Activity——Activity的启动和结束
    搜索引擎的小技巧【可以组合起来使用】:
  • 原文地址:https://www.cnblogs.com/marility/p/8490058.html
Copyright © 2020-2023  润新知