Java跨域问题

目录

1、跨域问题说明

​2、跨域解决方案

2.1、局部跨域解决方案

2.1.1、@CrossOrigin注解跨域

2.1.2、手动设置响应头

2.2、全局跨域解决方案

2.2.1、实现WebMvcConfigurer接口设置跨域

2.2.2、定义CorsFilter Bean实现跨域

2.2.3、重写ResponseBodyAdvice接口中的beforeBodyWrite方法实现跨域

2.2.4、nginx配置跨域(nginx.conf)

3、跨域常见异常问题

3.1、No 'Access-Control-Allow-Origin' header is present on the requested resource

3.2、header contains multiple values 'XXX, *', but only one is allowed


1、跨域问题说明

  • 同源:两个页面具有相同的协议、域名和端口。
  • 跨域:当一个请求url的协议、域名或端口之中任意一个与当前页面url不同。
  • 跨域产生原因:浏览器设置了同源策略,当页面执行脚本的时候,浏览器会检查访问的资源是否同源,如果不是,就会报错。

举例说明:


2、跨域解决方案

        通过在响应头中设置Access-Control-Allow-Origin,表示允许跨域访问的原始域名,告诉浏览器这是一个安全请求,即可解决跨域问题。

        当设置Access-Control-Allow-Origin = * 时,表示允许所有站点跨域访问。

2.1、局部跨域解决方案

2.1.1、@CrossOrigin注解跨域

该注解可以修饰类和方法。设置简单,但需要为所有类或方法都加上注解。

@RestController
@CrossOrigin(origins = "*")
public class TestController {
    @RequestMapping("/test")
    public String test() {
        return "测试@CrossOrigin解决跨域问题";
    }
}

2.1.2、手动设置响应头

        方法级别的跨域。

@RestController
public class TestController {
    @RequestMapping("/test")
    public String test(HttpServletResponse response) {
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Max-Age", "10");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        
        return "测试手动设置响应头解决跨域问题";
    }
}

2.2、全局跨域解决方案

2.2.1、实现WebMvcConfigurer接口设置跨域

        通过实现WebMvcConfigurer接口里的addCorsMappings方法设置跨域。

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")             // 匹配所有接口
                .allowCredentials(true)     // 是否发送 Cookie
                .allowedOriginPatterns("*") // 支持域
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) // 支持方法
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

2.2.2、定义CorsFilter Bean实现跨域

@Configuration
public class MyCorsFilter {
    @Bean
    public CorsFilter corsFilter() {
        // 1.创建 CORS 配置对象
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*");                // 支持域
        config.setAllowCredentials(true);                    // 是否发送 Cookie
        config.addAllowedMethod("*");                        // 支持请求方式
        config.addAllowedHeader("*");                        // 允许的原始请求头部信息
        config.addExposedHeader("*");                        // 暴露的头部信息
        
        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        
        // 3.返回 CorsFilter 对象
        return new CorsFilter(corsConfigurationSource);
    }
}

2.2.3、重写ResponseBodyAdvice接口中的beforeBodyWrite方法实现跨域

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * 是否重写响应内容
     * 返回 true 表示重写
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
    /**
     * 方法返回之前调用此方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 设置跨域
        response.getHeaders().set("Access-Control-Allow-Origin", "*");
        return body;
    }
}

2.2.4、nginx配置跨域(nginx.conf)

        nginx在获取下游响应后,在响应头中加上如下配置:

add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Credentials 'true' always;
add_header Access-Control-Allow-Headers * always;
add_header Access-Control-Allow-Methods 'PUT, GET, POST, DELETE, OPTIONS' always;
if ($request_method = 'OPTIONS') {
    return 204;
}

3、跨域常见异常问题

3.1、No 'Access-Control-Allow-Origin' header is present on the requested resource

        XXXX from origin XXXX has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

  • 原因:响应结果未增加Access-Control-Allow-Origin头。
  • 解决方案:后端解决方案可参照《2、跨域解决方案》。

3.2、header contains multiple values 'XXX, *', but only one is allowed

        The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:8080, *', but only one is allowed. Origin 'http://localhost:8080' is therefore not allowed access.

  • 原因:跨域重复设置,比如在nginx设置了跨域,又在业务服务中设置了跨域,最后的响应中就会有多个Access-Control-Allow-Origin值。
  • 解决方案:请求全流程保证只进行一次跨域设置即可。

以上内容为个人学习理解,如有问题,欢迎在评论区指出。

部分内容截取自网络,如有侵权,联系作者删除。

你可能感兴趣的:(Java基础,java)