跨域访问问题(Cross-Origin Resource Sharing,CORS)是由浏览器的同源策略引起的安全限制。同源策略是一种浏览器安全策略,它要求网页中的所有资源必须来自同一个域名、协议和端口,否则浏览器会阻止跨域的资源请求。

什么时候会出现跨域?

1、域名不同:如从xffjs.com的页面请求baidu.com的资源
2、协议不同:如从Http的页面请求Https的资源
3、端口不同:当页面的端口请求的资源的端口不一致时,同样会触发跨域问题

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

当前页面 被请求页面 是否跨域
http://xffjs.com http://xffjs.com/xxx
http://xffjs.com https://xffjs.com
http://xffjs.com http://a.xffjs.com
http://xffjs.com http://xffjs.com:8080

跨域解决方式

通过Nginx配置解决

# ******解决跨域问题******
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;
add_header Access-Control-Allow-Headers *;

Java使用@CrossOrigin注解

/**
 * 接口测试
 */
@CrossOrigin
@GetMapping("/test")
@ResponseBody
public ApiResult test() {
    return ApiResult.success("请求成功!");
}

没加注解之前:

加上注解之后:

@CrossOrigin可以作用于方法和类上面。

实现WebMvcConfigurer并重写addCorsMappings方法

@Configuration
public class ResourcesConfig implements WebMvcConfigurer {

    /**
     * web跨域访问配置
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOrigins("*")
                // 是否允许证书
                .allowCredentials(true)
                // 设置允许的方法
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间 单位秒
                .maxAge(3600);
    }
}

通过CrosFilter

它是SpringWeb提供的一个处理跨域的过滤器

@Configuration
public class WebMvcConfig {
    @Bean
    FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
        corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
        corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        registrationBean.setFilter(new CorsFilter(source));
        registrationBean.setOrder(-1);    //设置优先级为最高 正常的 0、1等
        return registrationBean;
    }
}

通过JSONP解决

JSONP是利用script标签实现跨域访问,通过动态创建script标签来加载跨域资源,服务器返回一个包含回调函数的JavaScript脚本,客户端通过回调函数处理响应数据。

PS:不过JSONP只支持GET请求,且只能用于跨域请求JSON数据

<!DOCTYPE html>
<html lang="en">

<body>
    <!-- 静态请求 -->
    <!-- <script src="http://127.0.0.1:30/api/getData?cb=callback"></script> -->
    <script>
        // 动态创建script标签
        const script = document.createElement('script')
        // 设置src属性
        script.src = 'http://127.0.0.1:8080/api/getData?cb=callback'
        // 接收后端的回调函数
        function callback(res) {
            console.log(res,'res');
        }
        // 将script挂载到页面上
        document.getElementsByTagName('body')[0].appendChild(script)
    </script>
</body>
</html>