javascript 跨域问题 1.同源策略起源 2.跨域访问

同源策略是浏览器最基本的安全策略,它认为任何站点的内容都是不安全的,所以当脚本运行时,只被允许访问来自同一站点的资源。
同源是指域名、协议、端口都相同。
如果没有同源策略,就会发生下面这样的问题:

恶意网站用一个iframe把真实的银行登录页放到他的页面上,当用户使用用户名密码登录时,父页面的javascript就可以读取到银行登录页表单中的内容。
甚至浏览器的1个Tab页打开了恶意网站,另一个Tab页打开了银行网站,恶意网站中的javascript可以读取到银行网站的内容。这样银行卡和密码就能被轻易拿走。

2.跨域访问

由于同源策略的原因,浏览器对跨域访问做了很多限制,但有时我们的确需要做跨域访问,那要怎么办?常见的解决办法有以下几种:

2-1 浏览器端解决方案

客户端的解决方案主要有iframe传值jsonCallback

  • iframe传值
  • a.com下有a.html;
  • a.html创建iframe加载b.com下的b.html,可在加载b.html时通过?或#将参数传递到b.html中;
  • b.html加载后,可以通过提取location.search或location.hash中的内容获取a.html传过来的参数;
  • b.html创建一个iframe,加载a.com下的c.html,并且参数也通过?或#传给c.html;
  • 因为c.html和a.html是相同域名,所以c.html可以使用parent.parent访问到a.html的对象,这样也就可以将b.html需要传递的参数传回到a.html中。
  • jsonCallback
    客户端js代码:
$.ajax({
type : "get",
async:false,
url : "ajax.ashx",
dataType : "jsonp",
jsonp: "callbackparam",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)
jsonpCallback:"success_jsonpCallback",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
success : function(json){
alert(json);
alert(json[0].name);
},
error:function(){
alert('fail');
}
}); 

服务器端响应代码(C#):

public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
string callbackFunName = context.Request["callbackparam"];
context.Response.Write(callbackFunName + "([ { name:"John"} ] )");
} 

jsonp String
在一个jsonp请求中重写回调函数的名字。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,比如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。
jsonpCallback String
为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。这主要用来让jQuery生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存GET请求的时候,指定这个回调函数名。

ajax jsonp与普通的ajax请求的主要区别在于——请求响应结果的处理。如上面代码所示的响应结果为:success_jsonpCallback([ { name:"John"} ] ); ————其实就是,调用jsonp回调函数success_jsonpCallback,并将要响应的字符串或json传入此方法(作为参数值),其底层的实现,大概的猜想应该是:

function success_jsonpCallback(data)
{
success(data);
}
>```


#### 2-2 服务端解决方案
> 服务端解决方案也主要有两种`增加http头信息`和`反向代理`

- 增加http头信息
 + 在服务器返回信息中增加以下头信息:
    Access-Control-Allow-Origin: 允许的域名
    Access-Control-Allow-Methods: 允许的请求方式
    
- 反向代理(Reverse Proxy)是指以代理服务器来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 请求连接的客户端,此时,代理服务器对外就表现为一个服务器。
- 正向代理(Forward Proxy),通常都被简称为代理,就是在用户无法正常访问外部资源,比方说受到GFW的影响无法访问twitter的时候,我们可以通过代理的方式,让用户绕过防火墙,从而连接到目标网络或者服务。
 
- 反向代理的服务器配置
```js
# 反向代理设置nginx
location /api {
    proxy_pass "http://192.168.60.31:8602";
    proxy_set_header Host "192.168.60.31:8602";
    proxy_set_header X-Forwarded-For $remote_addr;
}
# 反向代理设置Apache
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /api http://192.168.60.31:8602
ProxyPassReverse /api http://192.168.60.31:8602