详细

javascript 跨域问题

1.同源策略起源

  • 同源策略是浏览器最基本的安全策略,它认为任何站点的内容都是不安全的,所以当脚本运行时,只被允许访问来自同一站点的资源。
  • 同源是指域名、协议、端口都相同。
  • 如果没有同源策略,就会发生下面这样的问题:
恶意网站用一个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代码
```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的时候,我们可以通过代理的方式,让用户绕过防火墙,从而连接到目标网络或者服务。

  • 反向代理的服务器配置

# 反向代理设置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