前后端分离导致跨域问题处理


前言

前后端项目分离,项目部署的时候会产生跨域的问题,本文梳理了跨域产生的原因和如何处理跨域问题。


一、跨域是什么?

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

当前页面url被请求页面url是否跨域原因
http://www.test.com/http://www.test.com/index.html同源(协议、域名、端口号相同)
http://www.test.com/https://www.test.com/index.html跨域协议不同(http/https)
http://www.test.com/http://www.baidu.com/跨域主域名不同(test/baidu)
http://www.test.com/http://blog.test.com/跨域子域名不同(www/blog)
http://www.test.com:8080/http://www.test.com:7001/跨域端口号不同(8080/7001)

二、跨域浏览器报错

浏览器报错

三、跨域解决方案

1. 自建项目如何解决跨域

1.1 servlet项目

a. 单个请求处理方案

针对某个servlet里面的doPost或者doGet方法,按照下面的代码,在业务逻辑前面添加。

/* 允许跨域的主机地址 */
response.setHeader("Access-Control-Allow-Origin", "*");  
/* 允许跨域的请求方法GET, POST, HEAD 等 */
response.setHeader("Access-Control-Allow-Methods", "*");  
/* 允许跨域的请求头 */
response.setHeader("Access-Control-Allow-Headers", "*"); 
b. 全部请求处理方案

针对整个项目的全部请求,按照如下操作

1) 定义过滤器接口Filter的实现类,实现类中修改respone的头信息,把 “Access-Control-Allow-Origin” 的域名修改问请求方的域名,如下:
package filter;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
 
 
public class CORSFilter implements Filter {
 
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletResponse response = (HttpServletResponse) res;
		response.setHeader("Access-Control-Allow-Origin", "<请求方域名如:http://www.sohu.com>");
		response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
		response.setHeader("Access-Control-Max-Age", "3600");
		response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
		response.setHeader("Access-Control-Allow-Credentials", "true");
		chain.doFilter(req, res);
	}
 
	public void init(FilterConfig filterConfig) {}
 
	public void destroy() {}
 
}
2) 在web.xml中配置此过滤器:
<filter>
	<filter-name>CORSFilter</filter-name>
	<filter-class>filter.CORSFilter</filter-class>
</filter>

1.2 springboot项目

1.2.1 创建一个filter解决跨域。
@Component

public class SimpleCORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
        chain.doFilter(req, res);
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}
1.2.2 使用@CrossOrigin这个注解在controller类中使用
@CrossOrigin(origins = "http://192.168.1.10:8080", maxAge = 3600)
@RequestMapping("rest_index")
@RestController
public class IndexController{

2. 公司项目如何解决跨域

2.1 uap项目

2.1.1 在main.js中,配置数据所在服务器的前缀(即固定部分),代码如下:
import axios from 'axios'
Vue.prototype.$axios = axios
axios.defaults.baseURL = '/api'  //关键代码

关键代码:axios.defaults.baseURL = ‘/api’,作用是我们每次发送的请求都会带一个/api的前缀。

2.1.2 在config文件夹下的index.js文件中的proxyTable字段中,作如下处理:
dev: {
    env: require('./dev.env'),
    port: 8090,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        target:'http://api.douban.com/v2', // 你请求的第三方接口
        changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
        pathRewrite:{  // 路径重写,
          '^/api': ''  // 替换target中的请求地址,也就是说以后你在请求http://api.douban.com/v2/XXXXX这个地址的时候直接写成/api即可。
        }
      }
    },
    cssSourceMap: false
  }
2.1.3 在具体使用axios的地方,修改url如下即可:
axios.get("/movie/top250").then((res) => {
  res = res.data
  if (res.errno === ERR_OK) {
     this.themeList=res.data;
  }
}).catch((error) => {
  console.warn(error)
})

2.2 基建项目

基建项目采用公司v7平台,底层是 servlet架构,采用上面servlet的解决方案。

2.3 云监理项目

云监理项目属于互联网项目,通过nginx转发的方式实现。

location /hussarApi/ {
    proxy_pass  http://yjl.taimohongcheng.com:9999;
}
   location /wx/ {
    proxy_pass  http://yjl.taimohongcheng.com:9001;
}

2.4 轻骑兵v8

  refer-whitelist:  # 使用前后分离,需要配置前端请求的白名单,防止跨域请求后台,例如前台请求地址为:http://192.168.6.14:8081/ 此处就配置为http://192.168.6.14:8081/
    - http://localhost:8082/
    - http://localhost:8081/
    - http://localhost:8088/
    - http://localhost:8089/
    - http://loaclhost:8082/
    - http://localhost:8080/
    - http://zwyjl.taimohongcheng.com:8080/

总结

以上就是今天要讲的内容,本文仅仅简单介绍了几种比较通用的解决跨域的方法。希望通过本次内容的讲解,能让大家今后对此类问题有一个更加清晰的认识和解决方案。

参考资料

https://blog.csdn.net/wh_xmy/article/details/87705840
https://www.cnblogs.com/diandianquanquan/p/10607102.html
https://blog.csdn.net/wangxin1982314/article/details/50249543
https://www.cnblogs.com/zgrey/p/13972270.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值