简体   繁体   中英

“Cross-Origin Request Blocked: The Same Origin Policy” Error in browser

I got this error when I try to POST json file to my server.

On my server side, the code is:

    @POST
    @Path("updatedata")
    @Produces("text/plain")
    @Consumes("application/json")
    public Response UpdateData(String info) {
        Gson gson = new Gson();
        List<Data> list = gson.fromJson(info, new TypeToken<List<Data>>() {
        }.getType());

        int is_success = 0;
        try {
            is_success += trainingdata.updateData(list);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        String returnjson = "{\"raw\":\"" + list.size() + "\",\"success\":\"" + is_success + "\"}";
        return Response.ok().entity(returnjson).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "POST").build();
    }

I can update my data successfully through RESTClient - a Chrome Plugin.

But when I build the frontend and try to call the API through jaascript, Firefox shows: Cross-Origin Request Blocked: The Same Origin Policy .... Chrome shows: XMLHttpRequest cannot load ... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '...' is therefore not allowed access

I wrote the javascript like this:

var json = JSON.stringify(array);

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://myurl:4080/updatedata", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(json);

xhr.onload = function (e) {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            alert('hello');
        }
    }
};
xhr.onerror = function (e) {
    console.error(xhr.statusText);
};

Is there any problem with my javascript code?

I deploy my backend code and front end code in the same machine.

The GET function works successfully.

@GET
@Produces("application/json")
@Path("/{cat_id}")
public Response getAllDataById(@PathParam("cat_id") String cat_id) {
    ReviewedFormat result = null;
    try {
        result = trainingdata.getAllDataById(cat_id);
        Gson gson = new Gson();
        Type dataListType = new TypeToken<ReviewedFormat>() {
        }.getType();
        String jsonString = gson.toJson(result, dataListType);
        return Response.ok().entity(jsonString).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET").build();

    } catch (SQLException e) {
        logger.warn(e.getMessage());
    }
    return null;
}

Front end:

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://URL:4080/mywebservice/v1/trainingdata/" + cat_id, true);

xhr.onload = function (e) {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            //console.log(xhr.responseText);
            var jsoninfo = xhr.responseText;
            var obj = JSON.parse(jsoninfo);
        }
     }
}

CORS prevents issues from occurring with cross-site attacks and forces smart development by not relying on other people's resources (which could die). Its a default security feature on most servers and browsers.

In Apache you can disable CORS by adding a header, IIS and AppEngine work similarly.

Since you are developing locally, your best bet is either XAMPP/WAMPP plus an appropriate header - or simply switch to FireFox.

FireFox does not consider local files under CORS, while most browsers do.

Apache Fix :

Add header ->

Header set Access-Control-Allow-Origin "*"

Reset Server ->

apachectl -t
  • sudo service apache2 reload

IIS Fix:

Modify web.config in root directory (similar to HTAccess)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="*" />
     </customHeaders>
   </httpProtocol>
 </system.webServer>
</configuration>

App Engine :

Header Method for Python: self.response.headers.add_header()

class CORSEnabledHandler(webapp.RequestHandler):
  def get(self):
    self.response.headers.add_header("Access-Control-Allow-Origin", "*")
    self.response.headers['Content-Type'] = 'text/csv'
    self.response.out.write(self.dump_csv())

For Java : resp.addHeader()

public void doGet(HttpServletRequest req, HttpServletResponse resp) {
  resp.addHeader("Access-Control-Allow-Origin", "*");
  resp.addHeader("Content-Type", "text/csv");
  resp.getWriter().append(csvString);
}

For Go : w.Header().Add()

func doGet(w http.ResponseWriter, r *http.Request) {
  w.Header().Add("Access-Control-Allow-Origin", "*")
  w.Header().Add("Content-Type", "text/csv")
  fmt.Fprintf(w, csvData)
}

CORS issues can be bypassed via JSONP for GET requests if this interested you: http://en.wikipedia.org/wiki/JSONP

This is an issue caused by making a cross domain request in javascript. The browser prevents this for security reasons.

In javascript you can't make requests to a different domain (including different port) by default.

Your options are to enable CORS or use a reverse proxy if you need to send requests to another domain.

It sounds like you have control over the remote resource you're posting to. If that's the case, your remote resource needs to have the following header:

Access-Control-Allow-Origin: http://yourrequestingurl.com

More information here (It looks like someone asked a question like yours already): Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at

Thanks for @TGH's hint, I finally solve the problem by adding a web proxy.

Refer to Using a Web Proxy , I create a proxy.php file, which receive Javascript's xmlHttpRequest, get the postdata and call the web service API.

<?php

$method = isset($_POST['method']) ? $_POST['method'] : 'POST';
$postData = file_get_contents('php://input');
$url = $envArray['url'] . ':' . $envArray['port'] . '/mywebservice/v1/trainingdata/updatedata';

echo curl($url, $postData, $method);
}

function curl($url = '', $params = '', $method = 'POST'){
    if (empty($url)) {
        error_log('Curl URL is empty.');
        return;
    }
    $envArray = Settings::getEnvAry();

    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);                                                                     
    curl_setopt($ch, CURLOPT_POSTFIELDS, html_entity_decode($params, ENT_QUOTES));
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
            'Content-Type: application/json',                                                                                
            'Content-Length: ' . strlen($params)
        )                                                                       
    );
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);                                                                      

    $response = curl_exec($ch);
    $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $rs = array('status' => $http_status, 'response' => $response);

    return json_encode($rs);
}
?>

And in the front end, I call the proxy.php

 var xhr = new XMLHttpRequest();
    xhr.open("POST", "proxy.php", true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(json);

I think this is better for deploy project onto remote box, instead of modifying Apache configuration.

You can add header in your Nginx configuration and similarly in other web servers

example

add_header Access-Control-Allow-Origin *;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM