跨域问题详解

详解跨域问题

1. 什么是跨域问题?

  • 跨域问题是指在Web开发中,当一个网页尝试请求另一个域 (不同的协议、域名、或端口)的资源时,由于浏览器的同源策略限制,这些请求会被阻止。
  • 源是什么意思?何为同源 ?
  • Web内容的源由用于访问它的URL 的协议域名端口
  • 同源不同源一句话就可以判断:就是url中 prtocol host port 都相同即为同源。
  • 跨域问题的产生 ?
    • 先做一个约定, 你的前端项目部署在 (http://AAA.com)上,你的后端项目部署在(http://BBB.com)上,并且你没有做任何跨域的配置。
      • 首先, 你在浏览器访问 http://AAA.com,前端服务器会将响应的页面返回,浏览器将之渲染绘制,得到页面。
      • 如果,在返回的页面中,有一张图片资源,它的url地址是 http://BBB.com/1.jpg,那么此时这张图片的加载就产生了跨域问题。
      • 再者,如果你要点击某个按钮加载一些数据,提交的url是 https://BBB/com/list,那么这也会产生跨域问题。
      • 原因: 身在 http://AAA.com 却想随意访问 http://BBB.com上面的内容,而不经过允许这是不合理的。

举个例子:

http://AAA.com 比喻成你的房间,将 http://BBB.com比作 你父母的房间。你可以随意使用自己房间里的东西,但是你可以随意使用你父母房间里的东西吗?

###2. 何为预检请求 ? ###

  • 预检请求是由浏览器自动发送的一种HTTP OPTIONS请求,它通常用于在发送实际请求之前,询问服务器是否允许实际请求的跨域访问。
  • 预检请求与跨域问题息息相关。很多时候,你可以利用预检请求,调试你的跨域配置。

大致请求流程图如下:

image-20241110211609018


3 .解决方法

  • 通常解决思路有两种:

    • 直接将前端服务和后端服务的协议、域名、端口配置成一样。根据跨域问题的定义,这样就不会产生跨域。
    • 配置前端服务器(例如Nginx)支持跨域,配置后端代码支持跨域。
  • 从前端解决 (Nginx)

    • 在nginx配置文件中,通过添加CORS相关的HTTP头部:
      • Access-Control-Allow-Origin: 指定哪些域可以访问资源。可以使用通配符*表示允许任何域,但出于安全考虑,通常指定具体的域名。
      • Access-Control-Allow-Methods: 指定允许的HTTP方法
      • Access-Control-Allow-Headers: 指定允许的自定义请求头部。
      • Access-Control-Allow-Credentials: 指定是否允许发送Cookie。
    • 对于预检请求(OPTIONS请求),Nginx需要返回状态码204 No Content,并在响应中包含必要的CORS头部。这告诉浏览器服务器允许跨域请求。

    修改配置文件:

server {
    listen 80;
    server_name example.com;

    location / {
        # 处理预检请求
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
        }

        # 处理实际请求
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
    }
}

生效配置:

sudo nginx -s reload
  • 从后端解决 (Java SpringBoot)

    • 配置注解 (@CrossOrigin)

      • 对于控制器或者具体的请求处理方法,你可以使用@CrossOrigin注解来允许跨域请求。这种方法比较灵活,可以针对单个控制器或者请求进行配置。

      • import org.springframework.web.bind.annotation.CrossOrigin;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.RestController;
        
        @RestController
        @CrossOrigin(origins = "https://example.com") // 允许指定域的跨域请求
        public class MyController {
            
            @GetMapping("/example")
            public String example() {
                return "Example Response";
            }
        }
        
    • 全局CORS配置 (实现WebMvcConfigurer)

      • import org.springframework.context.annotation.Bean;
        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 WebConfig implements WebMvcConfigurer {
        
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**") // 对所有的URL都生效
                        .allowedOrigins("https://example.com")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                        .allowedHeaders("*")
                        .allowCredentials(true);
            }
        }
        
    • 使用CorsFilter.

      • 可以创建一个CorsFilter Bean来配置CORS。

      •   @Bean
            public CorsFilter corsFilter() {
                CorsConfiguration config = new CorsConfiguration();
                // 设置允许跨域请求的域名
                config.addAllowedOrigin(allowedOrigins);
                // 是否允许证书
                 config.setAllowCredentials(true);
                // 设置允许的方法
                config.addAllowedMethod("*");
                // 允许任何头
                config.addAllowedHeader(allowedHeader);
                UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
                configSource.registerCorsConfiguration("/**", config);
                return new CorsFilter(configSource);
            }
        
    • 与SpringSecurity集成

      • 如果你的应用使用了Spring Security,CORS配置需要与Spring Security集成。可以通过提供CorsConfigurationSource Bean来实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值