同源策略--跨域
为啥会出现跨域
我们发送的请求通常包含这三部分:协议+域名+端口。如果浏览器发送的ajax请求和当前界面的url的这三部分全部相同即为同源,反之不同源。
如果没有同源策略,假设用户登陆网站a后又去访问b网站,那么b网站就可以窃取用户在网站a的cookie进而冒充用户。
注意,我们常说的同源策略是针浏览器针对ajax的限制!!ajax请求可以到达服务器并响应,但是浏览器会对响应进行校验,非同源则跨域。
跨域解决几种解决方案
CORS(corss origin resource sharing)
CORS(跨域资源共享),是一种基于HTTP头的机制,该机制需要浏览器和服务器同时支持,
对于前端而言不需要做任何操作,浏览器在发送请求时会自动带上cors请求头,我们只需要在服务器的响应头进行设置即可,只要HTTP响应头中包含相应的CORS响应头即可。
CORS机制在老版本的浏览器中不支持,现代浏览器都支持CORS。在使用CORS发送AJAX请求时浏览器端代码和过去一致,服务器端仅需要配置CORS的响应头。
服务器需要设置的响应头如下:
对于复杂请求,在正式请求发送前会有一个预检请求OPTIONS来询问服务器,是否允许跨域请求,请求头包含这些东西:
OPTIONS /cors HTTP/1.1
Origin: http://localhost:8888 请求来源
Access-Control-Request-Method: GET 请求方法
Access-Control-Request-Headers: X-Custom-Header 额外的头信息
因为我们服务器的响应头已经配置了哪些请求方法、哪些请求源可以跨域,浏览器会首先检查服务器对预检请求的响应,如果响应中包含了允许跨域的 CORS 响应头,浏览器会继续发送实际的请求。
复杂请求和简单请求
简单请求
- 请求方法:GET、POST、HEAD
- HTTP的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
复杂请求
- 请求方法:put、delete
一般认为axios是复杂请求,因为axios默认会添加一些自定义头部,尤其是在处理 POST 请求时。以下是几个常见的例子:
Content-Type
:默认情况下,Axios 会将Content-Type
设置为application/json
,这是一个常见的自定义请求头。当你发送 JSON 数据时,浏览器会认为这个请求是复杂请求,需要发送预检请求。
Authorization
:如果请求中包含了Authorization
头,这会使请求变得复杂,浏览器会触发预检请求。跨域请求时的凭证:如果请求设置了
withCredentials: true
(允许跨域请求携带 cookie 或其他凭证信息),也可能导致浏览器将请求视为复杂请求。
服务器代理
略
前端Nginx代理
略
JSONP
Jsonp是最早的跨域解决方案,利用script标签可以跨域的原理实现。
缺点是只能发起GET请求
原理:
Jsonp其实就是一个跨域解决方案。跨域请求数据是不可以的,但是跨域请求js脚本是可以的。可以把数据封装成一个js语句,做一个方法的调用。跨域请求js脚本可以得到此脚本。得到js脚本之后会立即执行。可以把数据做为参数传递到方法中。就可以获得数据。从而解决跨域问题。
比如用<script>标签链接了一个callback函数,服务器返回JSON数据并把数据作为函数的参数传递进去,页面执行callback函数将数据作为参数来处理。<script type="text/javascript">function callback(data){// other code here}var myScript = document.createElement("script");myScript.src = "http://www.server.com/data.json?jsonp=callback";document.body.appendChild(myScript); </script>