参考如下博客,自己小小总结了下跨域的一些问题:
什么是跨域
浏览器为什么要设计同源策略
什么是跨域?如何解决
跨域的概念
一个域下的文档或者脚本(比如ajax) 去请求另外一个域的资源。
这里判断是否在一个域的,依据三点: 协议(http|https) + 域名 + 端口 ,如果中间 有任一个不同,那么就算是跨域请求。
注意: 如果两个域名指向同一个ip ,那也算是跨域请求!
我们来看下面的页面是否与 http://store.company.com/dir/index.html 是同源的?
http://store.company.com/dir/index2.html 同源
http://store.company.com/dir2/index3.html 同源 虽然在不同文件夹下
https://store.company.com/secure.html 不同源 不同的协议(https)
http://store.company.com:81/dir/index.html 不同源 不同的端口(81)
http://news.company.com/dir/other.html 不同源 不同的域名(news)
跨域的原由
主要是因为浏览器的设定了同源策略(SOP)。
不同的域下存着不同的数据,例如cookie 等,发送同域的请求,cookie 会自动携带上,如果是不同域的请求,因为有了同源策略,那么cookie 是无法携带的 且 发送不同域的请求也是被拦下来的。
思考一下,如果没有SOP ,当请求到跨域的网站时,那个网站就能获取到源网站的一些cookie 信息了,要知道 cookie 里有时候存储的都是用户信息,比如sessionId , 若对方网站是一个恶意网站,很轻松地就能获取到你的sessionId ,然后进行连接攻击了。
注意: 一些加载图片、js、css等资源是不违背同源策略的,比如 http://phone.happy.com 里需要展示 http://img.happy.com/xxx.png 是可行的。如果是访问接口 , 就可能违背。
跨域的实际例子
一个APP应用开发,前端使用H5 做页面 , 后端提供APP的接口 即可。2个项目都部署到同一台服务器上,分配不同域名,并且都部署到nginx上。
前端 | 后端 | |
---|---|---|
域名 | http://phone.happy.com | http://api.happy.com |
前端项目请求后端接口时,从http://phone.happy.com 访问http://api.happy.com的时候,就是一个跨域请求,一般在浏览器F12模式下,可以看到类似类似类似下图的错误日志:
那么如何解决这种问题呢?请耐心地看下文。
解决跨域的办法
网上也有很多解决办法,是从前端着手的。额,我自己的解决办法就是通过Nginx的代理。当Nginx 接收到前端需要请求后端接口时,将前端请求转到后端接口服务上即可。
需要注意的是,在我的后端接口项目的context-path 我设定的是 /happyapi (/+项目名+api),尽量和 前端 里的一些路由不要冲突吧。
实战
主要就是在nginx上配置下就好了
。。。省略
http{
#上游服务器-接口项目
upstream happyapi{
server localhost:9099 weight=1 max_fails=1 fail_timeout=3s;
}
#接口项目
server{
listen 80; #服务端口号,也就是nginx的port
server_name api.happy.com; #服务器的域名
location /{
proxy_pass http://happyapi; #转到上游服务器
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
。。。省略
}
}
#前端H5项目
server{
listen 80;
server_name phone.happy.com;
#h5项目
location /{
root /usr/local/happy/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
#h5项目里的字体格式
location ~* /.(eot|ttf|ttc|otf|eot|woff|woff2|svg)$ {
root /usr/local/happy/dist;
}
#拦截到api的请求,代理转发到接口项目
location /happyapi/{
proxy_pass http://happyapi; #对应upstream
}
}
}
核心内容:
#拦截到api的请求,代理转发到接口项目
location /happyapi/{
proxy_pass http://happyapi; #对应upstream
}
所以如果前端发送 http://phone.happy.com/happyapi/user/login 的请求时,Nginx 会拦截并转发到 http://api.happy.com/happyapi/user/login 上 ,也就是真正的接口项目了。