使用nginx + lua进行token鉴权

最近在使用minio文件服务器,来实现图片上传与展示功能,在展示的时候出现一个问题,就是图片在做鉴权时,minio提供的有效地址是真的拉跨,没法实现图片链接的有效鉴权功能,而且链接直接给出来的话也有风险。

后面想着加一个反向代理的方式,也就是Nginx做代理,这样就不会暴露图片的ip地址。但是,在做鉴权时遇到了麻烦,网络上大部分推荐lua脚本来实现鉴权的方式,在经过几天的不断试错,才最终将他实现,现在在此记录下。

工具:openresty(nginx集成lua模块,比较简单)

lua包需要下载lua-resty-http工具包,地址lua-resty-http,解压后将.lua文件放到 lualib\resty目录下就行。

实现思路:用户发送请求---> nginx ----->根据图片路径策略-----> 执行lua代码(发送http到后端token鉴权)----->通过就代理到具体图片服务器----->否则提示无权限

nginx关键代码

http {
    
    # 定义全局变量
    init_by_lua_block {
		cjson = require "cjson";
		http = require "resty.http";
	}

    server {
        
        location ~^/(api)/image/(.*)$ {
			rewrite_by_lua_block {
				-- local cjson = require "cjson"
				-- local http = require "resty.http"
				local httpc = http.new()
				local ngx = ngx
				local headers = ngx.req.get_headers()
				-- get请求参数中T就是token
				local token = headers["token"]
				local request_method = ngx.var.request_method
				local args = nil
				if "GET" == request_method then
					args = ngx.req.get_uri_args()
				elseif "POST" == request_method then
					ngx.req.read_body()
					args = ngx.req.get_post_args()
				end
				
				token = args["token"];
				if not token then
					ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
					ngx.status = ngx.HTTP_FORBIDDEN
					ngx.say("您无权限浏览该图片。")
					ngx.exit(200)
				end
				-- 字符串拼接
                -- 你要实现token鉴权的服务,header和参数都给你实现了,根据实际需要选择
				local url = "http://127.0.0.1:8080/image/checkToken?token="..token;
				
				local res, err = httpc:request_uri(url, {method="GET", headers={["token"]=token}})
				
				if not res then 
					ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
					ngx.say(cjson.encode({message = "Error getting response",status = ngx.HTTP_INTERNAL_SERVER_ERROR }));					
					ngx.exit(200)
				end
                if res.body == '0' then 
					ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
					ngx.say("您无权限浏览该图片。");					
					ngx.exit(200)
				end	
			}
			
			proxy_pass http://yourip:9000/$2;
			
		}
    }
}

Java后端代码

@RestController
@RequestMapping("/image")
public class TokenResource {
    @RequestMapping("/checkToken")
    public String checkToken(HttpServletRequest request, String token) {
        System.out.println("程序进来了");
        String header = request.getHeader("token");
        System.out.println("头部token:" + header);
        if (StringUtils.isEmpty(token)) {
            System.out.println(token + ":0");
            return "0";
        }
        if ("1".equals(token)) {
            System.out.println(token + ":1");
            return "1";
        }
        return "0";
    }
}

当token校验通过,就不做拦截,lua代码执行完会走到nginx的转发路径上来

​
proxy_pass http://your_ip:9000/$2​

~^/(api)/image/(.*)$ 写成 ~^/api/image/(.*)$ 时 proxy_pass 改为 http://your_ip:9000/$1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值