Aliyun OSS Nginx proxy module(阿里云OSS Nginx 签名代理模块)

来源:互联网 发布:知乎封面图片尺寸 编辑:程序博客网 时间:2024/06/08 14:24

1、此文章主要介绍内容

本文主要介绍如何利用Nginx lua 实现将阿里云OSS存储空间做到同本地磁盘一样使用。核心是利用Nginx lua 对OSS请求进行签名并利用内部跳转将所有访问本地Nginx的请求加上OSS 签名转发给OSS,实现本地Nginx无缝衔接阿里云OSS,存储空间无限扩展,存储成本无限下降,数据安全%99.99…… 。

2、本篇文章使用到的一些工具技术及如何学习和获取

1、lua

本文用到的都是一些基本的lua,基本上花半小时阅读下lua的语法就可以轻松理解本文内容

2、Nginx lua

主要是学习nginx lua 及环境部署,不过阅读本文还不需要亲自动手去学习及部署nginx lua 环境,读者可以从docker 官方镜像源pull openresty 镜像进行实验。本文已openresty/1.7.7.2 作为实验环境。

3、阿里云OSS

赶紧开通吧,用起来相当爽,一处存储全球无限制访问
https://www.aliyun.com/act/aliyun/ossdoc.html

4、参考博客

建议阅读我的另外一篇博客,对深入理解OSS 及互联网上提供的HTTP服务有更深刻的理解
http://blog.csdn.net/sunrain_chy/article/details/50804410

3、利用Nginx lua 实现请求签名并转发至OSS

Lua 签名 code
注:此代码并非出自作者之手
oss_auth.lua

-- has been sorted in alphabetical orderlocal 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'}function string.startswith(s, start)   return string.sub(s, 1, string.len(start)) == startendlocal 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 sendlocal 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)endlocal 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_strend   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   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.exec("@oss")end   -- mainres = 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、如何使用上述代码

首先oss_auth.lua 无需做任何改动

nginx.conf 中需要将
your_oss_bucket 替换为阿里云OSS 的bucket名
your_access_id替换未AccessKeyId
your_access_key 替换为 AccessKeySecret

例如:

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;        }    }}
1 0
原创粉丝点击