https://blog.csdn.net/zhang6622056/article/details/75221492
跨域是网络安全领域的一个专有名词。简单点理解就是某些操作越过了域名的界限,访问了别的域名。如果脚本可以自由访问其他域,就会产生很多安全问题。
什么情况下会跨域? 不同协议、不同域名、不同端口、不同主机。
什么情况不是跨域? 满足域名、协议、端口均相同的即不是跨域。
解决方案:
1、jsonp(不推荐)
最初用来解决跨域问题的方式,叫做JSONP,它的基本原理是:跨域的“资源嵌入”是被浏览器允许的。所以,可以通过一个script标签来嵌入一段来自其他服务器的脚本。由于这个脚本完全运行在当前域,无法访问第三方服务器的cookie等敏感信息,所以是安全的。
JSONP的缺点是它只能支持GET操作,没法支持POST等操作,但是由于兼容性好等优点,仍然有很多网站采用JSONP的方式公开自己的API供第三方调用。
2、反向代理
要想解决跨域问题,最简单彻底的方法当然是把他们拉到一个域下,而这就是该“反向代理”发挥作用的时候了。
所谓反向代理,就是在自己的域名下架设一个Web服务器,这个服务器会把请求转发给第三方服务器,然后把结果返回给客户端。这时候,在客户端看来,自己就是在和这台反向代理服务器打交道,而不知道第三方服务器的存在。
所以,如果有一个Web服务程序,它同时提供了反向代理功能和静态文件服务功能,静态文件服务负责渲染前端页面,反向代理则提供对第三方服务器的透明访问。那么前端和后端就变成了同源的,不再受同源策略的约束。
那么,有这样的Web服务程序吗?有,而且不止一个。事实上,几乎所有的主流Web服务器都提供了反向代理功能。这里仅以nginx为例来示范反向代理的配置方式,其他Web服务器请搜相应的文档自行研究。
server {
listen 80;
server_name your.domain.name;
location / {
proxy_pass http://localhost:5000/; # 把根路径下的请求转发给前端工具链(如gulp)打开的开发服务器,如果是产品环境,则使用root等指令配置为静态文件服务器
}
location /api/ {
proxy_pass http://localhost:8080/service/; # 把 /api 路径下的请求转发给真正的后端服务器
proxy_set_header Host $http_host; # 把host头传过去,后端服务程序将收到your.domain.name,否则收到的是localhost:8080
proxy_cookie_path /api /service; # 把cookie中的path部分从/api替换成/service
proxy_cookie_domain localhost:8080 your.domain.name; # 把cookie的path部分从localhost:8080替换成your.domain.name
}
}
注意最后这两句话,由于cookie中存在一个path机制,可以对同一个域下的不同子域进行区分。所以,如果后端所使用的路径是/service
,而前端使用的路径是/api
,那么前端将不能访问后端的cookie,这就导致登录等操作所写入的cookie无法正常传入传出,其表现则是登录始终没有效果。cookie的domain机制也是类似的原理。
现实中的后端服务器,使用path机制的很多,所以这项设置非常实用。
server {
listen 80;
server_name domain.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location /client { #访问客户端路径
proxy_pass http://localhost:81;
proxy_redirect default;
}
location /apis { #访问服务器路径
rewrite ^/apis/(.*)$ /$1 break;
proxy_pass http://localhost:82;
}
}
3、CORS方式
这是W3C提供的另一种跨域方式。它定义了在跨域访问资源时浏览器和服务器之间如何通信。CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。
作为一项标准的跨域规范,CORS本应该是最值得采用的。 问题在于,老式浏览器不支持CORS,而我们显然还没到可以无视老式浏览器的时候。 所以,只要有可能,就应该优先采用反向代理的方式。
CORS的原理是基于服务方授权的模式,也就是说提供服务的程序要主动通过CORS回应头来声明自己信任哪些源(协议+域名+端口)。 由于得到了服务方的授权,浏览器就可以放行来自这些域的请求了。