访问控制请求头,添加到AJAX请求头与jQuery

我想添加一个自定义头的AJAX POST请求从jQuery。

我试过了:

$.ajax({
type: 'POST',
url: url,
headers: {
"My-First-Header":"first value",
"My-Second-Header":"second value"
}
//OR
//beforeSend: function(xhr) {
//  xhr.setRequestHeader("My-First-Header", "first value");
//  xhr.setRequestHeader("My-Second-Header", "second value");
//}
}).done(function(data) {
alert(data);
});

当我发送这个请求,我看FireBug,我看到这个头:

OPTIONS xxxx/yyyy HTTP/1.1
. xml 主持人:127.0.0.1:6666 < br / > User-Agent: Mozilla/5.0 (Windows NT 6.1;WOW64;rv:11.0) Gecko/20100101 Firefox/11.0
接受:text / html, application / xhtml + xml应用程序/ xml; q = 0.9, /; q = 0.8 < br / > 接收语言:fr - fr; q = 0.8, en - us; q = 0.5, en; q = 0.3 < br / > Accept-Encoding: gzip, deflate
连接:维生< br / > 产地:空< br / > Access-Control-Request-Method:文章< br / > Access-Control-Request-Headers: my-first-header my-second-header < br / > 编译指示:no - cache < br / > cache - control: no - cache < br / > < / p >

为什么我的自定义头文件去Access-Control-Request-Headers:

Access-Control-Request-Headers: my-first-header my-second-header

我期待的头值是这样的:

My-First-Header:第一个值
My-Second-Header: second value

这可能吗?

1007729 次浏览

你在Firefox中看到的并不是实际的请求;注意HTTP方法是OPTIONS,而不是POST。它实际上是浏览器做出的“pre-flight”请求,以确定是否应该允许跨域AJAX请求:

http://www.w3.org/TR/cors/ < a href = " http://www.w3.org/TR/cors/ " > < / >

预飞行请求中的Access-Control-Request-Headers头包含实际请求中的头列表。然后,在浏览器提交实际请求之前,服务器将报告这些头在此上下文中是否受支持。

下面是一个如何在jQuery Ajax调用中设置请求头的示例:

$.ajax({
type: "POST",
beforeSend: function(request) {
request.setRequestHeader("Authority", authorizationToken);
},
url: "entities",
data: "json=" + escape(JSON.stringify(createRequestObject)),
processData: false,
success: function(msg) {
$("#results").append("The result =" + StringifyPretty(msg));
}
});

下面的代码适合我。我总是只使用单引号,而且效果很好。我建议你只使用单引号只使用双引号,但不要混淆。

$.ajax({
url: 'YourRestEndPoint',
headers: {
'Authorization':'Basic xxxxxxxxxxxxx',
'X-CSRF-TOKEN':'xxxxxxxxxxxxxxxxxxxx',
'Content-Type':'application/json'
},
method: 'POST',
dataType: 'json',
data: YourData,
success: function(data){
console.log('succes: '+data);
}
});

这就是为什么不能用JavaScript创建机器人的原因,因为您的选项受限于浏览器允许您执行的操作。你不能只是命令一个浏览器遵循歌珥策略,这是大多数浏览器遵循的,发送随机请求到其他来源,并允许你简单地得到响应!

此外,如果你试图手动编辑一些请求头,比如浏览器自带的开发者工具中的origin-header,浏览器会拒绝你的编辑,并可能会发送一个预先的OPTIONS请求。

尝试使用rack-cors宝石。并在Ajax调用中添加报头字段。

因为你发送自定义报头,所以你的CORS请求是不是一个简单的请求,所以浏览器首先发送一个preflight OPTIONS请求来检查服务器是否允许你的请求。

Enter image description here

如果您在服务器上打开CORS,那么您的代码将正常工作。你也可以使用JavaScript来获取(在这里)

let url='https://server.test-cors.org/server?enable=true&status=200&methods=POST&headers=My-First-Header,My-Second-Header';




$.ajax({
type: 'POST',
url: url,
headers: {
"My-First-Header":"first value",
"My-Second-Header":"second value"
}
}).done(function(data) {
alert(data[0].request.httpMethod + ' was send - open chrome console> network to see it');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Here is an example configuration which turns on CORS on nginx (nginx.conf file):

location ~ ^/index\.php(/|$) {
...
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}

下面是一个示例配置,它打开Apache上的CORS(。htaccess)。

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------


# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/


# <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
# </IfModule>


#Header set Access-Control-Allow-Origin "http://example.com:3000"
#Header always set Access-Control-Allow-Credentials "true"


Header set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

从客户的角度来说,我解决不了这个问题。

node . jsExpress.js端,你可以使用歌珥模块来处理它。

var express    = require('express');
var app        = express();
var bodyParser = require('body-parser');
var cors       = require('cors');


var port = 3000;
var ip = '127.0.0.1';


app.use('*/myapi',
cors(), // With this row OPTIONS has handled
bodyParser.text({type: 'text/*'}),
function(req, res, next) {
console.log('\n.----------------' + req.method + '------------------------');
console.log('| prot:' + req.protocol);
console.log('| host:' + req.get('host'));
console.log('| URL:' + req.originalUrl);
console.log('| body:', req.body);
//console.log('| req:', req);
console.log('.----------------' + req.method + '------------------------');
next();
});


app.listen(port, ip, function() {
console.log('Listening to port:  ' + port);
});


console.log(('dir:' + __dirname));
console.log('The server is up and running at http://' + ip + ':' + port + '/');

如果没有cors(),这些OPTIONS必须出现在POST之前。

.----------------OPTIONS------------------------
| prot:http
| host:localhost:3000
| url:/myapi
| body: {}
.----------------OPTIONS------------------------


.----------------POST------------------------
| prot:http
| host:localhost:3000
| url:/myapi
| body: <SOAP-ENV:Envelope .. P-ENV:Envelope>
.----------------POST------------------------

Ajax调用:

$.ajax({
type: 'POST',
contentType: "text/xml; charset=utf-8",


//These does not work
//beforeSend: function(request) {
//  request.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
//  request.setRequestHeader('Accept', 'application/vnd.realtime247.sct-giro-v1+cms');
//  request.setRequestHeader('Access-Control-Allow-Origin', '*');
//  request.setRequestHeader('Access-Control-Allow-Methods', 'POST, GET');
//  request.setRequestHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type');
//},
//headers: {
//  'Content-Type': 'text/xml; charset=utf-8',
//  'Accept': 'application/vnd.realtime247.sct-giro-v1+cms',
//  'Access-Control-Allow-Origin': '*',
//  'Access-Control-Allow-Methods': 'POST, GET',
//  'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type'
//},
url: 'http://localhost:3000/myapi',
data: '<SOAP-ENV:Envelope .. P-ENV:Envelope>',
success: function(data) {
console.log(data.documentElement.innerHTML);
},
error: function(jqXHR, textStatus, err) {
console.log(jqXHR, '\n', textStatus, '\n', err)
}
});

尝试添加'Content-Type':'application/json':

 $.ajax({
type: 'POST',
url: url,
headers: {
'Content-Type':'application/json'
}
//OR
//beforeSend: function(xhr) {
//  xhr.setRequestHeader("My-First-Header", "first value");
//  xhr.setRequestHeader("My-Second-Header", "second value");
//}
}).done(function(data) {
alert(data);
});