为 JSP/Tomcat/Windows 设置目录权限

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3425591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:59:31  来源:igfitidea点击:

Setting directory permissions for JSP/Tomcat/Windows

javawindowsjsptomcatpermissions

提问by BridgetG

I have a web app consisting of some JSPs that were previously running on a Linux box. I need to get this running on a Windows XP SP3 machine running Tomcat 5.5.29. Most everything is working now but this one item: The app has a capability to write a configuration file to its Windows directory (i.e. C:\Program Files\Apache\Tomcat\webapps\myapp). But when it tries to do this, the app cannot open the FileOutputStream (returns null). If I drop off the path specifier, and just let it open the file, it successfully opens it in the Tomcat directory.

我有一个 Web 应用程序,其中包含一些以前在 Linux 机器上运行的 JSP。我需要让它在运行 Tomcat 5.5.29 的 Windows XP SP3 机器上运行。现在大多数东西都在工作,但有一项:该应用程序能够将配置文件写入其 Windows 目录(即 C:\Program Files\Apache\Tomcat\webapps\myapp)。但是当它尝试执行此操作时,应用程序无法打开 FileOutputStream(返回 null)。如果我去掉路径说明符,并让它打开文件,它会成功地在 Tomcat 目录中打开它。

The first line fails, but the second one succeeds:

第一行失败,但第二行成功:

//  outputFile2 = new PrintWriter(new FileOutputStream(basePathName + "programAll.txt", false));
    outputFile2 = new PrintWriter(new FileOutputStream("programAll.txt", false));

Here is the code that creates the basePathName:

这是创建 basePathName 的代码:

    String basePathName = getBaseFilePath();  
    ...
    public String getBaseFilePath()
            {
            String curDir = System.getProperty("catalina.home");  
            curDir = curDir + "/webapps/pubmed/"; 
            curDir = "file:///" + formatPathNameForOS(curDir);
            return curDir;
            }

   public String formatPathNameForOS(String pathName)
        {
        if (codeIsOnWindows())
            {
            pathName = pathName.replace('/','\');
            }
        else
            {
            pathName = pathName.replace('\','/');
            }
        return pathName;
    }

Here's the exception message:

这是异常消息:

HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:460)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
root cause

java.lang.NullPointerException
    org.apache.jsp.updateMemberLists_jsp._jspService(updateMemberLists_jsp.java:1492)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

Here's the stack trace:

这是堆栈跟踪:

Aug 6, 2010 1:20:39 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.NullPointerException
    at org.apache.jsp.updateMemberLists_jsp._jspService(updateMemberLists_jsp.java:1492)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
    at org.globus.tomcat.coyote.valves.HTTPSValve55.invoke(HTTPSValve55.java:45)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:873)
    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
    at java.lang.Thread.run(Thread.java:595)

I've looked at the updateMembersLists_jsp.java, and here is the section where the null pointer is occurring:

我查看了 updateMembersLists_jsp.java,这里是出现空指针的部分:

//create a file to write to the output
PrintWriter outputFile2 = null;
try
    {
    outputFile2 = new PrintWriter(new FileOutputStream(basePathName + "programAll.txt", false));
//  outputFile2 = new PrintWriter(new FileOutputStream("programAll.txt", false));
    }
    catch (FileNotFoundException e)
        {
        out.write("<p><font color='red'>Error Saving</font></p>");
        }
outputFile2.print(output);  // THIS IS LINE 1492 -- NULL POINTER
outputFile2.close();

Also: We are now running Tomcat off of the root directory instead of Program Files. I have checked the basePathName and it is being calculated correctly.

另外:我们现在从根目录而不是 Program Files 运行 Tomcat。我已经检查了 basePathName 并且它正在正确计算。

Now I figured out that Tomcat's policy settings might need to be adjusted. I added the following lines to catalina.policy hoping it would set things right:

现在我发现可能需要调整 Tomcat 的策略设置。我在 catalina.policy 中添加了以下几行,希望它能把事情做好:

// The permissions granted to the pubmed webapp
grant codeBase "file:${catalina.home}/webapps/pubmed/-" {
        permission java.io.FilePermission "${catalina.home}/webapps/pubmed/-", "read, write";
        permission java.io.FilePermission "${catalina.home}/webapps/pubmed/*", "read, write";
};

This didn't seem to have any effect. The Windows user that tomcat is running under has read/write permissions on the pubmed directory. Aside from the fact that it seems questionable for this webapp to be writing files to its own directory, what am I missing?

这似乎没有任何影响。运行 tomcat 的 Windows 用户对 pubmed 目录具有读/写权限。除了这个 webapp 将文件写入自己的目录似乎有问题之外,我还缺少什么?

Sean

肖恩

采纳答案by naikus

Try obtaining the path in the following way:

尝试通过以下方式获取路径:

String path = getServletContext().getRealPath("/");

This will convert your path (to your webapp) to the actual path on your disk.

这会将您的路径(到您的 web 应用程序)转换为磁盘上的实际路径。

回答by BalusC

You should not use relative paths in Java IO. The path would become relative to the current working directorywhich depends on how you started the webserver/webapplication. When Tomcat is started in Eclipse for example, it may be the Eclipse project directory. When Tomcat is started from CMD, it may be the currently opened folder in CMD. When Tomcat is started as service, it may be /binfolder of Tomcat. To determine it yourself, do as follows:

您不应在 Java IO 中使用相对路径。该路径将成为相对于当前工作目录的路径,这取决于您如何启动网络服务器/网络应用程序。例如在Eclipse 中启动Tomcat 时,它可能是Eclipse 项目目录。从CMD启动Tomcat时,可​​能是CMD中当前打开的文件夹。当Tomcat作为服务启动时,它可能是/binTomcat的文件夹。要自己确定,请执行以下操作:

System.out.println(new File("programAll.txt").getAbsolutePath()); 

And you'll see that it's completely different than you'd expect.

您会发现它与您预期的完全不同。

You need to specify absolutepaths instead. You can use ServletContext#getRealPath()to convert a webcontent-relative path to an absolute disk file system path.

您需要指定绝对路径。您可以使用ServletContext#getRealPath()将 webcontent-relative 路径转换为绝对磁盘文件系统路径。

String relativeWebPath = "programAll.txt";
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath);
output = new FileOutputStream(absoluteDiskPath);
// ...

The getServletContext()method is available inside every servlet.

getServletContext()方法在每个 servlet 中都可用。



That said, did you take into consideration that all modified files in the webcontent will be wiped/overriden whenever you redeploy/restart the webapp/server? If you'd like to have a bit more permanent storage, I strongly recommend to store them outsidethe webcontent (of course in an absolute path, e.g. /var/webapp/filesor so).

也就是说,您是否考虑过在您重新部署/重新启动 web 应用程序/服务器时将擦除/覆盖 web 内容中所有修改过的文件?如果您想要更多的永久存储空间,我强烈建议将它们存储在 webcontent之外(当然在绝对路径中,例如/var/webapp/files左右)。