处理无“访问控制允许来源” - 客户端问题

Posted

技术标签:

【中文标题】处理无“访问控制允许来源” - 客户端问题【英文标题】:Handle no 'Access-Control-Allow-Origin' - issues on client side 【发布时间】:2014-02-12 11:40:19 【问题描述】:

对于许多新手来说,这个问题可能不是一个新问题。我是其中之一,我必须在客户端处理这个问题。所以,请不要将此问题标记为重复。

我的网站客户端代码部署在服务器中,该网站调用部署在其他不同服务器中的 Web 服务。 (请注意:我没有此网络服务代码访问权限)。

我的 AJAX 代码来检索数据:

$.ajax(
        type: 'GET',
        url: 'http://webservice_url',
        success: function (data) 
             //success
        ,
        failure: function(error)
            //error
        
    );

通过 AJAX 访问此网络服务时,我收到:

XMLHttpRequest cannot load http://webservice_url. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

浏览器控制台日志:

我可以在浏览器控制台中成功查看我的 Web 服务的响应(在我的 Web 服务的“网络”选项卡 ->“响应”选项卡下)。但是,正在检索上述错误。

在查看之前的许多帖子时,我发现通过将响应标头设置为:

response.addHeader("Access-Control-Allow-Origin", "*");

将解决此问题。

但是,我无权更改我的网络服务代码以添加响应标头。我必须在网站上解决这个问题。

我使用 ExpressJS 和 Node.js 开发了这个网站。我的应用代码是

var http = require('http');
var routes = require('./routes');
var express = require('express');
var path = require('path');

var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.cookieParser('secret code'));
app.use(express.logger('dev'));
app.use(express.favicon());
app.use(express.methodOverride());
app.use(express.session());
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// Add headers
app.use(function (req, res, next) 
    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Pass to next layer of middleware
    next();
);

app.get('/', routes.index);

http.createServer(app).listen(3000, function()
    console.log('Express server started successfully');
);

添加 res.setHeader('Access-Control-Allow-Origin', '*') 对我没有帮助。

谁能指导我。

【问题讨论】:

如果您无法访问 Web 服务,那么您显然无法更改它生成的响应标头——因此您无法使用跨域 AJAX。如果他们提供其他请求数据的方法,请查看他们的文档,例如JSONP。 【参考方案1】:

这是因为跨域限制。

您在客户端代码中添加了Access-Control-Allow-Headers,这是错误的。它应该添加到服务器端代码中,即您尝试访问的 Web 服务中。

但是,由于您无权访问该 Web 服务,因此您可以使用 jQuery ajax,如 answer 中所示

$.ajax(
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     jsonp: 'callback',
     jsonpCallback: 'jsonpCallback',
     success:function(json)
         // do stuff with json (in this case an array)
         alert("Success");
     ,
     error:function()
         alert("Error");
     ,
);

function jsonpCallback(data)
    alert("jsonpCallback");

或者,使用解释的备用函数here

要使用jsonp,网络服务必须支持回调参数,查看他们的文档。

【讨论】:

感谢您的快速回复。现在我明白了“访问控制允许标题”对我不起作用的原因。我试过'jsonp'。现在我没有在控制台中检索 No 'Access-Control-Allow-Origin' 错误!但是,我仍然无法在 AJAX 成功块中接收响应数据。在浏览器控制台中调查我的网络服务时(在我的网络服务的“网络”选项卡 ->“响应”选项卡下),我收​​到了有效的响应。但是,“请求 URL”中附加了一些回调。如MY_WEBSERVICE?callback=jQuery19104137628001626581_1390394111156…。你能指导我吗 jsonp 中的回调是这样工作的。您必须像我在更新的答案中显示的那样传递回调。此回调作为查询字符串参数,ws 应将响应包含在回调函数中。 嗨 CanMAH,如果我的问题很愚蠢,对不起。我是 JSONP 的新手。我使用了您的示例代码。但是,成功响应时不会为我调用 jsonpCallback 函数。当 web 服务支持回调参数时,您提到使用 JSONP。我认为我的网络服务不支持 jsonp(因为在客户端没有为我调用 jsonpCallback 函数)。如果我错了,请纠正我。由于我无法控制我的服务器代码(Web 服务),因此我无法更改该 Web 服务来处理 jsonp 类型。我还有什么其他的灵魂可以在客户端工作吗?再次感谢您的宝贵时间。 jsonp doesn't work without a callback,除此之外我认为没有其他解决方案了。 你为什么不在你的服务器上创建一个代理方法来接受你的 ajax 请求,向那个 web 服务发出请求?

以上是关于处理无“访问控制允许来源” - 客户端问题的主要内容,如果未能解决你的问题,请参考以下文章

ExpressJS Post 方法 - 无访问控制允许来源

春季网关请求被 CORS 阻止(无访问控制-允许-来源标头)

Angular 和 Laravel CORS 访问控制允许来源问题

Angular 2 http服务中的访问控制允许来源问题

如何绕过访问控制允许来源?

如何绕过访问控制允许来源?