⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/qq_34115899/article/details/116763968 「砖业洋__」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

从前端的角度看options

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

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

跨域问题

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

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

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

OPTIONS请求

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

从后端的角度看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请求就会报错如下,预检请求也无法成功响应

预检请求失败

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

CORS error

服务器拒绝OPTIONS请求

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

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

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

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

文章目录
  1. 1. 从前端的角度看options
  2. 2. 从后端的角度看options