繁体   English   中英

安全地允许用户生成的文件从服务器下载

[英]Securely allow user-generated files to be downloaded from server

我使用Tomcat8 / Java

我目前允许通过使用GUID创建文件名,然后将其保存在公共目录中,并提供该文件的链接,来从服务器下载敏感的用户生成的Excel文件(以Java / POI创建)。

阶段1

用户选择各种参数,JSP将这些参数发送到Java文件

String fileName = "excelFiles/"
                + myReports
                        .createExcel(listCompanyDetails);

public static String createExcel(List listCompanyDetails) {
        String fileName = "MyFile"+UUID.randomUUID() + ".xls";
        String fileFullPath="\..."+fileName;
        FileInputStream inputStream = new FileInputStream(new File(APPCodeTable.templateExcelFile));
        Workbook wb=new HSSFWorkbook(inputStream);
        FileOutputStream out = new FileOutputStream(fileFullPath);
        wb.write(out);
        out.close();
}

第二阶段

然后,JSP将文件显示在iFrame中

<iframe id="target_upload" name="target_upload" width="100%"
src="<%=fileName%>" height="100%"></iframe>

在我们的系统上完成的渗透测试的结果表明,我们应该改为从jsp文件生成流中的文件,这样做会更加安全,因为它将避免使用GUID,并且避免直接链接到该文件将绕过登录授权。

但是,似乎最好使用servlet进行编码。 例如, 实现一个简单的文件下载servlet

我正在考虑将文档保存在由GUID标识的服务器上,然后将此GUID传递给servlet。 但是,这似乎违背了我提高安全性的初衷。

如果我实现了一个简单的下载servlet(如附件中的链接),那么如何在servlet中获取创建的文件?

通过将工作簿写入HttpServletResponse.getOutputStream(),而不是在阶段1中写入文件并在阶段2中读取该文件,可以有效地将两个步骤折叠为1。

1.收集用户参数(假设这是在<form> )并针对IFRAME进行发布。 例如

 <form action="reportservlet/MyReport.xls" method="POST" target="target_upload">

2.设置新的Servlet +映射(*映射允许MyReport.xls部分为任何内容,包括在提交表单时动态生成的内容)。

<servlet>
    <servlet-name>ReportServlet</servlet-name>
    <servlet-class>foo.ReportServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ReportServlet</servlet-name>
    <url-pattern>/reportservlet/*</url-pattern>
</servlet-mapping>

3.在您的servlet中,类似于(忽略servlet中的业务逻辑的“不良设计”。这仅是说明性的)

public void doPost(HttpServletRequest req, HttpServletResponse rsp) throws ServletException {
    // all the security stuff and stuff to produce List listCompanyDetails
    FileInputStream inputStream = new FileInputStream(new File(APPCodeTable.templateExcelFile));
    Workbook wb=new HSSFWorkbook(inputStream);
    rsp.setContentType("application/vnd.ms-excel");
    wb.write(rsp.getOutputStream()); // this is the key...write directly to the request output vs. a temp file
}

一些评论..

  1. 我假设您正在为一组受良好控制的用户进行开发,这些用户将a)使用IE,b)安装了Excel-在IFRAME中定位excel内容是一个非常糟糕的主意
  2. 绝对不要使用JSP代替我建议的Servlet-使用JSP生成二进制数据只是一个“坏主意”。 从技术上讲是可行的,但是除非正确构造JSP,否则很可能会引入字符数据(很可能是很难看到的换行符和/或尾随空格),这会破坏XLS

我实现了来自实现简单文件下载servlet的 @wen的答案

此外,我删除了使用@Ramesh PVK在如何拒绝对Tomcat目录的Web访问中的建议对文件保存目录的直接Web访问。

<security-constraint>
  <web-resource-collection>
    <web-resource-name >precluded methods</web-resource-name>
    <url-pattern >/excelFiles/*</url-pattern>
    </web-resource-collection>
    <auth-constraint/>
</security-constraint>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM