跨域问题是一个很常见的问题,经常在前后端对接时发生,因此我们可以从前端和后端两个方向了解一下跨域以及其解决办法。
什么是跨域?
跨域本质是浏览器基于同源策略 的一种安全手段。同源策略(Sameoriginpolicy),是一种约定,它是浏览器最核心也最基本的安全功能。同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据 。可以理解为网站与网站之间的防火墙。
所谓同源(即指在同一个域)具有以下三个相同点:
- 协议相同(protocol)下图1号
- 主机相同(host) 下图2+3+4号
- 端口相同(port)一般在下图的4号后面并用冒号表示
反之非同源请求,也就是协议、端口、主机其中一项不相同 的时候,这时候就会产生跨域。
推荐的跨域方案
前端 | 后端 | |
---|---|---|
开发环境 | proxy | cors |
生产环境 | nginx |
proxy
在项目的 vue.config.js 文件中,可以在devServer中配置代理。
target:你请求的第三方接口
changeOrigin:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请 求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
pathRewrite:替换target中的请求地址,也就是说以后你在请求 http://localhost:8081/api/customer/list这个地址的时候直接写成/api即可
css
module.exports = {
...
devServer: {
proxy: {
'/api': {
target: 'https://your-api-server.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
我们在封装的http请求文件中使用全局变量保存基本的请求路径,并且将路径保存在env命名的文件种。这样做的好处是,webpack会根据项目启动环境的不同而找到实际发起代理请求的地址。
注意是否会存在影响接口请求的文件,例如mock文件,如果存在请先注释。
nginx
通过配置nginx实现代理
nginx的原理与proxy相同,都是代理转发,仅仅在于属性名字不相同的区别。
我们可以了解一些常见属性。
nginx 属性 | 解释 |
---|---|
listen | 监听的端口号 |
server_name | 指定服务器名称 |
location /xxx | 代理转发的路由地址写在此处 |
ini
server {
listen 80;
# server_name xxx.xxx.com;
location / {
root /var/www/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8088;
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;
}
}
cors
cors 本质上是在请求中增加一些 HTTP 头。
通过在服务端增加一个特殊的 Header 来告诉客户端跨域的限制,如果浏览器支持 CORS 、并且判断 Origin 通过的话,就会允许 XMLHttpRequest 发起跨域请求。我们可以了解一下 Header 的属性。
CORS Header属性 | 解释 |
---|---|
Access-Controll-Allow-Origin | 允许访问的请求源 |
Access-Controll-Allow-Methods | 允许访问的方法 |
Access-Controll-Max-Age | 在 xx 秒 内不再发预检校验请求 |
Access-Control-Allow-Credentials | 是否允许访问 Cookies |
Access-Control-Allow-Headers | 是否允许请求包含 content-type |
我们以 java 为例,增加一个 CrossOriginConfig 配置类。下面这段话的意思是允许所有来源对其进行访问。
scala
public class CrossOriginConfig extends WebMvcConfigurerAdapter {
static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS).maxAge(3600);
}
}
总结
跨域方式千千万,不如熟记其中一两式,其实跨域问题真的不是一个很难解决的问题,多尝试几次即可。
👀最后
如果我的文章能帮到大家,希望大家能动动小指头给我个点赞吧谢谢~💐💖