读取 Tomcat 目录外的文件

Read files outside Tomcat's directory

在 Linux 服务器中,我的 java 应用安装在:

/opt/apache-tomcat8/webapps/myApp/

在以前的目录下,我可以很容易地 read/write 文件,但是我需要检查一些位于完全不同的目录中的图像是否存在:

/home/mywebsite/public_html/image/catalog/mainImages/

我没能做到。我什至尝试为 mainImages 文件夹授予 777 权限,但 Tomcat 它仍然无法从该目录读取。

我认为我的 java 代码与此无关,但以防万一(我删除了不必要的额外代码):

            filePath = prefix + listImagesArr[i][1];
            File f = new File(filePath);
            if(f.exists()){
                System.out.println("Directory exists!!");
                if (f.isFile()) {
                    //do nothing
                    System.out.println("File exists");
                } else {
                    System.out.println("File doesn't exist");
                }
            } else {
                System.out.println("Directory doesn't exist");
            }

我总是得到“目录不存在”,但相信我,目录就在那里。

这与linuxusers/groups有关吗?

任何帮助将不胜感激!!

更新!!

经过一些研究,我被困在这里。

我找到了检查 user/folder.

权限的方法

此路径的所有文件夹都有一个名为“itlogiccom”的用户和所有者 linux Tomcat 的用户名为“tomcat8

我已将 tomcat8 添加到 itlogiccom 组:

lid -g itlogiccom
itlogiccom(uid=512)
tomcat8(uid=490)

所以现在,tomcat8 应该能够读取 itlogiccom 是所有者的目录和文件,并且具有必要的权限。

使用 sudotest 我可以检查用户 tomcat8 是否能够读取从指定的目录。当读取成功时,输出为“0”,否则为任何其他数字。在接下来的代码中,您将看到前 4 种情况是成功的,但是,当我尝试从 home 目录读取时,读取不成功(输出为 1):

[/home/mywebsite/public_html/image/catalog]# sudo -u tomcat8 test -r ./mainImages/ZKTN3S.jpg; echo $?
0
[/home/mywebsite/public_html/image]# sudo -u tomcat8 test -r ./catalog/mainImages/ZKTN3S.jpg; echo $?
0
[/home/mywebsite/public_html]# sudo -u tomcat8 test -r ./image/catalog/mainImages/ZKTN3S.jpg; echo $?
0
[/home/mywebsite]# sudo -u tomcat8 test -r ./public_html/image/catalog/mainImages/ZKTN3S.jpg; echo $?
0
[/home]# sudo -u tomcat8 test -r ./mywebsite/public_html/image/catalog/mainImages/ZKTN3S.jpg; echo $?
1

mywebsite 和 public_html 具有相同的 group/owner 和相同的权限:

drwxr-xr-x+ 40 itlogiccom itlogiccom 4096 Feb  5 14:21 mywebsite/
drwxr-xr-x+ 12 itlogiccom itlogiccom 4096 Feb  5 16:13 public_html/

所以这就是为什么我只是不明白为什么我无法从“主”目录读取。

顺便说一句,如果我执行相同的测试,使用“itlogiccom”用户代替,读取成功:

[/home]# sudo -u itlogiccom test -r ./mywebsite/public_html/image/catalog/mainImages/ZKTN3S.jpg; echo $?
0

我不明白为什么会出现这种情况。我只需要用户“tomcat8”可以从这个路径读取文件:

/home/mywebsite/public_html/image/catalog/mainImages/

任何帮助将不胜感激!!

为了清楚起见,如果我尝试阅读:

/home/mywebsite/(以及此路径下的每个文件夹),读取成功。

但是当我读到:

/home/

读取不成功

2 你可以在这里做的事情首先验证权限它必须像 rwrwrw 并通过提供完整路径进行测试。我发现你正在使用 mac 系统。要获取完整路径,请复制文件夹并粘贴到终端中。您将看到文件夹的完整路径。并使用该路径。

嘿兄弟,

