Java Web前后端分離中CORS配置及OPTIONS請求優(yōu)化
0x00 CORS 概述
跨域資源共享(CORS) 是一種機制赘风,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源蛹尝。當一個資源從與該資源本身所在的服務器不同的域绑榴、協(xié)議或端口請求一個資源時,資源會發(fā)起一個跨域 HTTP 請求雷客。
跨域資源共享( CORS )機制允許 Web 應用服務器進行跨域訪問控制祈秕,從而使跨域數(shù)據(jù)傳輸?shù)靡园踩M行。現(xiàn)代瀏覽器支持在 API 容器中(例如
XMLHttpRequest
或 Fetch )使用 CORS九秀,以降低跨域 HTTP 請求所帶來的風險。
CORS存在的主要原因就是瀏覽器的同源策略粘我。
預檢請求(preflight request)
對于跨域請求鼓蜒,瀏覽器首先通過OPTIONS方法發(fā)送一個預檢請求,用于判斷服務端是否可以接收當前請求征字,然后才會發(fā)送真正的HTTP請求都弹。
請求頭部
在HTTP請求的頭部,主要有如下幾個字段和CORS相關:
Access-Control-Allow-Origin
該字段用于標識服務端可以接收來自什么地方的請求匙姜,為"*"
時表示可以接收畅厢;
Access-Control-Allow-Methods
該字段用于標識服務端可以接收什么樣的請求,主要包括GET
氮昧、POST
框杜、OPTIONS
浦楣、PUT
、DELETE
等咪辱;
Access-Control-Allow-Headers
該字段存在預檢請求中振劳,用于標識服務端允許的頭部內(nèi)容,主要包括Accept
油狂、Accept-Language
澎迎、Content-Language
、Content-Type
等选调,服務端返回內(nèi)容到Access-Control-Expose-Headers
字段;
Access-Control-Max-Age
該字段存在預檢請求中灵份,用于標識服務端設置的預檢請求信息緩存時間仁堪。即在服務端設置的時間范圍內(nèi),只需發(fā)送一次OPTIONS請求;
Access-Control-Allow-Credentials
該字段存在預檢請求中填渠,用于標識是否接收瀏覽器端的認證信息弦聂。認證信息主要包括Cookie
、authorization headers
等內(nèi)容氛什。該字段和瀏覽器中的withCredentials
相對應莺葫,瀏覽器端用于標識是否發(fā)送認證信息,服務端用于標識是否接收認證信息枪眉。
0x01 Filter中配置CORS
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.addHeader("Access-Control-Allow-Origin", "path/to/origin");
httpServletResponse
.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
httpServletResponse.setHeader("Access-Control-Allow-Headers",
httpServletRequest.getHeader("Access-Control-Request-Headers"));
httpServletResponse.addHeader("Access-Control-Max-Age", "86400");
httpServletResponse.addHeader("Access-Control-Allow-Credentials","false");
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
0x02 SpringBoot中配置CORS
全局配置
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("path/to/origin")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("POST", "GET", "OPTIONS")
.maxAge(86400)
.allowCredentials(false);
}
}
單獨配置
@CrossOrigin(
origins = "path/to/origin",
methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS},
allowedHeaders = "*",
allowCredentials = "false",
maxAge = 86400)
0x03 OPTIONS請求優(yōu)化
右上可知捺檬,Access-Control-Max-Age字段用于標識預檢請求的緩存時間,因此可以設置Access-Control-Max-Age為較大值來優(yōu)化OPTIONS請求贸铜,在設置的時間段內(nèi)堡纬,只有第一次請求是需要發(fā)送OPTIONS的,后面的請求均不需要蒿秦。
但是烤镐,預檢請求只針對于單個URL,而不是整個域名棍鳖,即對http://domain/a
和http://domain/b
這2個請求炮叶,均需要發(fā)送OPTIONS。