[转载] nginx +后端 对静态文件进行鉴权

news/2024/11/14 14:16:15/

Java SpringBoot下使用X-SendFile实现文件下载 - 行万里路才能回到内心深处,读万卷书才能看得清皓月繁星

Java SpringBoot下使用X-SendFile实现文件下载

  •  Lokie.Wang
  •  2022-10-10 22:26:19
  •  笔记
  •  SpringBoot nginx

1.起因

在项目中有一个文件是服务器端打包生成后的文件放在服务器中某一个目录内,文件的特点如下:

  • 体积比较大,超过1G家常便饭
  • 数据比较敏感,业务上不能匿名下载,必须有严格的权限和鉴权体系
  • 终端用户使用的环境网络不稳定或者网速非常缓慢

2.传统做法

传统做法很容易,采用SpringBoot建立API,采用Token等方式对用户权限鉴定后,读取文件流,由Java发送给客户端。这样不暴露静态HTTP链接给用户,解决了鉴权问题。但是由于文件大用户网速慢并且不稳定等各种原因实际效果并不理想。主要问题如下:

  • 由于工作在nginx代理后,有超时现象发生来源
  • 用户希望有断点续传功能,无法轻易实现
  • 读文件Java开销比较大

3 解决方案

思路:能否结合让静态文件下载由类似nginx这样的web服务器去进行,并有一鉴权功能。方案当然是有的,比如采用lua或者自己编写nginx插件,但是改动都比较大成本非常高,查阅文档后发现可以采用如下x-sendfile这中方式来实现。

3.1 什么是X-SENDFILE

X-Sendfile 通过一个特定的 HTTP header 来实现:在 X-Sendfile 头中指定一个文件的地址来通告前端 web 服务器。当 web 服务器检测到后端发送的这个 header 后,它将忽略后端的其他输出,而使用自身的组件(包括 缓存头 和 断点重连 等优化)机制将文件发送给用户。

在使用 X-Sendfile 之前,我们必须明白这并不是一个标准特性,在默认情况下它是被大多数 web 服务器禁用的。而不同的 web 服务器的实现也不一样,包括规定了不同的 X-Sendfile 头格式。如果配置失当用户可能会下载到错误的文件。

SENDFILE 头使用的 WEB 服务器
X-SendfileApache, Lighttpd v1.5, Cherokee
X-LIGHTTPD-send-fileLighttpd v1.4
X-Accel-RedirectNginx, Cherokee

缺点:由于发送下载文件由nginx做了,所以Java是无法知道文件下载完成的

3.2 Nginx的X-SENDFILE

这里主要说明nginx的X-SENDFILE配置。

3.2.1 相关特殊的HTTP头

  • X-Accel-Redirect:设置URI给nginx进行内部的跳转
  • X-Accel-Buffering:下载使用Cache,默认YES
  • X-Accel-Expires: 缓存超时时间。
  • X-Accel-Limit-Rate:限速

3.2.2 相关配置

在nginx配置文件中设置如下:

location /protected/ {internal;root   /some/path;
}

internal指令保证了这个链接只能被nginx自己访问,root可以映射目录。

4 示例

Nginx 配置

# 动态权限
locaton /api/ {proxy_pass http://upstream:8080/;
}
#内部静态地址
location /download/ {internal;root   /some/path;
}

注意: /some/path/donwload文件夹必须存在

这里以Springboot Java代码作为例子

