针对前后端分离项目(springboot+vue)跨域问题总结

背景

        前端访问后台如果不想走代理模式,则需要在后台进行配置,允许跨域访问,本文对配置过程进行总结。

跨域介绍

        跨域请求指的是在 Web 应用程序中,通过 JavaScript 代码向另一个域名(或端口、协议)发起 AJAX 请求。跨域请求分为简单跨域请求和复杂跨域请求。

简单跨域请求

        如果 AJAX 请求满足以下所有条件,则称其为简单跨域请求:

  • 请求方法只能是 GET、POST 或 HEAD
  • HTTP 请求头限制:只能包含 AcceptAccept-LanguageContent-LanguageContent-Type(仅限于 application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 允许跨域访问的 HTTP 响应头:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma

对于简单跨域请求,浏览器会自动向服务端发送一个额外的 Origin 头信息,用来说明请求来自哪个源(即域名、端口或协议)。服务端可以根据这个头信息来确定是否允许该跨域请求。

复杂跨域请求

        除了简单跨域请求以外的所有跨域 AJAX 请求都被视为复杂跨域请求。简单跨域请求以外的 AJAX 请求,都会先进行一次预检,然后才会真正发出请求。

预检请求使用 OPTIONS 方法,向服务端发送以下信息:

  • Access-Control-Request-Method:请求的方法(比如 GET、POST 等)
  • Access-Control-Request-Headers:请求头信息

服务端需要对这个预检请求进行响应,响应中包含以下信息:

  • Access-Control-Allow-Origin:允许跨域访问的源
  • Access-Control-Allow-Methods:允许使用的 HTTP 方法
  • Access-Control-Allow-Headers:允许包含的 HTTP 请求头
  • Access-Control-Max-Age:预检结果的有效期

只有在收到了正确的预检响应后,浏览器才会发出真正的 AJAX 请求。

解决方式

1、新建配置类CorsConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOrigins("*")
                // 这里:是否允许证书 不再默认开启
                .allowCredentials(true)
                // 设置允许的方法
                .allowedMethods("*")
                // 跨域允许时间
                .maxAge(3600);
    }
}

2、新建过滤器CorsFilter(解决预检错误问题:Response to preflight request doesn't pass access control check: It does not have HTTP ok status.)


import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter(filterName = "corsFilter", urlPatterns = "/*")
public class CorsFilter implements Filter {

    private static final String OPTIONS = "OPTIONS";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Credentials", "true");
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "*");
        res.addHeader("Access-Control-Allow-Headers", "*");
        res.addHeader("Access-Control-Max-Age", "3600");

        // 如果是OPTIONS则结束请求
        if (OPTIONS.equals(((HttpServletRequest) request).getMethod())) {
            response.getWriter().println("ok");
            return;
        }

        chain.doFilter(request, response);
    }
}

猜你喜欢

转载自blog.csdn.net/wangluoxiehui/article/details/130848914