问题是关于tomcat的安全性,但首先考虑以下示例:
假设你有apache web服务器。然后,在www文件夹下,创建名为dist的文件夹,并在文件夹dist下创建名为bdf23b1c-ddd3-4d5b-8fdf-948693674011
的文件夹。在此文件夹下创建一些包含安全信息的文件:
www/dist/bdf23b1c-ddd3-4d5b-8fdf-948693674011/pic.png
这显然是个坏主意,因为任何用户都可以转到yoursite.com/dist
并查看此文件夹中包含的所有内容。
另一方面,假设情况相同,但在tomcat web应用程序中创建了文件夹dist。如果您的web.xml中包含以下内容:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/dist/*</url-pattern>some java tool from outside
</servlet-mapping>
然后你可以使用它的URL安全地下载pic.png。如果你去yoursite.com/dist,那么默认情况下tomcat不会显示你这个文件夹的内容。
但我的问题是:它是如何安全的?也许你可以使用服务器外部的一些java工具连接到tomcat并以某种方式确定你宝贵数据的完整路径?我知道java中的安全性,它将是最终的解决方案,但我不想在这里进行任何基于密码的身份验证。
UPD#1:如果存在某些此类漏洞(与外部或其他任何Java工具连接),请在此处发布。假设使用我们的应用程序替换ROOT应用程序的默认tomcat安装。也许对server.xml进行一些调整以禁止“恶意java工具”的不需要的连接?
顺便说一句,我已经设置了防火墙,拒绝除http,https和ssh之外的所有网站流量。
UPD#2:正如我在评论中提到的,我想为Dropbox功能创建最便宜的替代方案。我不想使用密码,因为它对我们的客户来说很不方便(我们希望为客户提供游戏的预发布访问权限)
答案 0 :(得分:3)
您正在做的是&#34; security through obscurity&#34;。
但实际上它会“工作”#34;只有知道该URL的人才能下载该文件,只要您确保目录列表一直被拒绝,并且该文件的链接不存在于Google等网络浏览器可以获取的位置。并且没有人会扫描与您的gf共享链接的媒体。
这绝对不是完全安全的,取决于你想要分享的数据类型,我会选择不同的解决方案......
答案 1 :(得分:3)
首先,您可以将Apache配置为不显示目录内容(我很惊讶它显然(显然)),因此这里不需要Tomcat。 / p>
至于从外面连接到Tomcat,你不会允许那是你吗?当你去上班时,你不会把你的前门解锁。
最后,用户必须猜测路径(并且足够关心那里的内容),所以它不太可能泄漏(除非你必须小心关于像Marged指出的网络玩家一样。)
但是,您可以在Apache中配置基本身份验证,而不是依赖于长时间的神秘路径。这样你就不用担心Tomcat或Java了。
答案 2 :(得分:2)
使用servlet本身不会生成任何内容secure。您不需要Java工具来连接,您甚至可以使用Telnet,任何脚本语言或创建自己的套接字。只需使用某个地方的下载servlet,至少Basic authentication(&#34;信息隐藏&#34;没有安全方面;)。
&#34;我想为Dropbox功能创建最便宜的替代方案......&#34;
然后使用WebDav。 Apache WebServer已经准备好共享和保护数据的模块。我想没有类似DropBox的客户端,但是你可以让你的客户端连接到共享文件夹或其他东西。
答案 3 :(得分:1)
我喜欢Stefan Lindenberg关于WebDav用法的评论,我一定会仔细研究它。但我无法抗拒重新发明轮子,所以我设法创建了这个简单的Java解决方案,这为我的安全性增加了更多的默默无闻。 :)对于这一小段代码的任何评论和批评,我将不胜感激。
package com.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author Anton P. Kolosov
*/
public class ObscureSecureServlet extends HttpServlet {
private static final Pattern UUID_PATTERN = Pattern.compile("^[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", Pattern.CASE_INSENSITIVE);
private String basePath;
/**
* Initialization routines
* @param config Servlet configuration
* @throws ServletException
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
basePath = config.getInitParameter("basePath");
}
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String res = request.getParameter("res");
String name = request.getParameter("name");
Matcher matcher = UUID_PATTERN.matcher(res);
if (matcher.matches()) {
// Only UUIDs are allowed for res parameter
File file = new File(basePath + "/" + res, name);
if (file.exists()) {
sendFile(file, request, response);
return;
}
}
// Can redirect to jsp if you wish...
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>File not found</title>");
out.println("</head>");
out.println("<body>");
out.println("File for res = " + res + " and name = " + name + " was not found!");
out.println("</body>");
out.println("</html>");
}
}
private void sendFile(File file, HttpServletRequest request, HttpServletResponse response) throws IOException {
long fileSize = file.length();
response.setHeader("Content-length", Long.toString(fileSize));
response.setContentType("application/octet-stream");
response.setHeader( "Content-Disposition", "filename=\"" + file.getName() + "\"" );
ServletOutputStream out = response.getOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
write(file, bufferedOutputStream);
bufferedOutputStream.flush();
}
/**
* Writes a document to the passed stream.
* @param bufferedOutput The method writes name to this output stream
* @throws IOException IOException
*/
public void write(File file, BufferedOutputStream bufferedOutput) throws IOException {
byte buffer[] = new byte[1024 * 4];
BufferedInputStream bufferedInput = null;
try {
FileInputStream inputStream = new FileInputStream(file);
bufferedInput = new BufferedInputStream(inputStream);
int lengthRead = 0;
int offset = 0;
while (true) {
lengthRead = bufferedInput.read(buffer, 0, buffer.length);
if (lengthRead == -1) {
break;
}
bufferedOutput.write(buffer, 0, lengthRead);
offset += lengthRead;
}
} finally {
if (bufferedInput != null) {
bufferedInput.close();
}
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Servlet for 'obscure secure' file retrieving";
}// </editor-fold>
}
答案 4 :(得分:0)
通过考虑你能想象到的东西,安全无效,这完全取决于攻击者可以想象的内容。攻击你的计划的一些方法:
https://
),所有数据都将通过互联网发送,服务器和浏览器之间的任何人都可以看到您正在做的事情(并保存图像副本) )。国家安全局就是这么做的。这些只是我自己帽子里的想法。在2015年,通过自己考虑或“聪明”的安全性不再起作用。如果你关心安全问题,你必须投入大量的时间和金钱才能实现安全。