10

I have an API which converts base64 string to image and write the image in Tomcat Server.The image writes successfully after calling API but gives the error while retrieving the same image follows:

"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin is therefore not allowed access. XMLHttpRequest cannot load http://hostname:4444//tmpFiles/31487660124865.jpg. No 'Access-Control-Allow-Origin' header is present on the requested resource.

My code is as follows:

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;
    }
}

And web.xml is:

     <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>

And my tokenFilter Class is :

 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");
Tanvi Garg
  • 308
  • 5
  • 18
  • have you tried by pulged in https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi in chrom ? – Sangram Badi Mar 21 '17 at 10:55
  • Thanks for the suggestion,i made correction. – Tanvi Garg Mar 21 '17 at 10:56
  • Don't want to use chrome plugin because ever user who is using application will not add the chrome plugin Right ? – Tanvi Garg Mar 21 '17 at 10:56
  • Add addHeader("Access-Control-Allow-Origin", "*") to your request as well (request.addHeader("Access-Control-Allow-Origin", "*") or store your image in the web app root folder/subfolder; – dsp_user Mar 21 '17 at 11:04
  • Already did the same. – Tanvi Garg Mar 21 '17 at 11:10
  • No, don’t do `request.addHeader("Access-Control-Allow-Origin", "") `. The `Access-Control-Allow-Origin` header is strictly a response header that only needs to be sent by the server. There’s zero purpose for having your client code send it as a request header – sideshowbarker Mar 21 '17 at 14:09
  • How can i add response header which needs to be sent by the server. @sideshowbarker – Tanvi Garg Mar 22 '17 at 05:58
  • @TanviGarg it looks to me like you already have your server properly configured for sending the right CORS response headers. Apparently it’s not working for some reason. I don’t know why. Maybe you need to restart the server, or check the server logs to see if it’s failing to find some necessary jar file, or something. – sideshowbarker Mar 22 '17 at 06:08
  • 1
    By the way, you should probably remove the entire `public Message uploadImage` code snippet from your question. Because it’s irrelevant to the problem you describe in the question. So it’s just distracting. You say in the question that the image upload is working as expected. If that’s the case, then there’s no problem with that code, and nobody needs to see that code in order to help you solve your problem – sideshowbarker Mar 22 '17 at 06:10
  • Restarted server 'n' number of times,but can'y find any solution – Tanvi Garg Mar 22 '17 at 06:12
  • Post the entire code of the TokenFilter and also do you have any other filters, if so post the order in which all your filters are configured/invoked. – msmani Oct 06 '17 at 11:42
  • "http://:4444//tmpFiles/31487660124865.jpg"..have you removed the host name here or its an issue ? – Shailendra Oct 06 '17 at 18:00
  • Also double slash may cause issie with proper mapping the request `http://:4444*//*tmpFiles/31487660124865.jpg` – Aleh Maksimovich Oct 07 '17 at 15:27
  • Hi, can you please add the Response header and the Request Header? – code4fun Oct 10 '17 at 09:41
  • Did you already had a look at: https://stackoverflow.com/questions/16296145/set-cors-header-in-tomcat ? – code4fun Oct 10 '17 at 09:44
  • Already seen that one. – Tanvi Garg Oct 10 '17 at 10:32
  • Is you client code and server code in same EAR? Can you please share the client code which is calling API to fetch an image – Amit K Bist Oct 10 '17 at 18:09
  • _"The image writes successfully... but gives the error while retrieving the same image"_ Show example of a testable link to such a PNG file. You just want to display it inside Java app using `Image` class, right? Is there an actual server involved or only just a port number (4444)? – VC.One Oct 13 '17 at 15:38
  • There's actually a server which is apache tomcat involved. – Tanvi Garg Oct 14 '17 at 07:38
  • @TanviGarg please use `@` symbol to notify someone. Only here cos I just remembered this question right now. Did you try my code with your url?... : `URL url = new URL("http://hostname:4444//tmpFiles/filename.jpg");`. Also since the uploading is fine why show us function `uploadImage` since nothing to fix there, right? The problem is with code in your unseen function `getImage`... For example why make an XMLHttpRequest for an image when all you need is to retrieve bytes from URL? Even better why not just load the damn URL as standard image path (example in my answer)? – VC.One Oct 14 '17 at 22:13

5 Answers5

1

You need to add the filter in web.xml in CATALINA_HOME/conf with proper path name or just /*. Add filter like below

  ...

 <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>

...

For more info check this official document

Shettyh
  • 1,188
  • 14
  • 27
0

There are some rules to follow:

  1. If you make a request XMLHttpRequest to a different domain, then this issue will arise.
  2. Browser always allows same origin, not others for security policy. If browser finds any request to different, then it will block you.

This question [How to use a CORS proxy to get around “No Access-Control-Allow-Origin header” problems] is answered here: https://stackoverflow.com/a/43881141/2293534

CORS Security - Universal Allow

  1. Setting the 'Access-Control-Allow-Origin' header to *
  2. Effectively turns the content into a public resource, allowing access from any domain.

Scenarios:

  1. An attacker can steal data from an intranet site that has set this header to * by enticing a user to visit an attacker controlled site on the Internet.
  2. An attacker can perform attacks on other remote apps via a victim’s browser when the victim navigates to an attacker controlled site.

I have given an answer here: Is this CORS handler safe? You can check about CORS here. It will clarify your more.

Resource Link:

  1. Cross-Origin XMLHttpRequest
  2. Why does my JavaScript get a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error when Postman does not?
SkyWalker
  • 28,384
  • 14
  • 74
  • 132
0

If you have access to the pipelines in tomcat server, you can try to serve the API in HTTPS, then the CORS would not be happen.

OR

you can disable cors in tomcat server which i do not recommend

Evinn
  • 153
  • 1
  • 11
0

CORS problems? Use a proxy and follow the rules. By altering your header, you are removing security that was put in place to avoid a particular type of attack. That's a bad idea if you are doing anything that needs to be secure.

At a proxy you can intercept the request and alter anything in the header you need to and rewrite the response header as well if needed without incurring risk.

From your error message "http://:4444//tmpFiles/31487660124865.jpg" there is obviously something wrong with the url. Please post the code for the request.

@SkyWalker is correct with his answer. I suspect once you supply us with the rest of the code it will be obvious that the domain or protocol and domain are changing. If that is the case and you dont want make yourself vulnerable, simply run it through a proxy terminating the valid ssl cert at the proxy. (not implying that you shouldnt secure the traffic to the upstream)

Nginx works well for these sort of task. But pick your proxy.. There's a ton of them out there.

natedennis
  • 117
  • 8
  • This is my mistake, there's one edit "http://:4444//tmpFiles/31487660124865.jpg". Which code you need, i'll upload. – Tanvi Garg Oct 13 '17 at 07:16
0

If making an XMLHttpRequest causes problems then don't use it, instead consider just fetching the data (using HttpURLConnection) into a local bytearray. Now decode (display) the image as loaded from a local variable (eg: a bytes array) to avoid CORS.

Also I am used to a URL like : http://host:port/address/ but yours is witten as http://:port// so I don't understand how you can access a web (http) server by using a port only and without server address. That should cause URL error, but you must be reaching the file destination somehow, since CORS happens to protect the media...

The below code might be worth trying in a blank/new testing project :

(PS: No testable link provided like http://server:port/tmpFiles/image.jpg, so using as shown)

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("StackOverflow test");
JLabel label = new JLabel(new ImageIcon(image));
frame.setSize(500, 500); 
frame.add(label); frame.setVisible(true);

And the related imports :

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;
VC.One
  • 14,790
  • 4
  • 25
  • 57