跨域的理解和解决

目录

一、同源策略

二、跨域

解决方式有以下几种:

方法一.在后端定义一个工具类CorsConfig

方法二. @CrossOrigin 注解

方法三  使用Spring Security的WebSecurityConfigurerAdapter配置跨域请求:

 方法四:实现 WebMvcConfigurer

方法五,使用nginx:


先说说自己的理解吧,感谢wudumengyan同学的解惑,

        http://     www.xxx.com     :8080

       当浏览一个网页http:// www.xxx.com:8080/index时,例如点击了一个按钮,该网页发一个请求,只要该请求的地址与上面网址三个有一个不对应(协议、域名、端口号),那就是跨域了,这不是网站的问题,也不是项目的问题,而是浏览器的问题,浏览器的同源策略阻止访问。同源策略,其实就是 协议主机端口都相同的,才可以互相访问。
        再来说 这个跨域请求是在哪个阶段被拦截了呢?
        1.A客户端 发出请求,
        2.B服务端 收到请求,
        3.B服务端返回响应信息,
        4.A收到相应信息。

        答案是3 到4之间,A的请求是能正常的发出去的,B服务端后端也正常的响应了, B服务端返回响应信息之后,浏览器是把响应给拦截了。 

       一般出现在什么地方呢?比如我们前后端分离项目中,前端端口是8088,后端端口是8089 ,访问前端页面的时候发请求到后端就会跨域,还有我们浏览csdn,突然有个广告点了一下跳到了京东页面,也算跨域。

下面是转载的同源策略和跨域的专业解释什么是跨域以及如何解决?通俗易懂带你彻底搞定 - 知乎

一、同源策略

 同源策略是一个重要的安全策略,它用于限制一个Origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

Origin:指web文档的来源,Web 内容的来源取决于访问的URL的方案 (协议)主机 (域名) 端口定义。只有当方案,主机和端口都匹配时,两个对象具有相同的起源。

图片

二、跨域

关于URL是否同源,根据上图中的①②③进行判断即可,只要有一点不同,就达到跨域的条件。顺带一提,即便是向域名对应的ip进行资源请求,仍然会跨域。

IE的特殊性:Internet Explorer 的同源策略有两点差异,一是IE未将端口号纳入同源策略的检查,其次是两个高度互信的域名也不受同源策略的检查。

常见的跨域情景:

图片

浏览器内常见的跨域报错:

图片

跨域出现的场景:

一般常见于开发阶段,本地启动项目后,当前页面域名和后台服务器域名不相同,导致跨域。在项目上线后,会通过统一域名、后端配置域名白名单等方式避免跨域。



跨域问题的本质 ,就是浏览器拦截了响应,所以后端只需要在响应头中添加相应的字段,就可以解决跨域问题

解决方式有以下几种:

方法一.在后端定义一个工具类CorsConfig
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 CorsConfig {
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
            corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
            corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
            corsConfiguration.setMaxAge(1800L);
            source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
            return new CorsFilter(source);
        }
    }
方法二. @CrossOrigin 注解

在controller上加上@CrossOrigin 注解或者@CrossOrigin(origins = “http://localhost:8081”),优点是粒度更细,某URL是否跨域可以分开配置,缺点是,如果整个项目都要跨域,则每个controller都需要添加注解

  1. CorsFilter过滤器:在Spring Boot中可以通过自定义一个CorsFilter过滤器来配置跨域请求。在该过滤器中设置允许的请求源(Access-Control-Allow-Origin)、允许的请求方法(Access-Control-Allow-Methods)和允许的请求头部(Access-Control-Allow-Headers)等信息。‘

  2. @CrossOrigin注解:在Spring Boot的Controller层的具体方法上添加@CrossOrigin注解,用于指定允许跨域请求的来源、方法和头部信息。

@RestController
    @RequestMapping(path = "/user")
    @CrossOrigin  // 解决跨域问题
    public class UserController {
        //......
    }
方法三  使用Spring Security的WebSecurityConfigurerAdapter配置跨域请求:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors(); // 启用跨域配置
        // 其他安全配置...
    }
}
 方法四:实现 WebMvcConfigurer
  1. @Configuration
    @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
    public class AppConfig implements WebMvcConfigurer {
     
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")  // 拦截所有的请求
                    .allowedOrigins("http://www.abc.com")  // 可跨域的域名,可以为 *
                    .allowCredentials(true)
                    .allowedMethods("*")   // 允许跨域的方法,可以单独配置
                    .allowedHeaders("*");  // 允许跨域的请求头,可以单独配置
        }
    }
     
    方法五,使用nginx:
@Configuration
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
public class AppConfig implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // 拦截所有的请求
                .allowedOrigins("http://www.abc.com")  // 可跨域的域名,可以为 *
                .allowCredentials(true)
                .allowedMethods("*")   // 允许跨域的方法,可以单独配置
                .allowedHeaders("*");  // 允许跨域的请求头,可以单独配置
    }
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值