Bootstrap

前后端跨域问题解决方案

 前后端跨域问题由浏览器同源策略而来,出现了跨域问题,实际上,请求是可以到达后端控制器内部的,浏览器会因为同源策略将后端返回的结果屏蔽,并向外说明跨域错误。

解决跨域问题的一些方法(不全,后面遇上不同的解决方法再补上,此文持续更新)

1、后端接口或路由方法上添加@CrossOrigin注解

放后端接口上:

 放单个路由方法上:

2、在路由方法里的响应体中配置响应头:

ps: 想要哪个控制器里的方法跨域,只需将下面代码复制粘贴到该方法里就行

HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.addHeader("Access-Control-Allow-Origin","*");

该方法体现了方法1中 @CrossOrigin 注解能实现跨域的本质( @CrossOrigin 注解在内部也是给响应头配置了上面那个参数,但是配置会更详尽一些)

3、写个配置类实现WebMvcConfigurer类,再重写addCorsMappings方法

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

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .allowedHeaders("*")
                .maxAge(3600);
    }
}

直接写个配置类实现WebMvcConfigurer类,将上面重写的方法复制粘贴进去就行。附上包名全路径,防导错包。

4、通过给spring注入一个CorsFilter (跨域过滤器)的方法实现

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class AA {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        // 有效期 1800秒
        config.setMaxAge(1800L);
        // 添加映射路径,拦截一切请求
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        // 返回新的CorsFilter
        return new CorsFilter(source);
    }

}

直接写个配置类,然后将AA类里的代码直接原封不动复制粘贴进去就行,更多的配置可以自定义。注意上面特意把导入的包名全路径给了出来,因为容易选错了包,则实现不了效果。

5、引言:前面第1、2种方法肯定不是推荐使用的,因为一个项目中的路由方法很多,1、2种方法需要逐个添加,但是可以把第2种方法改良一下。

思路:写一个拦截器,在拦截器里添加方法2中的代码。

注:“拦截器” 通俗理解,起到了一个钩子的作用,好比后端spring的前置通知、前端vue中vue实例的生命周期中谈的几个钩子函数,没前端浏览器发送的所有请求,在进入控制器里的具体代码之前(包括进入路由映射之前),都会先进入这个叫做 “拦截器” 的东西,我们就是要在 “拦截器” 里用方法2,这样免去了每个路由方法手动配置跨域参数的弊端。

您瞧:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 增加一个拦截器,可以对拦截请求做一些自定义处理
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


                //添加这么一条代码
                response.addHeader("Access-Control-Allow-Origin","*");


                System.out.println("拦截请求");
                return true;
            }
        })
                // 设置拦截器的过滤路径规则:/** 代码所有请求都拦下来去执行(重写的preHandle方法里的内容)
                .addPathPatterns("/**")
                // 设置不需要拦截的过滤规则:不拦截/admin/login请求
                .excludePathPatterns("/admin/login");
        
        }
}

这里还有前端配置跨域代理和后端的nginx(反向代理),微服务(配置网关)的方法来解决跨域问题,这里呼应文首的  “文章持续跟新”,遇上了再详细记录。

;