Nginx访问FTP服务器文件的时效性/安全校验的方法

 更新时间:2023年12月12日 09:23:39   作者:Code A Better Life  
nginx的实现方式在校验失败的时候页面返回error image,跳转的是420 error_page,成功的时候会访问FTP文件服务器的路径,反正图片到页面展示,这篇文章主要介绍了Nginx访问FTP服务器文件的时效性/安全校验,需要的朋友可以参考下

背景

FTP文件服务器在我们日常开发中经常使用,在项目中我们经常把FTP文件下载到内存中,然后转为base64给前端进行展示。如果excel中也需要导出图片,数据量大的情况下会直接返回一个后端的开放接口地址,然后在项目中对接口的参数进行鉴权,或者实效性检验等,最后从FTP下载图片用流的方式传到浏览器中。

但是这种方式会加大内存的消耗,所有的文件相关的都在内存中下载回传给前端;报表下载的数据量很大的情况下服务很容易拖垮。所以就设想通过两层nginx反向代理的方式是否可以满足文件的直接访问。

假设FTP文件服务器的照片存放地址为:/upload/signature

传统实现

首先我们在下载excel的时候需要组装一个url,如下所示的get请求就是一个对外开放无需权限的接口,真实情况下会对realFilePath进行加密组装,里面放一些timestamp或者redis的key来验证实效性、安全性等。

  @GetMapping("/signatureImage/{path}")
    public void signatureImage(@PathVariable("path") String realFilePath, HttpServletResponse response) throws IOException {
        //realFilePath = "/20231206/qhyu.png"
        String fileName = "qhyu.png"; //可以切割获取。
        String path = "/upload/signature"; // 固定的存放路径
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try (Ftp ftp = new Ftp("Ftp_address", "Ftp_port", "username", "password")) {
            ftp.download(path+realFilePath, fileName, outputStream);
        } catch (Exception e) {
            log.error("FTP文件下载出错:{}", e.getMessage());
            throw new QhyuException(MessageCode.FILE_DOENLOAD_ERROR.getCode());
        }
        // 将内存中的文件内容转换为输入流
        InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        // 设置响应的内容类型为图片格式
        String contentType = MediaType.IMAGE_PNG_VALUE; // 假设为PNG格式
        response.setContentType(contentType);
        org.apache.commons.io.IOUtils.copy(inputStream, response.getOutputStream());
        response.flushBuffer();
        // 关闭内存流和FTP连接
        inputStream.close();
        outputStream.close();
    }

Nginx实现

要通过Nginx实现的话,基本上网上的方案都是让使用lua。虽然可以但是没必要。因为我从官网上找到了解决方案,如下所示。

在这里插入图片描述

提供一下proxy相关参数的含义:

  • proxy_set_header Host $host;

此参数设置了将客户端请求中的Host头部信息传递给代理服务器。$host变量表示客户端请求中的主机名。

  • proxy_intercept_errors on;

当启用此参数时,代理服务器会拦截后端服务器返回的错误响应,并将其作为代理服务器的响应返回给客户端。这允许代理服务器处理后端服务器的错误响应,并可以进行自定义的错误处理。

  • proxy_set_header X-Real-IP $remote_addr;

此参数设置了将客户端的真实IP地址传递给代理服务器。$remote_addr变量表示客户端的IP地址。

  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

此参数设置了将客户端的IP地址添加到X-Forwarded-For头部信息中。$proxy_add_x_forwarded_for变量表示将客户端IP地址添加到现有的X-Forwarded-For头部信息中。

  • proxy_buffering off;

当启用此参数时,禁用代理缓冲。代理缓冲可以在接收完整的响应后再将其发送给客户端,以提高性能和效率。禁用缓冲意味着代理服务器会立即将收到的数据发送给客户端,适用于需要实时数据传输的场景。

下面就是我的nginx配置:

    server {
        listen       10086;
        charset utf-8;
        access_log      /var/log/nginx/qhyu/qhyu_access.log;
        error_log      /var/log/nginx/qhyu/qhyu_error.log;
   location /verify {
        proxy_pass http://host:port/api/signatureImage/validate?realFilePath=$arg_realFilePath&signature=$arg_signature;
        proxy_set_header Host $host;
        proxy_intercept_errors on;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffering off;
        error_page 418 = @custom_redirect;
        error_page 420 = @custom_error;
     }
      location @custom_error{
        default_type application/json;
        return 200 'error image';
      }
      location @custom_redirect {
        rewrite ^ /signature/$arg_realFilePath last;
      }
      location /signature {
        alias /upload/signature/;
      }
}
}

