下载图像时出现 CORS 问题

Posted

技术标签:

【中文标题】下载图像时出现 CORS 问题【英文标题】:CORS issue while downloading Image 【发布时间】:2017-08-12 23:40:19 【问题描述】:

我有一个 API 可以将 base64 字符串转换为图像并将图像写入 Tomcat 服务器。调用 API 后图像写入成功,但在检索相同图像时出现错误如下:

“请求中没有“Access-Control-Allow-Origin”标头 资源。因此不允许 Origin 访问。 XMLHttpRequest 无法加载 http://hostname:4444//tmpFiles/31487660124865.jpg。不 'Access-Control-Allow-Origin' 标头出现在请求的 资源。

我的代码如下:

public Message uploadImage(Map<String, String> map) 

    // Initializing the message
    Message message = new Message();

    try 

        // Get the file data
        String fileData = map.get("file_data");

        // Split the data with the comma
        String base64Image = fileData.split(",")[1];

        // Convert the base64 input to binary
        byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(base64Image);

        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));

        // Manipulations in File Name
        String fileName = map.get("file_name");
        String file = fileName.substring(0, fileName.indexOf("."));
        String fileExtension = fileName.substring(fileName.indexOf("."));

        // Get the current time
        Long time = new Date().getTime();

        // Write the file name with the current time to avoid redundancy
        String maniputedFileName = file + "" + time + fileExtension;
        System.out.println("manipulated file name is " + maniputedFileName);

        // Check if file name is not empty
        if (!maniputedFileName.isEmpty()) 

            // Get the root path of tomcat server
            String rootPath = System.getProperty("catalina.home");

            System.out.println("root Path:- " + rootPath);

            // File Directory/Path on tomcat server
            File fileDirectory = new File(rootPath + File.separator + "webapps/tmpFiles");

            // If file direcory does not exist
            if (!fileDirectory.exists())
                fileDirectory.mkdirs();

            File outputfile = new File(fileDirectory.getAbsolutePath() + File.separator + maniputedFileName);

            // Write created image on server
            ImageIO.write(image, "png", outputfile);

            // Set the success message
            message.setDescription("You successfully uploaded file=" + maniputedFileName);
            message.setObject(outputfile.getAbsolutePath());
            message.setValid(true);
            return message;

        
        // Set the failure message
        else 
            message.setDescription("You failed to upload " + maniputedFileName + " because the file was empty.");
            message.setValid(false);
            return message;
        
    
    // Handling all exceptions
    catch (IOException e) 
        message.setDescription(e.getMessage());
        message.setValid(false);
        return message;
    

而 web.xml 是:

     <filter>
        <filter-name>tokenfilter</filter-name>
        <filter-class>com.springiot.filter.TokenFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>tokenfilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
    <filter-name>SimpleCORSFilter</filter-name>
    <filter-class>com.springiot.filter.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SimpleCORSFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

我的 tokenFilter 类是:

 HttpServletResponse response = (HttpServletResponse) res;

    response.addHeader("Access-Control-Allow-Origin", "*");
    response.addHeader("Access-Control-Allow-Methods", "POST, GET,OPTIONS, DELETE");
    response.addHeader("Access-Control-Max-Age", "3600");
    response.addHeader("Access-Control-Allow-Headers",
            "Content-Type, Access-Control-Allow-Headers, Authorization,X-Requested-With,token,userKey,user_id");

【问题讨论】:

