由於瀏覽器同源策略(同源策略,它是由Netscape提出的一個著名的安全策略,現在所有支持JavaScript 的瀏覽器都會使用這個策略。接下來通過本文給大家介紹Springboot如何優雅的解決ajax+自定義headers的跨域請求 ,需要的朋友可以參考下
1、什麼是跨域
由於瀏覽器同源策略(同源策略,它是由Netscape提出的一個著名的安全策略。現在所有支持JavaScript 的瀏覽器都會使用這個策略。所謂同源是指,域名,協議,端口相同。),凡是發送請求url的協議、域名、端口三者之間任意一與當前頁面地址不同即爲跨域。
具體可以查看下錶:
2、springboot如何解決跨域問題
1.普通跨域請求解決方案:
①請求接口添加註解@CrossOrigin(origins = "http://127.0.0.1:8020", maxAge = 3600)
說明:origins = "http://127.0.0.1:8020" origins值爲當前請求該接口的域
②通用配置(所有接口都允許跨域請求)
新增一個configration類 或 在Application中加入CorsFilter和CorsConfiguration方法
@Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); // 1允許任何域名使用 corsConfiguration.addAllowedHeader("*"); // 2允許任何頭 corsConfiguration.addAllowedMethod("*"); // 3允許任何方法(post、get等) return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); // 4 return new CorsFilter(source); } }
2.ajax自定義headers的跨域請求
$.ajax({ type:"GET", url:"http://localhost:8766/main/currency/sginInState", dataType:"JSON", data:{ uid:userId }, beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Authorization", access_token); }, success:function(res){ console.log(res.code) } })
此時請求http://localhost:8766/main/currency/sginInState接口發現OPTIONS http://localhost:8766/main/currency/sginInState 500錯誤,普通跨域的解決方案已經無法解決這種問題,爲什麼會出現OPTIONS請求呢?
原因
瀏覽器會在發送真正請求之前,先發送一個方法爲OPTIONS的預檢請求 Preflighted requests 這個請求是用來驗證本次請求是否安全的,但是並不是所有請求都會發送,需要符合以下條件:
•請求方法不是GET/HEAD/POST
•POST請求的Content-Type並非application/x-www-form-urlencoded, multipart/form-data, 或text/plain
•請求設置了自定義的header字段
對於管理端的接口,我有對接口進行權限校驗,每次請求需要在header中攜帶自定義的字段(token),所以瀏覽器會多發送一個OPTIONS請求去驗證此次請求的安全性。
爲何OPTIONS請求是500呢?
OPTIONS請求只會攜帶自定義的字段,並不會將相應的值帶入進去,而後臺校驗token字段時 token爲NULL,所以驗證不通過,拋出了一個異常。
那麼我們現在來解決這種問題:
① spring boot項目application.yml中添加
spring:
mvc:
dispatch-options-request: true
注意:這種解決方案可能在某些情況下並不能解決OPTIONS問題,原因可能是環境問題,也可能是複雜的自定義filter過濾器配置問題等。
②添加過濾器配置
第一步:手寫RequestFilter請求過濾器配置類此類需要實現HandlerInterceptor類,HandlerInterceptor類是org.springframework.web.servlet.HandlerInterceptor下的。
具體代碼實現:
@Component public class RequestFilter implements HandlerInterceptor { public boolean preHandler(HttpServletRequest request,HttpServletResponse response,Object handler){ response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS"); response.setHeader("Access-Control-Max-Age", "86400"); response.setHeader("Access-Control-Allow-Headers", "Authorization"); // 如果是OPTIONS請求則結束 if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) { response.setStatus(HttpStatus.NO_CONTENT.value()); return false; } return true; } }
第二步:手寫MyWebConfiguration此類需要繼承WebMvcConfigurationSupport。
注意:WebMvcConfigurationSupport是2.x版本以上的,1.x版本爲WebMvcConfigurerAdapter 。
具體代碼實現:
@Component public class MyWebConfiguration extends WebMvcConfigurationSupport{ @Resource private RequestFilter requestFilter; @Override public void addInterceptors(InterceptorRegistry registry) { // 跨域攔截器 registry.addInterceptor(requestFilter).addPathPatterns("/**"); } }
總結
以上所述是小編給大家介紹的Springboot解決ajax+自定義headers的跨域請求問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對神馬文庫網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請註明出處,謝謝!