跨域

跨域

1.什么是跨域

当一个资源去访问另一个不同域名或者同域名不同端口的资源时,就会发出跨域请求。如果此时另一个资源不允许其进行跨域资源访问,那么访问就会遇到跨域问题。

2.为什么有跨域问题存在

跨域指的是浏览器不能执行其他网站的脚本。是由浏览器的策略造成的,是浏览器对JavaScript施加的安全限制。JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象,即同源政策,

所谓同源:协议相同,域名相同,端口相同

比如:http://www.test.com./index.html

协议是:http://

域名是:www.test.com

端口号是:80(端口可以省略)

它的同源情况如下:

http://www.test.com/manager.html 同源

https://www.test.com/manager.html 不同源

http://www.test1.com/manager.html 不同源

http://www.test.com:81/manager.html 不同源

3.同源政策目的

同源政策目的是为了保护用户信息的安全,防止恶意的网站盗取数据。

4.非同源的限制范围

随着互联网的发展,同源政策越来越严格,如果非同源,一共会有三种行为受到限制

  1. Cookie、LocalStorage、IndexDB无法获取
  2. DOM无法获得
  3. Ajax请求不能获取

5.跨域问题解决方案

CORS

CORS是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

CORS方案,就是通过服务器设置响应头来实现跨域

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

只要同时满足以下条件,就属于简单请求,一般来说,只需要满足前两个即可

  • 请求方法是如下三种方法之一:GET、POST、HEAD
  • HTTP消息头不超过如下几个字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

非简单请求就是简单请求之外的所有请求

CORS字段介绍:
(1)Access-Control-Allow-Methods

该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

(2)Access-Control-Allow-Headers

如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

(3)Access-Control-Allow-Credentials

该字段与简单请求时的含义相同。

(4)Access-Control-Max-Age

该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

在这里插入图片描述

方法一、直接采用SpringBoot的注解@CrossOrigin(也支持SpringMVC)

简单粗暴的方式,Controller层在需要跨域的类或者方法上加上该注解即可


@RestController
@CrossOrigin
@RequestMapping("/")
public class test{
 
    @Autowired
    private SituationService situationService;
    // log日志信息
    private static Logger LOGGER = Logger.getLogger(SituationController.class);

}


方法二、处理跨域请求的Configuration

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("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

当你在项目中使用了该方法配置跨域问题后,再使用自定义的拦截器时,跨域问题的相关配置就会失效,请求依然会报跨域问题的错。

原因是客户端请求经过的先后顺序问题,当服务端接收到一个请求时,该请求会先经过过滤器,然后进入拦截器中,然后再进入Mapping映射中的路径所指向的资源,所以跨域配置在mapping上并不起作用,返回的头信息中并没有配置的跨域信息,浏览器就会报跨域异常。
正确的解决跨域问题的方法时使用CorsFilter过滤器CorsFilter

方法三、采用过滤器(filter)的方式

@Bean
    public CorsFilter corsFilter() {
        // 1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        // 放行哪些原始域
        config.addAllowedOriginPattern("*");
        // 是否发送Cookie信息
        config.setAllowCredentials(true);
        // 放行哪些原始域(请求方式)
        config.addAllowedMethod("*");
        // 放行哪些原始域(头部信息)
        config.addAllowedHeader("*");
        // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
        config.addExposedHeader("*");
        //时间
        config.setMaxAge(3600L);
        // 2.添加映射路径导入配置
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        // 3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
posted @ 2022-08-13 15:04  blakee  阅读(65)  评论(0编辑  收藏  举报