本博客不欢迎:各种镜像采集行为,请尊重知识产权法律法规。大家都是程序员,不要闹得不开心。
本文是系列文章,上一篇文章地址是:https://newsn.net/say/cross-domain-ajax-jsonp.html 。本文主要说两个高级点的跨域话题,即:接口cookie传递及不使用jsonp如何设置跨域。
跨域 ajax 请求之 cors 原理解析(图1-1)
原理描述
目前的最新浏览器下面,都可以不使用jsonp来跨域了,就是说还使用传统的json。当然了,前端请求的时候,要特殊写上点代码,后端处理的时候,也需要发出特殊的header头,整个过程才能畅通。
另外,默认情况下,跨域的话,是不会发送cookie的。而服务器端接口需要做权限判断之类的话,就需要cookie上的支持。这个时候,同样需要做些设置。
前端代码
好了,先整体的来说。下面是前端相关代码,以jquery为例:$.ajaxSetup({
crossDomain: true,
xhrFields: {
withCredentials: true
}
});
这个非常简单,设置上这个之后,页面上所有的ajax请求都不用特殊写代码了,都会默认支持跨域传递cookie。是不是很简单?
如果你不这么整体的来写的话,每个ajax请求都需要额外添加crossDomain和xhrFields这2个属性。貌似真心不是很方便。$.ajax({
url:'https://newsn.net/',
type:'GET',
dataType:'json',
success:function (data) {},
crossDomain: true,
xhrFields: {
withCredentials: true
}
});
后端代码
后端服务器端,需要发送这些header头到客户端,苏南大叔下面的demo是php版本的。Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:GET,POST,OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:864000
这里要特别强调的是:Access-Control-Allow-Origin这个属性,设置为*肯定可以。不过,这就非常不安全了,因为这个就是来控制到底哪个域名可以跨域访问接口的。所以,这个属性,一定要设置为具体的网址才好,注意要设置为 https://yourdomain.com:port 类似这样的,http和https一定要区分好,端口号如果有的话,也一定要带上。当然了,这些header是php发出的,还是nginx发出的,都是可以的。
nginx代替php发出特定header
可能,nginx发出header似乎更合适一些。那么下面贴出的就是可能的nginx设置。
参考文章:https://enable-cors.org/server_nginx.htmllocation / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers **should** be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
下面的是另外一个我使用过的配置:server {
listen 443 ssl;
server_name blogd.newsn.net;
ssl_certificate /application/nginx/ssl/newsn.net.crt;
ssl_certificate_key /application/nginx/ssl/newsn.net.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
access_log /data/logs/nginx/cloud/access.log json;
error_log /data/logs/nginx/cloud/error.log error;
set $ACAO 'http://blog.newsn.net https://blog.newsn.net';
if ($http_origin ~* ^(http|https)://blog\.newsn\.net$) {
set $ACAO $http_origin;
}
add_header Access-Control-Max-Age 864000;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin '$ACAO';
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
location /robots.txt {
root html;
}
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 864000;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin '$ACAO';
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
return 204;
}
proxy_pass http://blog-portal;
proxy_http_version 1.1;
proxy_set_header Connection "";
#proxy_set_header Host $host:$server_port;
proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name blog.newsn.net;
rewrite ^(.*) https://blog.newsn.net$1 permanent;
}
结语
苏南大叔觉得,鉴于nginx设置如此繁杂,我们还是老老实实的用php输出header吧,其实蛮简单的。是不是?据说,上述设置中的js部分在ie低版本浏览器下面是不ok的。那么如果我们需要兼容ie低版本的话,那么还是老老实实的写不安全的jsonp,似乎是更好的解决方案。
![93ddba5b688a6967c0a88c0220992c34.png](https://img-blog.csdnimg.cn/img_convert/93ddba5b688a6967c0a88c0220992c34.png)
如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。