@RequestMapping(value = "/api/download", method = RequestMethod.GET)public void plistDownLoad(HttpServletResponse response, @RequestParam("bidSectionID") String bidSectionID,@RequestParam("token") String token,HttpServletResponse response) { // 权限代码if(authService.auth(token)) {String filePath = fileService.getFilte(bidSetionID)// 上面返回 /download/test.zipStirng outFileName = FileNameUitls.getFileName(filePath);String contentDisposition = "attachment" + ";filename*=UTF-8''" + URLEncoder.encode(outFileName, "UTF-8");response.setHeader("Content-Type", "application/octet-stream;charset=utf-8");response.setHeader("Content-Disposition", contentDisposition);response.setHeader("X-Accel-Redirect", filePath);} else  {// 报错response.setCharacterEncoding("UTF-8");response.setContentType("application/json;charset=UTF-8");PrintWriter pw = response.getWriter();pw.write("非法访问");pw.flush();pw.close();}}

本文为Lokie.Wang原创文章,转载无需和我联系,但请注明来自lokie博客http://lokie.wang


Nginx与X-Sendfile

Nginx与X-Sendfile_ITPUB博客
 

Nginx与X-Sendfile

原创 Linux操作系统 作者:j58415115 时间:2012-08-07 02:41:29  176  0

X-accel模块允许由后台通过返回的头来决定投递静态文件。为什么要这么做呢?试想一下我们经常碰到的这种情况,在有的论坛中,下载资源需要登录认证、权限核查、积分扣除或者是积分增加等等,对于Nginx来说这些细粒度的控制其本身无法完成,因此需要应用程序来完成,当应用程序完成这些操作后,根据实际情况会做出选择,如果条件满足那么开始下载所要获取的静态资源(文件),注意,这是由动态的程序提供下载,对于动态程序来说,这是一个弱点,而对于Nginx来说,这是它的强项,那么在这种形式下能不能让Nginx来完成静态资源的下载呢?答案是可以的。但我们为什么有必要这么做呢?答案在于Nginx在打开静态文件上使用了sendfile(2),因此其IO效率非常之高。

 

处理流程

 

    具体的处理流程是:

 

   

      -------------------

     |"GET /dd/filename  |

     |                   |

    ∨                   |

  客户端请求----------->Nginx----->Backend(Apache、Tomcat、FastCGI,……)

∧                                       |

                          |                                       |

                          |  X-Accel-Redirect: /files/filename    |

|_______________________________________|

   

 

    我们从这个流程图中不难看出在客户端的请求被转向后台服务器时,服务器并没有为客户端返回实际要下载的资源(而是去做了其它的验证或者是其它的工作)而是使用了X-Accel-Redirect头将下载的资源又传递给了Nginx,最后又是通过Nginx服务器处理该请求发送给客户端。

 

    这种功能就是我们说的X-Sendfile,在Nginx中由X-Accel-Redirect来完成,在后台服务器将下载的请求抛给Nginx后,那么后台的服务器又可以承接其它的活进而处理其它的请求了,因此大大的减轻了后端服务器的压力。

 

    相对于其它的Nginx来说,X-accel模块与其它标准的Nginx模块有所不同,它的实现不是依赖于指令而是依赖于在特定方式下后台(或者叫上游)服务器发回的请求头,它的方法我们在前面也了解到了,就是通过发送一个带有URI的x-accel-redirect头,Nginx将会将这个请求作为正常(这里的正常就是指就像是使用浏览器一样的请求)的请求来处理这个请求,然后根据这个URI进行location匹配,然后是请求文件的匹配,最终实现的是在后端服务器返回的请求头中:“root + URI”与Nginx中location匹配,这里的“root”,我们以PHP程序为例:

 

header("X-Accel-Redirect: /files/" . $path);

   

    就是我们这个PHP程序中的“/files/”部分,而URI则是“$path”部分。在这里我们就了解到这里,在后面的例子会证实这一点。

 

    另外,还需要注意一点,由于Nginx服务器只认识从后端服务器发来的X-Accel-Redirect头,而从客户端发来的这种头,它并不理睬。

 

配置示例

 

# Will serve /var/www/files/myfile.tar.gz

# When passed URI /protected_files/myfile.tar.gz

location /protected_files {

    internal;

    alias /var/www/files;

}

 

# Will serve /var/www/protected_files/myfile.tar.gz

# When passed URI /protected_files/myfile.tar.gz

location /protected_files {

    internal;

    root /var/www;

}

 

You can also proxy to another server.

 

location /protected_files {

    internal;

    proxy_pass

}

 


 


http://www.ppmy.cn/news/106179.html

相关文章

MySQL数据库——MySQL如何分析查询语句?

MySQL是一种常用的关系型数据库管理系统,提供了强大的查询语句分析功能,以帮助开发人员优化查询性能。在本文中,我将详细介绍MySQL如何分析查询语句。 查询语句分析是MySQL中的一个关键过程,它通过分析查询语句的执行计划和性能指…

【SCI征稿】1区计算机科学类SCI, 自引率低,对国人友好~

一、【期刊简介】 JCR1区计算机科学类SCI&EI 【期刊概况】IF: 7.0-8.0,JCR1区,中科院2区; 【终审周期】走期刊系统,3-5个月左右录用; 【检索情况】SCI&EI双检; 【自引率】1.30% 【征稿领域】发表人工智能…

MySQL 系统信息函数

文章目录 系统信息函数1. 查看当前 MySQL 数据库版本号2. 查看当前使用的数据库3. 查看当前服务器连接次数 系统信息函数 当我们需要知道当前 MySQL 数据库的一些基本信息和使用情况的时候,可以使用系统信息函数来获取相关信息,以随时掌握数据库的使用情…

【操作系统】01.操作系统概论

操作系统的发展历史 未配置操作系统 手工操作阶段 用户独占全机,人机速度矛盾导致系统资源利用率低 脱机输入输出方式 为了缓解主机cpu和IO设备之间速度不匹配的矛盾,出现了脱机IO技术 在外围机的控制下,通过输入设备,将数据输…

排水管网监测预警系统:全面感知管网运行态势

城市排水管网是城市基础设施系统中至关重要的一部分,它负责将雨水和废水排出城市,维持城市的正常运行。然而,随着管网的老化和城市扩张,排水管网出现了越来越多的问题,如泄漏、堵塞和损坏,给城市环境和公共…

Golang指针, 值类型,标识符,关键字,运算符初始

Golang指针, 值类型,标识符,关键字,标识符 采用文章 https://www.runoob.com/go/go-operators.html本章使用go练习工具 https://tour.go-zh.org/welcome/1指针 基本介绍 基本数据类型,变量存的就是值,也叫值类型获…

CodeForces..翻转魔术.[简单].[].[]

题目描述: 题目解读: 给定由0,1组成的长度为n的字符串,执行翻转操作,即0变1,1变0; 判断执行一次翻转之后是否为回文。 解题思路: 寻找规律:如果翻转前已经是回文&…

牛客网基础语法11~20题

前言:今天是咱们第二期刷牛客网上的题目。 目标:对输入输出的格式,方法,类型掌握熟练,对double,float理解深入,编程思想更进一步。 鸡汤:人活着,再苦再累,都别…