我不熟悉 tomcat standalone 因为我只开发 SpringBoot 应用程序,但几天前我遇到了和你一样的问题。

  1. 开始时出现权限错误,最重要的是您拥有.jar所在的文件夹运行ning运行 拥有目录的用户的 .jar。或者你只是使用 sudo 或以 root 身份执行,这绝对有效。

  2. 下一步是向 Java 应用宣布您的外部目录。你可以这样做:

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    @PropertySource({ "classpath:server.properties" })
    public class WebConfig implements WebMvcConfigurer {
    
        @Value("${server.home}")
        private String serverHome;
    
        @Value("${server.images}")
        private String serverImages;
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
            String file = "file:";
    
            // Add custom locations from server outside of .jar file.
            registry.addResourceHandler("/resources/**").addResourceLocations(file + 
                this.serverHome).setCachePeriod(0);
            registry.addResourceHandler("/server-images/**").addResourceLocations(file 
                + this.serverImages).setCachePeriod(0);
         }
    
    }
    
  • 我添加了两个资源位置:

    • "/resources/**" inside.jar
    • "/server-images/**" 外部 服务器上的 .jar
  • 您可能想知道这些@Value(...) 字符串,它们是:

     server.home = /home/neo/foodguy/
     server.images = /home/neo/foodguy/images/
    
    • "neo" 替换为您的用户
    • /home/neo/foodguy/
    • 上创建文件夹 "images"

如您所见,服务器上的文件夹名称与资源处理程序的名称不同。如果您愿意,可以将它们设置为相等。这一行 String file = "file:"; 非常重要,没有它代码将无法运行。

  1. 如果您启用了安全 foo,您必须允许每个请求,如果它是为了公开。我使用 Keycloak 作为基于角色的用户管理软件。也许它在你的机器上有点不同,因为你可能不使用 Keycloak,但你肯定有一个安全配置 class,你可以在其中允许和拒绝 URL。我这样做了:

       @Override
       protected void configure(HttpSecurity http) throws Exception {
    
           super.configure(http);
    
           !! http.authorizeRequests().antMatchers("/server-images/**").permitAll(); !!
    
           http.authorizeRequests().antMatchers("/welcome-page").permitAll();
           http.authorizeRequests().antMatchers("/memberarea/**").hasRole("member");
           http.authorizeRequests().antMatchers("/adminarea/**").hasRole("admin");
           ...........
        }
    
  2. 您现在可以在前端执行此操作:

        <img src="/server-images/event.webp" class="..." alt="...">
    
  • 图像将通过您之前创建的资源处理程序 "/server-images/**""/home/neo/foodguy/images/event.webp" 加载。

至少一个糖果:我的客户想要为圣诞节、万圣节等假期上传传单,我需要管理我的客户的用户上传。我在后台建立了一个上传表单:

<!--/* th:action adds automatically csrf token */-->
<form method="POST" enctype="multipart/form-data" th:action="@{/login/admin/upload}" class="py-3 mt-4">

    <!--/* Form heading */-->
    <div class="row mb-1">
        <div class="col text-left">
            <h3 class="d-inline font-weight-bold" th:text="#{admin.eventflyer.title}"> 
            </h3>
        </div>
    </div>

    <!-- /* Upload form */ -->
    <div class="form-group">
        <input type="file" name="file" class="form-control-file" id="fileInputEventFlyer">
        <input type="submit" value="Upload" class="btn btn-grow bg-color-green text-white">
    </div>
</form>

注意 "multipart" 数据类型。在后端,我这样做是为了处理上传:

@Controller
@PropertySource({ "classpath:server.properties" })
public class MemberController {

    @Value( "${server.images}" )
    private String serverImages;

    @PostMapping("/login/admin/upload")
    @PreAuthorize(Roles.HAS_ADMIN)
    public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
        
        File pathToEventFlyerWEBP = new File(this.serverImages + "event.webp");
        File pathToEventFlyerPNG = new File(this.serverImages + "event.png");
        
        try {
            file.transferTo(pathToEventFlyerWEBP);
            file.transferTo(pathToEventFlyerPNG);
        } catch (IOException | IllegalStateException exc) {
            Logbot.exception(this.getClass(), new Throwable(), exc);
        }
            
        return "redirect:/login";
    }
}    

希望这能帮助您管理服务器上 Java.jar 之外的上传和下载。

如果您还有其他问题,请随时与我联系。


亲切的问候
凯文

编辑

尝试在 public_html 文件夹上递归设置权限,让自己能够访问该文件夹及其包含的所有文件夹。

 chmod -R 755 /home/mywebsite

chmod 将权限设置为所有者写入、组读取和执行、全部读取和执行。

如果您不想使用 -R(因为您不想共享目录中的其他内容),那么请在图像完整路径中的每个单独目录上执行此命令。

即使此处的许多评论都非常有帮助,但本例中的主要问题与某些 ACL(访问控制列表)有关,这些 ACL 阻止用户“tomcat8”读取我试图读取的目录.

这些规则已被删除,所以现在一切正常。