上传时发送文件至TOMCAT出现UniformInterfaceException

1. 出错的信息描述

HTTP Status 500 – Internal Server Errorhtml

MESSAGE :
Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:9090/uploads/91e5118e60924b21bd48a9ed19ab91ff_girl8.jpg returned a response status of 405 Method Not Allowedjava

Description :
The server encountered an unexpected condition that prevented it from fulfilling the request.web

Exception :spring

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:9090/uploads/91e5118e60924b21bd48a9ed19ab91ff\_girl8.jpg returned a response status of 405 Method Not Allowed
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:986)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

2. 出错的Project描述

使用的IDE: IDEA 2019-02
充当上传文件的Project hierarchy(Client):
image.pngapache

接收文件的Project hierarchy(Server):
image.pngapi

3. springmvc fileupload源码

controllertomcat

/**
     * 跨服务器文件上传
     * @return success
     */
    @RequestMapping("/fileupload3")
    public String fileupload3(MultipartFile upload) throws Exception {
        System.out.println("service id doing...");

        // 定义上传文件服务器路径
        String path = "http://localhost:9090/uploads/";

        // 说明上传文件项
        // 获取上传文件的名称
        String filename = upload.getOriginalFilename();
        // 把文件的名称设置惟一值,uuid
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;

        // 建立客户端的对象
        Client client = Client.create();

        // 和图片服务器进行链接
        WebResource webResource = client.resource(path+filename);

        // 上传文件
        webResource.put(upload.getBytes());

        return "success";
    }

index.jsp安全

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
    <form action="user/fileupload1" method="post" enctype="multipart/form-data">
        传统方式的文件上传:<input type="file" name="upload">
        <br>
        <input type="submit" value="上载">
    </form>

<hr>
    <form action="user/fileupload2" method="post" enctype="multipart/form-data">
        SpringMVC方式的文件上传:<input type="file" name="upload">
        <br>
        <input type="submit" value="上载">
    </form>

<hr>

    <form action="user/fileupload3" method="post" enctype="multipart/form-data">
        跨服务器的文件上传:<input type="file" name="upload">
        <br>
        <input type="submit" value="上载">
    </form>
</body>
</html>

4. 出错分析

"1.出错的信息描述" 能够知道咱们的错误在于PUT请求被用于接收文件的TOMCAT拒绝了。服务器

请查看Apache Tomcat 9 (9.0.30) - Default Servlet Reference。咱们须要注意到如下信息:websocket

4.1 webapp启动后default servlet会加载

So by default, the default servlet is loaded at webapp startup and directory listings are disabled and debugging is turned off.

4.2 DefaultServlet的initParameters中readonly默认为true

如下为readonly property的描述

Is this context "read only", so HTTP commands like PUT and DELETE are rejected? [true]

这意味着接收文件的TOMCAT默认加载DefaultServlet后,默认拒绝接收PUT和DELETE请求。所以咱们须要改变initParameters中的readonly = false

关于为何readonly默认为true这一点,你能够先看看TOMCAT对于把readonly设置为false持有什么样的见解,如下为参考连接:
Apache Tomcat RCE if readonly set to false (CVE-2017-12617) - Alphabot Security

The Apache Tomcat team announced today that all Tomcat versions before 9.0.1 (Beta), 8.5.23, 8.0.47 and 7.0.82 contain a potentially dangerous remote code execution (RCE) vulnerability on all operating systems if the default servlet is configuredwith the parameter readonly set to false or the WebDAV servlet is enabled with the parameter readonly set to false. This configuration would allow any unauthenticated user to upload files (as used in WebDAV). It was discovered that the filter that prevents the uploading of JavaServer Pages (.jsp) can be circumvented. So JSPs can be uploaded, which then can be executed on the server.

Now since this feature is typically not wanted, most publicly exposed system won’t have readonly set to false.

不难推断出TOMCAT考虑到安全性,默认关闭了TOMCAT的PUT和DELETE请求(即readonly = true)。

5. 解决方法

根据 "4.出错分析" 能够知道咱们须要修改web.xml文件的readonly参数。
咱们须要在DefaultServlet的init-param中添加readonly为false(若是你的配置文件没有readonly,那么你须要手动添加readonly=false)

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>readonly</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

启动两个TOMCAT,如今展现效果

index.jsp(Client端):
image.png

image.png

image.png

相关文章
相关标签/搜索