跨域請求
瀏覽器具有同源限制,即完全一致的意思是,域名要相同(www.example.com
和example.com
不同),協議要相同(http
和https
不同),端口號要相同(默認是:80
端口,它和:8080
就不同)
使用CROS處理跨域
Origin表示本域,也就是瀏覽器當前頁面的域。當JavaScript向外域(如sina.com)發(fā)起請求后,瀏覽器收到響應后,首先檢查Access-Control-Allow-Origin
是否包含本域,如果是,則此次跨域請求成功,如果不是,則請求失敗,JavaScript將無法獲取到響應的任何數據。
跨域能否成功,取決于對方服務器是否愿意給你設置一個正確的Access-Control-Allow-Origin
,決定權始終在對方手中。
簡單跨域請求
上面這種跨域請求,稱之為“簡單請求”。簡單請求包括GET、HEAD和POST(POST的Content-Type類型
僅限application/x-www-form-urlencoded
、multipart/form-data
和text/plain
),并且不能出現任何自定義頭(例如,X-Custom: 12345
),通常能滿足90%的需求。
其他類型的請求
對于PUT、DELETE以及其他類型如application/json
的POST請求,在發(fā)送AJAX請求之前,瀏覽器會先發(fā)送一個OPTIONS
請求(稱為preflighted請求)到這個URL上,詢問目標服務器是否接受:
OPTIONS /path/to/resource HTTP/1.1
Host: bar.com
Origin: http://my.com
Access-Control-Request-Method: POST
服務器必須響應并明確指出允許的Method:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://my.com
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true | false // 是否允許攜帶 Cookie
帶cookie的跨域請求
Access-Control-Allow-Credentials
響應頭會使瀏覽器允許在 Ajax 訪問時攜帶 Cookie,但我們仍然需要對 XMLHttpRequest 設置其 withCredentials
參數,才能實現攜帶 Cookie 的目標。
為了安全,標準里不允許 Access-Control-Allow-Origin: *
,必須指定明確的、與請求網頁一致的域名。同時,Cookie 依然遵循“同源策略”,只有用目標服務器域名設置的 Cookie 才會上傳,而且使用 document.cookie
也無法讀取目標服務器域名下的 Cookie。
Springboot設置跨域
可以在服務端設置允許跨域訪問,設置如下:
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否發(fā)送Cookie信息
config.setAllowCredentials(true);
//放行哪些原始域(請求方式)
config.addAllowedMethod("*");
//放行哪些原始域(頭部信息)
config.addAllowedHeader("*");
//2.添加映射路徑
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
在實際的實踐中發(fā)現,上述處理方式可以解決大多數情況下的跨域問題,但是當客戶端的請求帶有cookies時,我們就不能使用簡單的通配符*來處理跨域問題,會發(fā)現上述的springboot跨域設置失效,針對這個問題,可以使用過濾器將請求的url進行攔截,重新設置響應頭,就可以完成帶cookie請求跨域的處理。
攔截器處理跨域問題
用filter攔截每次請求,如果攜帶身份信息(Credential)時,獲取到具體的域響應給請求。
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//根據請求頭設置響應頭
String allowOrigin = request.getHeader("Origin");
String allowHeader = request.getHeader("Access-Control-Request-Headers");
response.setHeader("Access-Control-Allow-Origin", allowOrigin);
//設置允許帶cookie的請求
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "OPTIONS, POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", allowHeader);
filterChain.doFilter(servletRequest, servletResponse);
}
}
在實際的項目中,全局的跨域設置處理與攔截器可以同時設置,針對帶有cookie的請求,我們可以設置攔截器來進行處理,就可以很好的處理跨域問題。
參考自:https://blog.csdn.net/u014029255/article/details/56842509