Skip to content

跨域处理

产生原因

跨域产生的原因是由于前端地址与后台接口不是同源,从而导致异步请求发送失败

非同源产生的问题

  1. Cookie、LocalStorage 和 IndexDB 无法获取
  2. DOM 无法获得
  3. AJAX 请求不能发送

同源条件

协议,端口,主机 三者相同即为同源。反之,其中只要 某一个 不一样则为不同源

解决方案

本地开发跨域

本地开发一般使用下面 3 种方式进行处理

  • vite 的 proxy 进行代理
  • 后台开启 cors
  • 使用 nginx 转发请求

生产环境跨域

生产环境一般使用下面 2 种方式进行处理

  • 后台开启 cors
  • 使用 nginx 转发请求

后台开启 cors 不需要前端做任何改动

后台开启cors

java
@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final org.springframework.web.cors.CorsConfiguration config = new org.springframework.web.cors.CorsConfiguration();
    // 允许cookies跨域
    config.setAllowCredentials(true);
    // #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
    config.addAllowedOriginPattern("*");
    // #允许访问的头信息,*表示全部
    config.addAllowedHeader("*");
    // 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
    config.setMaxAge(18000L);
    // 允许提交请求的方法,*表示全部允许
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    // 允许Get的请求类型
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}
java
/**
 * 跨域过滤器
 */
@Component
@Order(-200)
public class CorsFilter implements Filter {

	static final String OPTIONS = "OPTIONS";

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		
		// 允许指定域访问跨域资源
		response.setHeader("Access-Control-Allow-Origin", "*");
		// 允许所有请求方式
		response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
		// 有效时间
		response.setHeader("Access-Control-Max-Age", "3600");
		// 允许的header参数
		response.setHeader("Access-Control-Allow-Headers", "x-requested-with,satoken");

		// 如果是预检请求,直接返回
		if (OPTIONS.equals(request.getMethod())) {
			System.out.println("=======================浏览器发来了OPTIONS预检请求==========");
			response.getWriter().print("");
			return;
		}

		// System.out.println("*********************************过滤器被使用**************************");
		chain.doFilter(req, res);
	}

	@Override
	public void init(FilterConfig filterConfig) {
	}

	@Override
	public void destroy() {
	}

}

使用Nginx转发请求

配置前端项目接口地址

java
# 在.env.production内,配置接口地址
VITE_GLOB_API_URL=/api

在nginx配置请求转发到后台

java
server {
  listen       80;
  server_name  tangyh.top;
  # 接口代理,用于解决跨域问题
  location /api {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # 后台 lamp-gateway-server 接口地址
    proxy_pass http://110.110.1.1:8760/api;
    proxy_redirect default;
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers X-Requested-With;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
  }
}

Last updated:

开发者笔记仓库