为什么要限制跨域?

为了防止恶意网站获取用户在其他网站上的信息。

如果不限制,恶意网站通过ajax访问银行余额页面。解析返回的html就能拿到用户余额。
没有限制请求,限制的是获取信息。
所以form表单可以跨域,而ajax不能跨域。
form只是提交不获取返回结果,ajax要获取结果

为什么不限制请求?请求本来就不好限制,给你个csrf就诱导了请求。重要请求要做验证码,但是一些不重要的请求可能返回隐私信息。防的就是黑客获取隐私信息。

发生跨域的条件

  1. 浏览器限制
  2. 发出的请求跨域
  3. XHR请求

解决方法

针对上面三个条件的解决方法

  1. 浏览器限制
    可以修改浏览器设置,但是无意义,不能修改所有用户的浏览器设置
  2. 发出的请求跨域
    • 修改被调用方(返回头,让浏览器支持跨域)
    • 修改调用方(代理服务器转发?)
  3. XHR请求
    JSON

1. JSONP【只支持get,过期】

返回js代码,发出的请求时script
跨域总结 - 图1
跨域总结 - 图2

跨域总结 - 图3

AbstractJsonpResponseBodyAdvice 已经过期,推荐使用CORS

Will be removed as of Spring Framework 5.1, use CORS instead.

将callback值作为函数名返回。”_”参数防止被缓存。

jsonp只支持get请求

2. 被调用方解决

跨域

2.1 服务器端实现

2.1.1 Filter 解决方案

跨域请求,请求头增加了origin 字段

跨域总结 - 图4

编写filter 增加response 字段

跨域总结 - 图5

2.1.1.1 简单请求&非简单请求

跨域总结 - 图6

非简单请求的预检命令

非简单请求,会有“预检命令”

跨域总结 - 图7

预检命令会发送 content-type method,看服务器是否支持此类型跨域。

跨域总结 - 图8

预检命令缓存

跨域总结 - 图9

2.1.1.2带cookie的跨域

  • 当代cookie 时,Acces-Control-Allow-Origin 不能为* 号
  • 增加Access-Control-Allow-Credentials:3600

问题:Acces-Control-Allow-Origin 不能为* 那其他跨域怎么办呢?

可以在filter中 获取request的origin字段,然后设置到response的Acces-Control-Allow-Origin 。

2.2 nginx配置

跨域总结 - 图10

  • 包括增加 响应头、
  • 将origin和自定义header返回
  • 处理预检命令OPTIONS

2.3 apache配置

2.4 spring 框架解决方案

@CrossOrigin
@CrossOrigin(origins = “ http://domain2.com“, maxAge = 3600)

3 调用方 解决方案

代理服务器

浏览器有跨域限制,服务器没有跨域一说。
浏览器请求到同域名的自己的nginx,ng转发到远程服务器。

跨域总结 - 图11

跨域总结 - 图12