Nginx反向代理转发Azure Blob存储签名URL参数失败的问题排查
嗨,我来帮你拆解下这个问题的根源和修复方案~
问题出在哪?
你当前的Nginx rewrite规则有个关键错误:rewrite ^ /?sp=rl&... break; 这条规则会把所有访问/documents路径的请求,不管原路径里的MyTest/doc.pdf是什么,直接重写成根路径/?[签名参数],这就把请求中最重要的Blob路径给丢了!
当Nginx把这个重写后的路径拼接到proxy_pass地址后,实际发给Azure Blob的请求变成了:https://testtestsitweu.blob.core.windows.net/publicfiles/?sp=rl&[其他签名参数]
而你的签名是针对publicfiles/MyTest/doc.pdf这个具体资源(或者容器级别的签名但需要正确的路径结构),Azure收到这种错误的URL结构后,自然会抛出“指定的签名资源不允许用于此资源级别”的认证失败错误。
怎么修复?
我们需要让Nginx完整保留请求中的Blob路径,再把签名参数正确附加到请求末尾。这里有两种靠谱的配置方式:
方式一:用rewrite捕获路径并拼接签名
这种方式直接把/documents/后面的路径捕获,拼接成Azure Blob的完整访问路径,再加上签名参数:
location /documents { # 捕获/documents/后的所有路径,拼接成publicfiles/xxx的格式,再附加签名 rewrite ^/documents/(.*)$ /publicfiles/$1?sp=rl&st=2024-02-15T14:18:59Z&se=2025-02-15T22:18:59Z&spr=https&sv=2022-11-02&sr=c&sig=TxTOjuaaaaaaaaaaaaaaaaaaaaaaaaaNgU%3D break; proxy_pass https://testtestsitweu.blob.core.windows.net; proxy_ssl_name testtestsitweu.blob.core.windows.net; proxy_ssl_server_name on; }
配置后,当你访问http://localhost:4200/documents/MyTest/doc.pdf,Nginx会转发成:https://testtestsitweu.blob.core.windows.net/publicfiles/MyTest/doc.pdf?[完整签名参数]
完全符合Azure Blob的访问格式,认证就能通过了。
方式二:利用proxy_pass的路径拼接特性
如果想更灵活管理签名参数,可以单独处理路径和查询参数:
location /documents/ { # 去掉/documents前缀,把剩余路径转发到publicfiles容器下 proxy_pass https://testtestsitweu.blob.core.windows.net/publicfiles/$uri; # 附加签名参数到查询字符串 proxy_set_header Query_String "sp=rl&st=2024-02-15T14:18:59Z&se=2025-02-15T22:18:59Z&spr=https&sv=2022-11-02&sr=c&sig=TxTOjuaaaaaaaaaaaaaaaaaaaaaaaaaNgU%3D"; proxy_ssl_name testtestsitweu.blob.core.windows.net; proxy_ssl_server_name on; }
如果你的请求还可能带其他自定义查询参数,也可以用$is_args$args把原始参数一起带上,比如把proxy_pass改成:proxy_pass https://testtestsitweu.blob.core.windows.net/publicfiles/$uri?$args&sp=rl&[其他签名参数];
额外提醒
- 确认你的SAS签名的
sr参数:如果是sr=c(容器级别),修复路径后就能访问容器下所有Blob;如果是sr=b(单个Blob级别),要确保签名是针对publicfiles/MyTest/doc.pdf这个具体路径生成的,不然还是会报错。 - 修改配置后记得用
nginx -t验证配置语法,没问题再重启Nginx生效~
备注:内容来源于stack exchange,提问作者ilhan

