点击上方“Java基基”,选择“设为星标”

做积极的人,而不是积极废人!

每天 14:00 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:blog.csdn.net/qq_34115899/

article/details/116763968


从前端的角度看options

options请求是浏览器的一个机制,不是前端开发人员说不想发options请求就不发的。当你这个post请求跨域的时候,那options请求就出现了(「当然还有putdelete请求也会发送预检请求,这些比较少见,在这里我就只谈post )。

options请求就去问问浏览器,我想跨域okok?如果后端设置了允许该域名跨域,那么接着post请求就正常发送。否则你就会在控制台看到该请求跨域的错误,类似于下面这种

9fe3d507b25a67c05c41bd032bb9f846.png
跨域问题

就这么简单,一句话概括:「当跨域的时候,post请求之前浏览器就会提前发送options请求,就是询问服务器我能否顺利发送跨域post请求,如果不能,浏览器Console就看到跨域错误提示,如果能,post请求就顺利发送。」

后端配置跨域后,options请求发到服务器,服务器就会返回,但是没有response data,你可以当作是浏览器和服务器的悄悄的对话,不是前端开发人员手动控制的,因为options也不会命中后端某个接口。

本地调试一下,前端发送POST请求,后端在POST方法里面打断点调试时,也不会阻碍OPTIONS请求的返回。

32c1c097d3e2182ed7616c0120d86db4.png
OPTIONS请求

「那么是不是post请求之前一定会有options请求呢?不一定,那得看后端怎么配置」

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

从后端的角度看options

从后端的角度看options——post请求之前一定会有options请求?胡说八道!

后端java配置跨域代码一般如下,供参考

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 {

    public CorsConfig() {
    }

    @Bean
    public CorsFilter corsFilter() {
        // 1. 添加cors配置信息
        CorsConfiguration config = new CorsConfiguration();
        // Response Headers里面的Access-Control-Allow-Origin: http://localhost:8080
        config.addAllowedOrigin("http://localhost:8080");
        // 其实不建议使用*,允许所有跨域
        config.addAllowedOrigin("*");

        // 设置是否发送cookie信息,在前端也可以设置axios.defaults.withCredentials = true;表示发送Cookie,
        // 跨域请求要想带上cookie,必须要请求属性withCredentials=true,这是浏览器的同源策略导致的问题:不允许JS访问跨域的Cookie
        /**
         * withCredentials前后端都要设置,后端是setAllowCredentials来设置
         * 如果后端设置为false而前端设置为true,前端带cookie就会报错
         * 如果后端为true,前端为false,那么后端拿不到前端的cookie,cookie数组为null
         * 前后端都设置withCredentials为true,表示允许前端传递cookie到后端。
         * 前后端都为false,前端不会传递cookie到服务端,后端也不接受cookie
         */
        // Response Headers里面的Access-Control-Allow-Credentials: true
        config.setAllowCredentials(true);

        // 设置允许请求的方式,比如get、post、put、delete,*表示全部
        // Response Headers里面的Access-Control-Allow-Methods属性
        config.addAllowedMethod("*");

        // 设置允许的header
        // Response Headers里面的Access-Control-Allow-Headers属性,这里是Access-Control-Allow-Headers: content-type, headeruserid, headerusertoken
        config.addAllowedHeader("*");

        // Response Headers里面的Access-Control-Max-Age:3600
        // 表示下回同一个接口post请求,在3600s之内不会发送options请求,不管post请求成功还是失败,3600s之内不会再发送options请求
        // 如果不设置这个,那么每次post请求之前必定有options请求
        config.setMaxAge(3600L);


        // 2. 为url添加映射路径
        UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();
        // /**表示该config适用于所有路由
        corsSource.registerCorsConfiguration("/**", config);

        // 3. 返回重新定义好的corsSource
        return new CorsFilter(corsSource);
    }
}

「这就解决了上面的问题,POST请求之前不一定有OPTIONS请求,如果设置了config.setMaxAge,仅第一次发送OPTIONS请求,不管POST请求成功还是失败,在设置的时间范围内,同一个接口请求是绝对不会再次发送OPTIONS请求的。」

后端需要注意的是,我这里设置允许请求的方法是config.addAllowedMethod("*")*表示允许所有HTTP请求方法。如果未设置,则默认只允许“GET”和“HEAD”。你可以设置的HTTPMethodGET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

经过我的测试,**OPTIONS无需手动设置,因为单纯设置OPTIONS也无效** 「。如果你设置了允许POST,代码为config.addAllowedMethod(HttpMethod.POST); 那么其实已经默认允许了OPTIONS,如果你」只允许了 GET,尝试发送POST请求就会报错如下,预检请求也无法成功响应

ceb25adc1fa2f592093a2029862a8919.png
预检请求失败

预检请求返回403,服务器拒绝了OPTIONS类型的请求,因为你只允许了GETOPTIONS类型的请求未被服务器允许。POST请求的状态显示CORS error

0aa3efdddf2264b40c8f917d3ad58106.png
CORS error
a72ec33492db990e36a35d47eb3c79ca.png
服务器拒绝OPTIONS请求

有人会疑问了,如果我既设置了GET,又设置了OPTIONS,我能否看到不发送POSTOPTIONS成功返回的场景?

config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.OPTIONS);

答案是否定的,单纯设置OPTIONS没有意义,现象和上面一样,OPTIONS响应码仍然403POST没有被发送。

正常情况下我们只要允许了POSTOPTIONS就自动允许了,PUTDELETE也一样。所以从后端开发人员角度来看,几乎无需考虑OPTIONS这种请求,日常需求中POST请求命中接口时根本感知不到OPTIONS请求的存在,当然你也可以和上面一样设置OPTIONS请求的有效时间,在时间范围内,同一个接口的POST请求之前不会有OPTIONS请求。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

c17ae86358176c00ece62071184d8484.png

已在知识星球更新源码解析如下:

e324fa084c1ebe7f4a7cfd8699555c1d.jpeg

dbf3ab3bbcb5d6d845e78cfc8865ec21.jpeg

d95152cf9503ea9167cc0e275759e48a.jpeg

56e49d698f494ae1c659979a4ac4414e.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