跨域问题产生的前提条件
- 必须要有浏览器,没有浏览器,是不存在跨域问题。
- 浏览器为了安全问题,限制了跨域访问,不允许跨域请求资源。
跨域
- 浏览器从一个域名的网页去请求另一个域名的资源,域名、端口、协议有任何一个不同,都被当作是不同的域,都是跨域。
- 跨域是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
- 域名不同:
- 主域名不同:http://www.baidu.com/index.html跟http://www.csdn.com/test.js
- 子域名不同:http://www.111.baidu.com/index.html跟http://www.222.baidu.com/test.js
- 域名和域名IP:http://www.baidu.com/index.html跟http://180.179.122.42/test.js
- 协议不同:http://www.baidu.com:8080/index.html跟https://www.baidu.com:8080/test.js
- 端口不同:http://www.baidu.com:8080/index.html跟http://www.baidu.com:8081/test.js
- 注意:
- 如果是端口和协议的不同,造成的跨域问题,前端是无能为力的,只能通过后台解决。
- 在跨域问题上,仅仅是通过URL的首部识别,而不会根据域名对应的IP地址是否相同来判断,因此localhost和127.0.0.1都是指向本机,也属于跨域。
- URL的首部:协议、域名、端口必须匹配。
跨域限制行为
- 无法读取非同源网页的Cookie、LocalStorage和IndexedDB。
- 无法接触非同源网页的DOM。
- 无法向非同源地址发送Ajax请求,可以发送,但是浏览器会拒绝接受响应。
解决跨域问题的方案
添加响应头
例子:http://127.0.0.1:8081请求http://127.0.0.1:8082/user
response.addHeader("Access-Control-Allow-Origin","允许请求该页面资源的地址")
response.addHeader("Access-Control-Allow-Origin","http://127.0.0.1:8081")
- ?原来是发送一个请求,现在会发送两个请求,一个是option类型的预检请求,用于询问服务器是否支持当前页面进行跨域,如果支持,再发送第二个get请求。
- 设置预检请求的时间,在时间范围内,第一次请求,需要发送预检请求,之后不用再发送预检请求,可以直接发送get请求。如果超过了预检请求的时间,则请求时会再次发送两个请求。
response.addHeader("Access-Control-Max-Age","预检请求时间,单位秒")
response.addHeader("Access-Control-Allow-Method","get或者post")
- SpringBoot中可以使用注解,在控制器的方法上添加@CrossOrigin注解。
@CrocsOrigin(origins={"允许请求资源的地址"})
手写Java反向代理
- ?通过一个代理控制器,拦截所有请求该服务器的/aip/**请求,使用RestTemplate,代理到8082服务器,进行访问,将结果响应回请求地址,再响应给前端。
Nginx反向代理
- 在nginx.conf文件中,配置一个反向代理路径,例如所有访问/api的请求,进行代理。
server{
listen 8080;
server_name localhost;
location / {
root html;
index index.html;
}
location /api {
proxy_pass http://127.0.0.1:8082;
}
}
- ?Nginx是一个静态服务器,可以存储静态页面,Nginx中的静态页面请求的是Nginx的地址,请求页面,访问的是Nginx自己的服务器,Nginx服务器再代理到另一个服务器。
Jsonp
- <script src=""></script>标签支持跨域,可以通过<script src="资源地址"></script>进行跨域,拿到返回的结果。
- 只支持Get请求,不支持Post请求。
|