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

时间:2016-08-17 14:43:59

标签: java security tomcat8

我使用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();
}

第2阶段

然后,JSP在iFrame中显示文件

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

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

然而,似乎使用servlet是更好的编码实践。例如Implementing a simple file download servlet

我正在考虑将文档保存在服务器上,由GUID标识,然后将此GUID传递给servlet。然而,这似乎打败了我改善安全的初衷。

如果我实现一个简单的下载servlet(如附带的链接),我怎样才能将我创建的文件放在该servlet中?

2 个答案:

答案 0 :(得分:0)

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

1。 收集用户参数(假设这是在<form>中完成)并将其定位到IFRAME。 e.g。

 <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的字符数据(很可能是一个难以看到的换行符和/或尾随空格)

答案 1 :(得分:0)

我从Implementing a simple file download servlet

实施了@ wen的答案

此外,我使用@ How to deny web access to a Tomcat directory

中的@Ramesh PVK建议删除了保存文件的目录的直接网络访问权限
<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>