你试过在 chrom 中插入chrome.google.com/webstore/detail/allow-control-allow-origi/… 吗? 感谢您的建议,我已更正。 不想使用 chrome 插件,因为使用应用程序的用户不会添加 chrome 插件对吗? 将 addHeader("Access-Control-Allow-Origin", "") 添加到您的请求中(request.addHeader("Access-Control-Allow-Origin", " i>") 或将您的图像存储在网络应用根文件夹/子文件夹中; 顺便说一句,您可能应该从您的问题中删除整个public Message uploadImage 代码 sn-p。因为它与您在问题中描述的问题无关。所以这只是分散注意力。您在问题中说图像上传按预期工作。如果是这样,那么该代码就没有问题,没有人需要看到该代码来帮助您解决问题 【参考方案1】:

如果创建XMLHttpRequest 会导致问题,请不要使用它,而是考虑将数据(使用HttpURLConnection)提取到本地字节数组中。现在解码(显示)从局部变量(例如:字节数组)加载的图像以避免 CORS。

我也习惯了这样的网址:http://host:port/address/,但你的网址是http://:port//,所以我不明白你如何只使用端口和没有服务器来访问网络(http)服务器 地址。这应该会导致 URL 错误,但您必须以某种方式到达文件目的地,因为 CORS 恰好保护了媒体...

以下代码可能值得在空白/新测试项目中尝试:

(PS:没有提供像http://server:port/tmpFiles/image.jpg这样的可测试链接,所以使用如图)

Image image = null;

try 

    URL url = new URL("http://:4444//tmpFiles/31487660124865.jpg");
    image = ImageIO.read(url);
 
catch (IOException e)  e.printStackTrace(); 

JFrame frame = new JFrame("*** test");
JLabel label = new JLabel(new ImageIcon(image));
frame.setSize(500, 500); 
frame.add(label); frame.setVisible(true);

以及相关的进口:

import javax.swing.ImageIcon;
import javax.swing.JFrame;          import javax.swing.JLabel;
import java.awt.Image;              import javax.imageio.ImageIO;
import java.net.HttpURLConnection;  import java.net.URL;

【讨论】:

【参考方案2】:

您需要在CATALINA_HOME/conf 中添加web.xml 中的过滤器,并使用正确的路径名或只是/*。添加如下过滤器

  ...

 <filter>
   <filter-name>CorsFilter</filter-name>
   <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
 </filter>
 <filter-mapping>
   <filter-name>CorsFilter</filter-name>
   <url-pattern>/*</url-pattern>
 </filter-mapping>

...

更多信息请查看this官方文档

【讨论】:

【参考方案3】:

CORS 问题?使用代理并遵守规则。通过更改标题,您正在删除为避免特定类型的攻击而设置的安全性。如果您正在做任何需要安全的事情,那是个坏主意。

在代理中,您可以拦截请求并更改您需要的标头中的任何内容,并在需要时重写响应标头,而不会产生风险。

从您的错误消息“http://:4444//tmpFiles/31487660124865.jpg”来看,网址显然有问题。请发布请求的代码。

@SkyWalker 的回答是正确的。我怀疑一旦您向我们提供其余代码,很明显域或协议和域正在发生变化。如果是这种情况并且您不想让自己容易受到攻击,只需通过代理运行它,终止代理上的有效 ssl 证书。 (并不意味着您不应该保护到上游的流量)

nginx 非常适合这类任务。但是选择你的代理..那里有很多代理。

【讨论】:

这是我的错误,有一个编辑“http://:4444//tmpFiles/31487660124865.jpg”。你需要什么代码,我上传。【参考方案4】:

如果您可以访问 tomcat 服务器中的管道,您可以尝试以 HTTPS 方式提供 API,那么 CORS 就不会发生。

您可以在我不推荐的 tomcat 服务器中禁用 cors

【讨论】:

【参考方案5】:

有一些规则需要遵守:

    如果您向其他域发出请求 XMLHttpRequest,则会出现此问题。 浏览器始终允许同源,而不是其他安全策略。如果浏览器发现任何请求不同,那么它会阻止你。

这个问题[How to use a CORS proxy to get around “No Access-Control-Allow-Origin header”问题]在这里得到解答:https://***.com/a/43881141/2293534

CORS 安全性 - 通用允许

    将“Access-Control-Allow-Origin”标头设置为 * 有效地将内容变成公共资源,允许从任何域访问。

场景:

    攻击者可以通过诱使用户访问攻击者控制的站点来从已将此标头设置为 * 的 Intranet 站点窃取数据 互联网。 当受害者导航到攻击者控制的站点时,攻击者可以通过受害者的浏览器对其他远程应用程序进行攻击。

我在这里给出了答案:Is this CORS handler safe? 你可以在这里查看 CORS。它会澄清你的更多。

资源链接:

    Cross-Origin XMLHttpRequest Why does my javascript get a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error when Postman does not?

【讨论】:

我看了你的回答,但那不起作用,我已经在我的问题中提到过。

以上是关于下载图像时出现 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

仅在 iOS 移动 Safari 中上传图像时出现错误的 CORS 失败

尝试在已部署的反应客户端和快速服务器上上传图像文件时出现 503 错误,然后是 CORS 错误

为啥使用 AWS CloudFront 时出现 CORS 客户端错误?

使用 POST API 时出现多个 CORS 错误

下载大量图像时出现内存泄漏问题

在Azure CDN中提供托管字体时出现CORS错误