AJAX跨域问题[CROS与NIGNX]以及cookie跨域共享

本地跨域与服务器跨域

前端页面与后台运行在不同的服务器或不同的域名时,就会出现跨域问题。

本地跨域:

如果是同一台服务器,前后端url拥有不同的域名,则通过后端设置正确的请求体origin则可解决:
(为了安全起见,前端不得修改请求体的 Origin域名)

     //定义响应头信息
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Allow-Headers: Content-Type, Origin, X-Requested-With, Accept');
        header('Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS');
        header('Access-Control-Max-Age: 3600');
        header('Access-Control-Allow-Origin:' . '前端域名网址');

服务器跨域:

目前解决这类跨域问题主要有以下方法:
不讨论只能使用GET的jsonp方法。

方法一、CROS(跨域资源共享,Cross-Origin Resource Sharing)的方法。

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)跨域资源共享 CORS 详解。看名字就知道这是处理跨域问题的标准做法。CORS有两种请求,简单请求和非简单请求。

简单请求下, 可以使用:

header("Access-Control-Allow-Origin", "*"); //表示允许任何远程访问
设置Access-Control-Allow-Methods //允许访问的方法等

非简单请求:

如果发送的是带凭据的非简单请求,但服务器的相应中没有包含这个头部,那么浏览器就不会把相应交给JavaScript,请求就无法得到结果的数据(浏览器得到了,但是我们请求的方法得不到,因为被浏览器拦截了),因此在withCredentials时,服务端的Access-Control-Allow-Origin必须配置具体的具体的域名, 不能为通配符。并且还需要设置其他的请求头:

CROS协议流程

1、设置HTTP响应头Access-Control-Allow-Origin,指定服务器端允许进行跨域资源访问的来源域。

2、预请求验证:
浏览器在发现页面中有上述条件的动态跨域请求的时候,并不会立即执行对应的请求代码,而是会先发送Preflighted requests(预先验证请求)

OPTIONS请求头部中会包含以下头部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。
服务器收到OPTIONS请求后,设置Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers头部与浏览器沟通来判断是否允许这个请求。

3、服务端流程[重要]
要实现CORS跨域,服务端需要这个一个流程:服务端流程
流程如下:

