Alibaba Cloud OSS image compression access openresty lua header signature (Alibaba Cloud OSS Nginx signature proxy module)

oss_auth.lua signed_subresources add'x   -oss-process' to realize image processing

Added

1. This article mainly introduces the content

This article mainly introduces how to use Nginx lua to use Alibaba Cloud OSS storage space as a local disk. The core is to use Nginx lua to sign OSS requests and use internal jumps to forward all requests to access local Nginx plus OSS signatures to OSS, so that local Nginx can seamlessly connect to Alibaba Cloud OSS, unlimited storage space expansion, and unlimited storage costs. Data security%99.99…….

2. Some tools and techniques used in this article and how to learn and acquire

1 、 lua

This article uses some basic lua, basically spend half an hour reading the grammar of lua, you can easily understand the content of this article

2、Nginx lua

Mainly to learn nginx lua and environment deployment, but reading this article does not need to learn and deploy nginx lua environment by yourself, readers can pull openresty mirror from the official docker mirror source to experiment. This article has been openresty/1.7.7.2 as the experimental environment.

3. Alibaba Cloud OSS

Hurry up and activate it, it’s pretty cool to use, one store has unlimited global access
https://www.aliyun.com/act/aliyun/ossdoc.html

4. Reference blog

It is recommended to read another blog of mine to have a deeper understanding of OSS and HTTP services provided on the Internet
http://blog.csdn.net/sunrain_chy/article/details/50804410

3. Use Nginx lua to implement request signing and forward it to OSS

Lua signature code
Note: This code is not from the author
oss_auth.lua


-- has been sorted in alphabetical order
local signed_subresources = {
   'acl',
   'append',
   'bucketInfo',
   'cname',
   'commitTransition',
   'comp',
   'cors',
   'delete',
   'lifecycle',
   'location',
   'logging',
   'mime',
   'notification',
   'objectInfo',
   'objectMeta',
   'partData',
   'partInfo',
   'partNumber',
   'policy',
   'position',
   'referer',
   'replication',
   'replicationLocation',
   'replicationProgress',
   'requestPayment',
   'response-cache-control',
   'response-content-disposition',
   'response-content-encoding',
   'response-content-language',
   'response-content-type',
   'response-expires',
   'restore',
   'security-token',
   'tagging',
   'torrent',
   'uploadId',
   'uploads',
   'versionId',
   'versioning',
   'versions',
   'website',
   'x-oss-process'
}

function string.startswith(s, start)
   return string.sub(s, 1, string.len(start)) == start
end

local function get_canon_sub_resource()
   local args = ngx.req.get_uri_args()
   -- lower keys
   local keys = {}
   for k, v in pairs(args) do
      keys[k:lower()] = v
   end
   -- make resource string
   local s = ''
   local sep = '?'
   for i, k in ipairs(signed_subresources) do
      v = keys[k]
      if v then
         -- sub table
         v = type(v) == 'table' and v[1] or v
         s = s .. string.format("%s%s=%s", sep, k, v)
         sep = '&'
      end
   end
   return s
end

local function get_canon_resource()
   resource = ''
   object = ngx.unescape_uri(ngx.var.uri)
   sub = get_canon_sub_resource()   
   return string.format("/%s%s%s", ngx.var.oss_bucket , object, sub)
end   

local function get_canon_headers()
   -- default: <lowerkey, value>
   local headers = ngx.req.get_headers()
   local keys = {}
   for k, v in pairs(headers) do
      if string.startswith(k, 'x-oss-') then
         -- client must assemble the same header keys
         if type(v) ~= 'string' then return nil end
         table.insert(keys, k)
      end
   end
   -- sorted in alphabetical order
   table.sort(keys)
   for i, key in ipairs(keys) do
      keys[i] = key .. ':' .. headers[key] .. '\n'
   end
   return table.concat(keys)
end

local function calc_sign(key, method, md5, type_, date, oss_headers, resource)
    -- string_to_sign:
    -- method + '\n' + content_md5 + '\n' + content_type + '\n'
    -- + date + '\n' + canonicalized_oss_headers + canonicalized_resource
    local sign_str = string.format('%s\n%s\n%s\n%s\n%s%s',
    method, md5, type_,
    date, oss_headers, resource)
    ngx.log(ngx.ERR, "SignStr:", sign_str, "\n")
    local sign_result = ngx.encode_base64(ngx.hmac_sha1(key, sign_str))
    return sign_result, sign_str
end   

local function oss_auth()
   -- ngx.log(ngx.INFO, 'auth')
   --local method = ngx.var.request_method
   local method = ngx.req.get_method()
   
   local content_md5 = ngx.var.http_content_md5 or ''
   
   local content_type = ngx.var.http_content_type or ''
  
   -- get date
   local date = ngx.var.http_x_oss_date or ngx.var.http_date or ''
   if date == '' then
      date = ngx.http_time(ngx.time())
      -- ngx.log(ngx.INFO, 'Date:', date)
      ngx.req.set_header('Date', date)
   end
   ngx.req.set_header('Date', ngx.http_time(ngx.time()))
   local resource = get_canon_resource()
   local canon_headers = get_canon_headers()
   local sign_result, sign_str = calc_sign(ngx.var.oss_auth_key, method, content_md5,
   content_type, date, canon_headers, resource)
   -- ngx.log(ngx.INFO, 'sign string:', sign_str)
   -- ngx.log(ngx.INFO, 'sign string len:', string.len(sign_str))
   local auth = string.format("OSS %s:%s", ngx.var.oss_auth_id, sign_result)
   ngx.req.set_header('Authorization', auth)

   ngx.log(ngx.EMERG,"<-- end :" .. auth)
    local headers = ngx.req.get_headers()
for k, v in pairs(headers) do

     ngx.log(ngx.EMERG,"[key]:",k," [v:",v)
end
   ngx.exec("@oss")
end   

-- main
res = oss_auth()

if res then
   ngx.exit(res)
end

nginx.conf

  server {
        listen 8000;

        proxy_http_version 1.1;
        proxy_buffering off;
        proxy_request_buffering off;

        location / {
            set $oss_bucket "your_oss_bucket";
            set $oss_auth_id "your_access_id";
            set $oss_auth_key "your_access_key";
            rewrite_by_lua_file "/path/oss_auth.lua";
        }

        # internal redirect
        location @oss {
            // endpoint eg: oss.aliyuncs.com
            proxy_pass http://your_oss_bucket.endpoint; 
        }
    }

4. How to use the above code

First of all, oss_auth.lua does not need to be changed.

In nginx.conf, you need to
replace your_oss_bucket with the bucket name of
Alibaba Cloud OSS your_access_id without
AccessKeyId and your_access_key with AccessKeySecret

E.g:

error_log  logs/error.log  debug;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    lua_package_path "/usr/servers/lualib/?.lua;";
    lua_package_cpath "/usr/servers/lualib/?.so;"; 
    server {
        listen       80;
        location / {
            set $oss_bucket "bucket-example";
            set $oss_auth_id "za2127hbbsdhjal0ytocbzr";
            set $oss_auth_key "gMOG3o+HJdsgdHdpieCNMcsaH+Q=";
            rewrite_by_lua_file conf/lua/oss_auth.lua;
        }

        location @oss {
            proxy_pass http://bucket-example.oss-cn-qingdao.aliyuncs.com;
        }
    }
}

access  

http://127.0.0.1/20200717/1594973763512-7a892062-1865-4006.jpg?x-oss-process=image/auto-orient,1/resize,m_lfit,w_400/quality,q_67

Guess you like

Origin blog.csdn.net/csl12919/article/details/107772148