跨域请求的原因及解决方案

一、什么是跨域?

请求方与服务方的源不同,就是跨域,包括:

  • 协议不同
  • 域名不同
  • 端口不同

跨域的缘由:
主要是因为浏览器指定的同源策略,即“协议+域名+端口”都相同,它是浏览器最基本和最核心的安全机制,关闭它会容易受到XSS和CSRF的攻击。

跨域的后果:

  1. Cookie,LocalStorage,IndexDB无法获取
  2. DOM和JS对象无法获得
  3. AJAX请求不能发送(实际能发送,但拿不到结果,被拦截下来)

二、跨域解决方案

1、Jsonp请求:
jsonp由两部分组成:回调函数和数据。回调函数是当浏览器收到响应时调用的函数,回调函数名一般在请求种指定,数据就是服务端处理完请求返回的数据,作为回调函数的参数。如:

http://somewhere-else/json/?callback=handleResponse

实现原理: 通过动态创建一个script,通过这个script去请求,请求完,该script即被销毁。可通过对JQ打断点的方式验证(可看见JQ在网页源码嵌入了一个临时的script,当Jsonp请求完成之后,该script即被销毁。)

缺点:

  1. 只能支持GET类型的请求,不支持POST, PUT, DELETE请求。
  2. Jsonp是从其他域种加载代码执行,可能会夹杂一些恶意代码,所以在使用jsonp时一定要保证被请求方安全可靠。
  3. jsonp请求返回的不是json数据,而是一个js脚本,需要后台服务器配合封装。

2、CORS:跨域资源共享,定义了在跨域访问时,浏览器和服务器的沟通方式,使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定跨域请求或响应时应该成功还是失败。

如:发起一个GET跨域请求,浏览器会为http头部加上一个额外的Origin头部,其中包含了页面的源信息(协议、域名和端口号),这个额外的Origin决定了服务器是否响应该请求。一个Origin头部实例:

Origin: https://www.somewhere-else.net

如果服务器认可该请求就会在响应头加上Access-Control-Allow-Origin标志字段,值可以是与请求头带来的Origin相同,如果该服务器上的是公共资源,值就是“*”。

Access-Control-Allow-Origin: https://www.somewhere-else.net

如果响应头没有这个字段,说明服务器拒绝了这次跨域请求,会抛出一个错误。
但是并不能被xhr的onerror事件捕获。默认情况下跨域请求都是不带凭证的(cookie,HTTP认证及服务端SSL证明等),通过修改xhr对象的withCredentials(IE10以前的版本不支持该属性)设置为true,可以指定某个请求携带凭证。如果服务器允许跨域请求携带凭证响应头部会有标示。

Access-Control-Allow-Credentials: true

如果发送的是带凭证的请求,响应头里却没有这个字段,那么浏览器就不会吧响应交给JS,意思是xhr获取到的responseText为空,status为0,这个时候onerror可以捕获到该错误。

通过@CrossOrigin注解来实现跨域请求:纯粹Java后台实现,前端照常使用Ajax请求。

@RequestMapping("/loadData")
@ResponseBody
@CrossOrigin
public Object loadData() {
   String msg = "Hello JSONP";
   return msg;
}

也可以添加参数,进一步限制允许跨域请求的范围:

@RequestMapping("/loadData")
@ResponseBody
@CrossOrigin(origins = "http://localhost:8080", methods = {RequestMethod.POST, RequestMethod.GET})
public Object loadData() {
   String msg = "Hello JSONP";
   return msg;
}

@CrossOrigin不仅支持在方法上添加,还支持在Controller类上添加,代表该Controller下面所有方法都支持跨域请求。

实际上底层的实现原理就是通过添加以下响应头实现的:
resp.setHeader("Access-Control-Allow-Origin", "*")
当然这种是所有的跨域请求都放行,不是很安全,如果你需要只让某些网络访问,那么可以将*替换为具体的请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值