首先,浏览器为何要采用同源策略对跨域请求进行限制?
CSRF(Cross-site request forgery),中文名称:跨站请求伪造。限制跨域是指限制两个网站相互读写对方的数据,合理性显而易见。可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
更多历史背景和实际案例可参照知乎链接:
https://www.zhihu.com/question/26379635
其次,常用解决方案:
前端项目集成nodejs – request模块
本地localhost启动一nodejs服务,添加一路由,代码举例如下:
router.get('/sina', function(req, res, next) {
console.log('req.headers: ', req.headers);
request('http://sina.com', function(error, response, data) {
console.log('error: ', error);
console.log('response: ', response.statusCode);
console.log('typeof(data): ', typeof(data));
console.log('data: ', data.length);
res.send({body: 'body'})
})
})
此场景下,http://sina.com是可以被成功访问的。个人理解就是此处是从一本地服务器访问sina.com
,相当于规避掉了浏览器的跨域访问限制。且前端项目集成了nodejs后,可在nodejs中去管理维护后端接口的调用,同时可在Linux服务器上采用PM2工具,单独部署项目。
被调用方 – NGINX解决方案
虚拟主机:多个域名指向同一个服务器,服务器根据不同域名,将请求转向不同应用服务器,看上去好像有多个主机,实际上只有一个主机。
先进行被调用方虚拟主机的配置:
先进行host的配置:
打开windows下的hosts文件,编辑,先映射一个本地域名:
127.0.0.1 b.com
用b.com表示被调用方的域名。
然后打开nginx下的conf目录,新建vhost文件夹,用于存放虚拟主机的配置文件,实际工作中一般就采用这种习惯;打开nginx.conf文件,在最后一行添加代码
include vhost/*.conf;
要nginx载入这个目录下面所有.conf结尾的文件。
在vhost中新建b.com.conf文件,用nginx的语法在其中增加一节点:
作用是,将所有请求转到localhost:8080,监听80端口,命名为b.com。
在nginx-1.11.5目录下打开命令行窗口:
先运行nginx.exe -t
,测试一下配置文件,测试成功后运行start nginx.exe
启动nginx,启动成功后进行测试:
将原来的访问url开头的localhost:8080改为b.com,运行后若依然能正常访问,代表测试成功,说明虚拟主机配置完成了。
因为这次是要在nginx上实现filter的功能,则先将原来的后台服务端的filter功能删除掉,
将注册filter的配置注释掉:
将下面的逻辑移到nginx中:
其中3个为固定值,另外两个由请求的头来决定,
改为:
将预检命令的逻辑处理也添加其中,在nginx中直接返回,就不需要转到应用服务器了。
运行nginx.exe -t
,测试一下配置文件。
运行nginx.exe -s reload
对nginx进行重新载入。
原来html中base url是通过localhost:8080直接访问的被调用方的应用服务器,现在将localhost:8080改为b.com,即变成了html中去访问被调用方的nginx http服务器了。
发送的cookie是被调用方的域名的cookie。在b.com下添加document.cookie='cookie1=xxx'
。
被调用方 – apache解决方案
先运行nginx.exe -s stop
将nginx停止掉,然后刷新b.com的请求,请求失败,说明nginx被停掉了。接下来进行apache的配置:
与nginx一样,我们先进行虚拟主机的配置,进入Apache24/conf目录下,打开httpd.conf文件,
先打开虚拟主机的相关配置,搜索vhost,将LoadModule...mod_vhost_alias.so
注释打开,
将配置文件Include conf/extra/httpd-vhosts.conf
注释也打开,保存httpd.conf。
找到对应的虚拟主机配置文件,即conf/extra/httpd-vhosts.conf
,打开,文件中的每一个节点就是一个虚拟主机,将最后一个节点的代码复制一份并添加到最后,删掉无用的前两行,ServerName改为b.com,日志改为b.com-error.log...
。在最后一行增加一个代理,让它把我们的请求转发过去,
ProxyPass / http://localhost:8080/
然后将此配置文件保存。因为此处使用了Proxy模块,所以需将文件中Proxy模块也打开,搜一下,将140行
LoadModule proxy_module modules/mod_proxy.so
打开,还需要把149行的
LoadModule proxy_http_module modules/mod_proxy_http.so
打开,保存文件。
键入Apache/bin目录,双击httpd.exe,弹出窗口,Apache启动成功,刷新下b.com的请求,此时b.com可正常访问了,表示虚拟主机配置成功了。
来测试一下,刷新下测试用例,看到为全部失败,接下来需要在Apache上配置下响应头,
增加支持跨域的响应头:
继续编辑httpd-vhosts.conf文件,在ProxyPass下增加代码:
Apache的配置比较复杂:
需要将httpd.conf中Headers和Rewrite模块打开:
搜索headers,将118行打开
LoadModule headers_module modules/mod_headers.so
搜索rewrite,将158行打开
LoadModule rewrite_module modules/mod_rewrite.so
保存修改后的两个文件。
将Apache关掉,双击重启,刷新测试用例,此时测试用例全部成功,表示此时的Apache支持跨域了,Apache的配置到此结束。
被调用方 – Spring框架解决方案
之前的方案都和框架无关,比如filter,是每个web应用都有的。如果采用了Spring框架,那么解决方案就变得简单起来,增加相应注解即可,请求也不需要再经过中间的http服务器了。
所以,首先将html中的base url b.com改回为localhost:8080,修改服务器后台代码,在TestController中增加注解,
@CrossOrogin
public class TestController {
保存,
再次刷新测试用例,可以看到,测试用例全部通过。
@CrossOrogin
可以加在类上面,也可以加在具体的方法上面。加在类上即代表此类的所有方法都支持跨域;它还可以进行一些额外的配置,但一般场景是不需要额外配置的。
调用方解决跨域 – 隐藏跨域 – nginx配置
当你无法修改被调用方的时候,就要在调用方做文章。请求是经由调用方的http服务器的反向代理,转发到被调用方的服务器的,在浏览器上面,看不到任何的跨域请求。
那么,什么是反向代理呢?
简单来说,就是你访问同一个域名的两个不同url,它们最后会去到两个不同的服务器,我们通过接下来的测试来理解这个概念:
先看一下反向代理在nginx上是怎样配置的:
配置之前,先把测试环境还原成不支持跨域调用,
把注解@CrossOrigin
删除掉:
接下来,在
C:\Windows\System32\drivers\etc\hosts
文件中增加一个host,
将原127.0.0.1 b.com改为
127.0.0.1 b.com a.com
用a.com表示调用方的虚拟主机。
然后,在nginx-1.11.5\conf\vhost中新建配置文件a.com.conf
域名为a.com,将所有请求转发到81端口,
加一个代理,把我们要调用的服务器的地址代理成ajaxserver
将html中的base url改为/ajaxserver
。
运行start nginx.exe
启动nginx
运行nginx -s reload
重新加载配置,访问a.com,可以看到3个成功,但getCookie失败了,
是因为新的域名里没有cookie的信息,在a.com下添加document.cookie="cookie1=xxx"
再次刷新,测试用例全部成功,跨域问题得到了解决。
看一下这种隐藏跨域与之前的支持跨域最大不同是什么?
就是我们调用的base url。
隐藏跨域下面调用的url都是本域的,所以base url处为相对地址,
而之前支持跨域里面,base url处写的必须是绝对地址,这就是最大的不同。
浏览器看到都是相对地址,都是同一个域的地址,所以不会有任何跨域问题。
调用方解决跨域 – 隐藏跨域 – Apache配置
Apache反向代理配置:
配置的目的就是增加一个虚拟主机,在虚拟主机中把跨域请求做一个代理,
找到Apache的虚拟主机配置文件conf/extra/httpd-vhosts.conf
增加一个节点:
将base url改为ajaxserverapache
,
保存。将nginx.exe -s stop
停掉,启动Apache服务,
运行a.com,测试成功,
且发现Request URL为http://a.com/ajaxserverapache/getCookie
Apache反向代理配置完成。
注:以上文章部分整理自慕课网教学视频:
https://www.imooc.com/video/16591
https://www.imooc.com/video/16592
今天的文章前端跨域问题总结分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18170.html