[关闭]
@yangxitian 2016-04-30T17:07:45.000000Z 字数 1656 阅读 1170

JS API跨域解决之CORS

blog


大家好!我是Shelter,今天给大家分享如何使用CORS解决JS跨域问题。

废话不多说,直接上解决方案代码,后面再做详细解释!

CODE

WEB后台增加Response Header头(PHP为例子)

  1. //配置信任的跨域来源
  2. header('Access-Control-Allow-Origin: http://localhost');
  3. //配置允许发送认证信息 比如cookies(会话机制的前提)
  4. header('Access-Control-Allow-Credentials: true');

前端

  1. var to = 'http://120.27.97.158/TDetc/listPopularize.html';
  2. $.ajax({
  3. type: 'POST',
  4. data: {},
  5. url: to,
  6. //开启携带认证信息,默认为关闭
  7. xhrFields: {
  8. withCredentials: true
  9. },
  10. success: function(result) {
  11. console.log(result);
  12. }
  13. });

原理解释

参考 FED社区: 浏览器 AJAX 跨域请求访问控制

1.同源策略(JS角度)

即一个域名下的JS只能操作(读写,请求等)该域名下的资源(包含服务器和本地资源,如cookie等)

假设没有同源策略,会发生什么事情呢?

总所周知,JS拥有读取cookie、发送数据到远程服务器和获取远程资源的能力。那么,如果没有同源策略的存在,也就是意味着任意网页的JS可以读取和发送用户PC上所有的cookie,另外自己服务器上的资源会被任意网页获取,可想而知,后果有多么严重。

2.JS API跨域问题所在

即JS想调用一个非同源资源,被目标服务器拒绝。那么也就是决定权在于服务器,所以只要告诉服务器哪个域名是自己人便可!

3.解决方案

这里先粗略讲下 JS 同源和非同源请求 的区别

// 如果出现跨域了,会进行如下请求
开始请求 ==> 预请求 ===> 主请求

// 如果没有出现跨域,或其他不必进行预请求情况
开始请求 ===> 主请求

预请求是一个method为option的请求,(预请求会有一小段有效期,所以有时候在后台无法观察到option请求)

预请求得到的相应如下:

  1. //信任的跨域源
  2. Access-Control-Allow-Origin: http://1.a.com:8081
  3. //允许的请求方式
  4. Access-Control-Allow-Methods: GET, POST
  5. //允许的自定义请求头
  6. Access-Control-Allow-Headers: x-request-with,content-type
  7. //是否接受跨域请求的认证信息,如cookie
  8. Access-Control-Allow-Credentials: true
  9. //信任跨域有效期,秒为单位
  10. Access-Control-Max-Age: 60
  11. //允许前端JS可以获取到的自定义response头
  12. Access-Control-Expose-Headers: x-test

JS得到预响应后,就会知道目标服务器是否允许被获取资源。
允许,则进行主请求,否则报错。

也就是后台完全可以根据需要,配置相应的response头,来解决自己站点JS跨域问题。
这就是CORS方法!是不是简单粗暴?


注意:假设信任的跨域源为任意源 * ,那么Allow-Credentials将无法开启成功!导致会话机制失常。
如果需要配置多个信任的跨域源,可以采用以下方法(PHP为例子):

  1. $allow_origin = [
  2. 'http://myself.com',
  3. 'https://myself.com'
  4. ];
  5. //只有跨域请求才会存在 HTTP_ORIGIN
  6. if( isset($_SERVER['HTTP_ORIGIN']) &&
  7. in_array($_SERVER['HTTP_ORIGIN'], $allow_origin)
  8. ) {
  9. header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
  10. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注