然后就是编写了一个接口,也就是在调用的时候可以访问/verify接口带上参数,就会跳转到这个接口进行校验,如果返回的http状态码是418说明校验通过,如果返回的是420说明校验失败。

@GetMapping("/signatureImage/validate")
    public Object signatureValidate(String realFilePath,String signature,HttpServletResponse httpServletResponse){
        String redisKey = AesEncryptUtil.decryption(signature);
        if (StrUtil.isBlank(redisKey)){
            httpServletResponse.setStatus(420);
            return RenderResult.success();
        }
        Object value = redisService.get(redisKey);
        if (value == null) {
            httpServletResponse.setStatus(420);
            return RenderResult.success();
        }
        List<String> signatureUrls = JSON.parseArray(JSON.toJSONString(value), String.class);
        if (signatureUrls == null || signatureUrls.isEmpty()){
            httpServletResponse.setStatus(420);
            return RenderResult.success();
        }
        if (!signatureUrls.contains(realFilePath)){
            httpServletResponse.setStatus(420);
            return RenderResult.success();
        }
        // greater than or equal to 300 should be passed to a client or be intercepted and redirected to nginx
        // for processing with the error_page directive
        // http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
        httpServletResponse.setStatus(418);
        return RenderResult.success();
    }

分析结果

nginx的实现方式在校验失败的时候页面返回error image,跳转的是420 error_page;成功的时候会访问FTP文件服务器的路径,反正图片到页面展示。在实际的开发过程中,外层可能还会有一个nginx反向代理,本文主要讲解了一下如何使用这个方式对访问的文件进行鉴权。

这样做的好处就是不需要每个文件都下载到内存然后使用流的方式传输,直接访问的方式减少了后端服务的压力,并且像头像、签名这种可能访问频繁的接口使用这种方式来处理是很棒的一种方式。

主要的思路就是拿到proxy_pass的返回信息,如果使用lua的话可以获取到我们返回的body内容,但是不使用lua的时候我们可以迂回处理,使用status code也一样可以达到目的。

到此这篇关于Nginx访问FTP服务器文件的时效性/安全校验的文章就介绍到这了,更多相关Nginx访问FTP服务器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • win10上安装nginx的方法步骤

    win10上安装nginx的方法步骤

    这篇文章主要介绍了win10上安装nginx的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • nginx-ingress-controller日志持久化方案的解决

    nginx-ingress-controller日志持久化方案的解决

    这篇文章主要介绍了nginx-ingress-controller日志持久化方案的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • Nginx禁止指定UA访问的方法

    Nginx禁止指定UA访问的方法

    这篇文章主要介绍了Nginx禁止指定UA访问的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • 解读Nginx和Apache的特点与区别

    解读Nginx和Apache的特点与区别

    这篇文章主要介绍了解读Nginx和Apache的特点与区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 通过nginx实现访问服务器指定目录下图片资源

    通过nginx实现访问服务器指定目录下图片资源

    这篇文章为大家详细主要介绍了如何通过nginx实现访问服务器指定目录下图片资源,文中通过图文进行了详细的讲解,有需要的小伙伴可以了解下
    2023-10-10
  • Nginx设置404错误页面跳转的几种方法总结

    Nginx设置404错误页面跳转的几种方法总结

    一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有些相关配置方法,下面小编给大家带来了Nginx实现404页面的几种方法,感兴趣的朋友一起看看吧
    2024-03-03
  • Nginx实现UDP四层转发的过程

    Nginx实现UDP四层转发的过程

    为了解决VPN连接速度慢的问题,可以通过Nginx实现UDP的四层转发,首先检查Nginx是否安装了with-stream模块,然后修改nginx.conf配置文件进行UDP端口的转发设置,使用nginx-t检查配置文件语法,无误后重新加载Nginx,这样通过国内服务器中转,可以提升连接到国外服务器的速率
    2024-09-09
  • Nginx隐藏式跳转(浏览器URL跳转后保持不变)

    Nginx隐藏式跳转(浏览器URL跳转后保持不变)

    这篇文章主要介绍了Nginx隐藏式跳转(浏览器URL跳转后保持不变),需要的朋友可以参考下
    2022-04-04
  • 在Nginx服务器中启用SSL的配置方法

    在Nginx服务器中启用SSL的配置方法

    这篇文章主要介绍了在Ningx服务器中启用SSL的配置方法,本文前提是已经在Linux系统下安装好了OpenSSL,需要的朋友可以参考下
    2015-08-08
  • Nginx服务优化配置方案

    Nginx服务优化配置方案

    这篇文章主要介绍了Nginx服务优化配置方案,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-03-03

最新评论