首先查看http头部有无origin字段;
如果没有,或者不允许,直接当成普通请求处理,结束;
如果有并且是允许的,那么再看是否是preflight(method=OPTIONS);
如果是preflight,就返回Allow-Headers、Allow-Methods等,内容为空;
如果不是preflight,就返回Allow-Origin、Allow-Credentials等,并返回正常内容。
服务端响应流程配置, 参考以下在过滤器中间层中处理的配置:

        header('Access-Control-Allow-Credentials: true'); // 非简单请求下的配置处理
       header('Access-Control-Allow-Headers: Origin, Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
        header('Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS');
        header('Access-Control-Max-Age: 3600');
        header('Access-Control-Allow-Origin: ' . Request::instance()->header('Origin'));
        //非简单请求下, 指定获取到的单个域名[间接通配], 此处加白名单组校验更好。
对于预请求的处理可以有以下几种方法:

1、JAVA的拦截器或者PHP中入口文件对OPTIONS请求进行拦截return

2、NIGNX在流程中统一处理

NIGNX对以上流程实现以及OPTIONS请求处理配置:参考

下面nginx-spdy-push里/pub接口启用CORS的配置:

location ~ ^/pub/([-_.A-Za-z0-9]+)$ {
 
    set $cors "local";
 
    # configure CORS based on https://gist.github.com/alexjs/4165271
    # (See: http://www.w3.org/TR/2013/CR-cors-20130129/#access-control-allow-origin-response-header )
 
    if ( $http_origin ~* "https://.+\.gw\.com\.cn(?=:[0-9]+)?" ) {
        set $cors "allow";
    }
    if ($request_method = "OPTIONS") {
        set $cors "${cors}options";
    }
 
    # if CORS request is not a simple method
    if ($cors = "allowoptions") {
        # Tells the browser this origin may make cross-origin requests
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        # in a preflight response, tells browser the subsequent actual request can include user credentials (e.g., cookies)
        add_header 'Access-Control-Allow-Credentials' "true";
 
        # === Return special preflight info ===
 
        # Tell browser to cache this pre-flight info for 1 day
        add_header 'Access-Control-Max-Age' 86400;
 
        # Tell browser we respond to GET,POST,OPTIONS in normal CORS requests.
        # Not officially needed but still included to help non-conforming browsers.
        # OPTIONS should not be needed here, since the field is used
        # to indicate methods allowed for 'actual request' not the preflight request.
        # GET,POST also should not be needed, since the 'simple methods' GET,POST,HEAD are included by default.
        # We should only need this header for non-simple requests  methods (e.g., DELETE), or custom request methods (e.g., XMODIFY)
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
 
        # Tell browser we accept these headers in the actual request
        add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type';
 
        # === response for OPTIONS method ===
 
        # no body in this response
        add_header 'Content-Length' 0;
        # (should not be necessary, but included for non-conforming browsers)
        add_header 'Content-Type' 'text/plain, charset=utf-8';
        # indicate successful return with no content
        return 204;
    }
 
    if ($cors = "allow") {
        rewrite /pub/(.*) /pub_cors/$1 last;
    }
 
    if ($cors = "local") {
        rewrite /pub/(.*) /pub_int/$1 last;
    }
}
 
location ~ /pub_cors/(.*) {
    internal;
    # Tells the browser this origin may make cross-origin requests
    add_header 'Access-Control-Allow-Origin' "$http_origin";
    # in a preflight response, tells browser the subsequent actual request can include user credentials (e.g., cookies)
    add_header 'Access-Control-Allow-Credentials' "true";
 
    push_stream_publisher                   admin; # enable delete channel
    set $push_stream_channel_id             $1;
 
    push_stream_store_messages              on;  # enable /sub/ch.b3
    push_stream_channel_info_on_publish     on;
}
 
location ~ /pub_int/(.*) {
  #  internal;
    push_stream_publisher                   admin; # enable delete channel
    set $push_stream_channel_id             $1;
 
    push_stream_store_messages              on;  # enable /sub/ch.b3
    push_stream_channel_info_on_publish     on;
}

方法二、NIGNX反向代理解决跨域:

[CORS] 需要服务器设置header :Access-Control-Allow-Origin。客户端AJAX额外携带参数,而
NIGNX反向这个方法一般很少有人提及,但是他可以不用目标服务器配合,不过需要你搭建一个中转nginx服务器,用于转发请求。

nginx配置

关于nginx的配置可以查看另一篇博文:http://www.cnblogs.com/renjing/p/6126284.html。找到nginx的配置文件“nginx.conf”,修改一下信息

server {
        listen       80; #监听80端口,可以改成其他端口
        server_name  localhost; # 当前服务的域名

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://localhost:81;
            proxy_redirect default;
        }

        location /apis { #添加访问目录为/apis的代理配置
            rewrite  ^/apis/(.*)$ /$1 break;
            proxy_pass   http://localhost:82;
       }
#以下配置省略

配置解释:

1.由配置信息可知,我们让nginx监听localhost的80端口,网站A与网站B的访问都是经过localhost的80端口进行访问。
2.我们特殊配置了一个“/apis”目录的访问,并且对url执行了重写,最后使以“/apis”开头的地址都转到“http://localhost:82”进行处理。
3.rewrite ^/apis/(.)/1 break;
代表重写拦截进来的请求,并且只能对域名后边以“/apis”开头的起作用,例如www.a.com/apis/msg?x=1重写。只对/apis重写。
  rewrite后面的参数是一个简单的正则 ^/apis/(.
),1代表正则中的第一个(),$2代表第二个()的值,以此类推。
  break代表匹配一个之后停止匹配。
4.经过重写后的请求,都会被认为是同源请求,从而不会导致跨域问题。
—————————————————————————————————————

cookie共享设置

一、将cookie的domain设置为多个/共同的顶级域名


图片.png

二、带认证的请求
默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。
在ajax里带上参数:
1 crossDomain: true,
2 xhrFields:{
3 withCredentials:true
4 },
如果服务器接收带凭据的请求,会用下面的HTTP头部来响应。
在服务端设置:
Access-Control-Allow-Credentials: true
服务器还可以在Preflight响应中发送这个HTTP头部,表示允许源发送带凭据的请求。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容