处理跨域问题

这里只讨论后端对跨域支持,前端的跨域支持一般都是在测试阶段用用的,跨域还是要后端解决

跨域问题的产生:浏览器的一种安全机制-->同源策略限制

同源策略:URL中包括协议,域名,IP,端口都要完全相同,如果有一项不同,浏览器会觉得有安全风险,不让访问.

前后端分离开发后,这种跨域请求变得突出

W3C 在2014年发布的 RFC 6454 中引入了预检请求的概念,用于在实际请求之前进行预先检查。

浏览器为了支持跨域请求,解决浏览器同源策略出现的问题引入了一种机制---->预检请求

预检请求主要用于确保服务器允许实际请求的发起。服务器在接收到预检请求后,会根据预检请求的信息进行检查,判断是否允许实际请求。如果允许,服务器会在响应头中包含一些 CORS 相关的信息,告诉浏览器可以发送实际请求。这个过程有助于防止恶意网站对其他网站的资源进行滥用。

预见请求就是浏览器自动发出一个查询请求,用来确认目标资源是否支持跨域。

预检请求一定是OPTIONS请求

OPTIONS 请求:

  • 用途: 用于在实际请求之前,向服务器发起一个预检请求,以检查服务器是否支持跨域请求。
  • 特点: OPTIONS 请求通常包含一些头信息,如 OriginAccess-Control-Request-MethodAccess-Control-Request-Headers 等,以询问服务器是否允许实际请求。服务器在收到 OPTIONS 请求后,会检查这些头信息,并决定是否允许实际请求。
  • 例子: CORS(Cross-Origin Resource Sharing)中的预检请求就是 OPTIONS 请求。

那么什么样的请求,会发送预检请求?

浏览器将请求分类为简单请求和非简单请求

对于简单请求和非简单请求的概念

简单请求:

GET,HEAD,POST请求,但是Content-Type必须是'application/x-www.form-urlencoded'或者'multipart/form-data'或者'text/plain'三者其中之一,没有自定义请求头并且只能有以下一个或者多个请求头包括:Accept,Accept-Language,Content-Language,Content-Type(必须是'application/x-www.form-urlencoded'或者'multipart/form-data'或者'text/plain'三者其中之一),Cache-Control,Expires,Last-Modified,Pragma.

非简单请求:包括PUT,DELETE请求或者包含自定义请求头的其他请求或者Content-Type不是'application/x-www.form-urlencoded'或者'multipart/form-data'或者'text/plain'三者其中之一的请求

一般现在前后端交互都用application/json因此基本都是复杂请求

非简单请求会发送预见请求询问服务器是否允许跨域

演示下非简单请求发送时的情况:

这里浏览器没看到预检请求的发送 可以由于版本问题

后端解决办法1

老版本的Chrome浏览器

做法在chrome地址栏总输入 chrome://flags/#out-of-blink-cors

将其设置为Disabled后重启浏览器

玩了半天 新版本Chrome浏览器的预检请求在Other里,按住Ctrl键+鼠标左点击上面的Fetch/XHR和Other看到预检请求

注意注意,浏览器有缓存,清理缓存,还有后端如果设置了预检请求有效期,那么只有第一次请求才有,后面存活时间内不会发送预检你可能查1天都查不出来,还有注意是否有开启代理,把代理关了(可能影响,只是可能,反正我没影响)

  1. ccess-Control-Allow-Origin: 这个头表示允许访问资源的域。如果服务器明确知道请求是来自特定的域,可以设置这个头为对应的域。如果是公开的资源,可以设置为 *,表示允许所有域的访问。

  2. Access-Control-Allow-Methods: 这个头表示允许实际请求使用的 HTTP 方法。如果服务器只允许特定的方法,例如 GET、POST,那么就在这个头中设置相应的方法。

  3. Access-Control-Allow-Headers: 这个头表示允许实际请求携带的请求头字段。如果请求中包含的请求头字段在这个头中,浏览器将允许实际请求。通常,如果请求中包含了自定义的请求头,服务器需要设置这个头来允许这些请求头字段。

  4. Access-Control-Allow-Credentials: 这个头表示是否允许携带身份凭证(例如 cookies、HTTP 认证信息)进行跨域请求。如果服务器需要接受携带身份凭证的请求,可以设置这个头为 true。注意,如果设置为 true,前端发起请求时需要将 withCredentials 属性设置为 true。

  5. Access-Control-Max-Age: 这个头表示预检请求的结果可以被缓存的时间,以减少对服务器的频繁请求。这个头是可选的,不一定要包含。

以上并不是一定要配置,看具体项目需要

通常解决跨域问题不会在每个控制器 控制器上去加@CrossOrign的方式

原因,项目都有过滤器或拦截器,请求还没到控制器就玩个der

行进跨域访问配置有三种方式

1.过滤器 2.拦截器 3.实现WebMvcConfigurer并重写addCorsMappings方法

主要是执行时机

这里用实现WebMvcConfigurer重写addCorsMappings的方法

复制代码
/**
 * @author hrui
 * @date 2023/11/29 4:19
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    //处理跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        System.out.println("===========addCorsMappings===========");
        registry.addMapping("/**")//选择可以跨域请求的路径
                //.addMapping("/api/**")
                .allowedOriginPatterns("*")//表示允许来自任意域的请求
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")//允许的实际请求方式,这个不影响预检请求axios.defaults.withCredentials = true;才可以携带Cookie
                .allowCredentials(true)//是否允许携带凭证信息(Cookie)sessionId 这里测试即使后端允许,前端
                .maxAge(3600)//该预检请求的有效时间 单位是秒  有效期内不需要再次发送预检请求
                //.allowedHeaders("*");//表示允许所有请求头
                .allowedHeaders("token");//这样设置,前端只能携带名为token的自定义请求头,也可以不自定请求头发送预检请求,但是不能定义其他名称的请求头
    }
}

如果上面这样设置 那么前端请求拦截器

拦截器过滤器参考

@CrossOrigin注解解决跨域和过滤器拦截器存在的问题-CSDN博客

相关推荐
喵叔哟13 分钟前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解1 小时前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
Mr.咕咕1 小时前
Django 搭建数据管理web——商品管理
前端·python·django