Http跨域和处理方案

1 跨域出现的原因

​ 跨域问题是由于浏览器的同源策略引起的。同源策略是一种安全机制,它限制了一个网页中的脚本只能访问与该网页具有相同协议、域名和端口的资源。如果一个请求的目标资源的协议、域名或端口与当前页面的不同,就会触发跨域请求。跨域问题的出现,一方面是为了保护用户的隐私和数据安全,防止恶意网站通过脚本获取或篡改用户在其他网站上的数据。另一方面,它也有助于确保各个网站之间的安全性,防止恶意网站利用其他网站的资源或执行恶意操作。但是有时候,我们确实需要进行跨域请求,比如在前端开发中使用 Ajax 请求获取其他域名下的数据。为了解决这个问题,出现了一些跨域解决方案,如 JSONP、CORS(跨域资源共享)、服务器代理等。这些解决方案可以使跨域请求变得可行,同时保证了安全

2 同源策略

  • 同源策略是浏览器用来约束数据请求的安全机制。同源策略要求:发起请求方和被请求方必须同协议、同域名、同端口,只要有一个不同,且被请求方没有设置CORS策略,那么本次请求会被认为跨域。

    • 协议:http 和 https
    • 域名:www.baidu.com 和 baike.baidu.com
    • 端口::8080 和 :8081

需要注意的是,当在跨域 (Cross-Origin) 场景中发送简单请求时,浏览器会使用 CORS (Cross-Origin Resource Sharing) 机制来验证是否允许跨域请求。服务器必须在响应中包含适当的 CORS 标头来授权浏览器进行请求。

3 请求类型

1 简单请求

在Web开发中,HTTP (Hypertext Transfer Protocol) 是一种用于在客户端和服务器之间传输数据的协议。简单请求 (Simple Request) 是其中一种HTTP请求类型。

简单请求是指符合以下条件的请求:

使用以下HTTP方法之一:GET、HEAD、POST。
使用除了自定义标头之外的标准标头。
不发送异步请求,如XMLHttpRequest的withCredentials标志设置为true。
不使用流式传输(Streamed)。
请求的内容类型(Content-Type)为以下之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain
简单请求的特点是在发送请求时,浏览器不会发送额外的预检请求(Preflight request)来验证服务器是否允许该请求。相反,浏览器直接发送请求并等待服务器的响应。

需要注意的是,当在跨域 (Cross-Origin) 场景中发送简单请求时,浏览器会使用 CORS (Cross-Origin Resource Sharing) 机制来验证是否允许跨域请求。服务器必须在响应中包含适当的 CORS 标头来授权浏览器进行跨域请求。

2 预检请求

预检请求(Preflight Request)是在某些跨域请求场景下,由浏览器自动发送的一种HTTP OPTIONS请求。预检请求用于在发送实际请求之前,询问服务器是否允许实际请求的跨域访问。

当发起跨域请求并满足以下条件之一时,浏览器会发送预检请求:

使用非简单请求(非简单请求的条件见前一个回答)。
在发送请求时,使用了自定义的标头(例如,使用了不在允许标准标头列表中的标头)。
预检请求的目的是让服务器告知浏览器,是否允许实际的跨域请求。预检请求中的OPTIONS请求会带有额外的头部字段,如Access-Control-Request-Method(指定实际请求使用的HTTP方法)和Access-Control-Request-Headers(指定实际请求中包含的自定义标头)。

服务器接收到预检请求后,会检查请求头部的信息,并在响应中包含适当的CORS头部字段,以指示是否允许实际请求。响应中的CORS头部字段包括:

Access-Control-Allow-Origin:指定允许跨域访问的源。
Access-Control-Allow-Methods:指定允许使用的HTTP方法。
Access-Control-Allow-Headers:指定允许使用的自定义标头。
Access-Control-Max-Age:指定预检结果的缓存时间(以秒为单位)。
只有在服务器返回允许跨域请求的CORS头部字段时,浏览器才会发送实际的请求,否则将不会发送实际请求,并且JavaScript代码无法访问响应数据。

4 如何处理跨域问题

思路就是修改响应头,将响应头中添加浏览器所要求的数据,进而实现跨域

1 全局处理

重写WebMvcConfigurer

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //放行哪些原始域
                .allowedOriginPatterns("*")
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

设置新的 CorsFilter

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1. 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        config.addAllowedOrigin("*");
        //是否发送 Cookie
        config.setAllowCredentials(true);
        //放行哪些请求方式
        config.addAllowedMethod("*");
        //放行哪些原始请求头部信息
        config.addAllowedHeader("*");
        //暴露哪些头部信息
        config.addExposedHeader("*");
        //2. 添加映射路径
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**",config);
        //3. 返回新的CorsFilter
        return new CorsFilter(corsConfigurationSource);
    }
}

2 局部处理

注解

@RestController
@CrossOrigin(origins = "*")
public class TransferController {
    @RequestMapping("/addRecycleList")
    public Result<String> addRecycleList({
       // todo
    }
}

手动设置

    @RequestMapping("/addRecycleList")
    @CrossOrigin(origins = "*")
     //@CrossOrigin(value = "http://localhost:8081") //指定具体ip允许跨域
     public Result<String> addRecycleList({
       // todo
    }

springBoot处理

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值