解決跨域請求,NG返回403(403并不一定是NG問題)
先說問題怎么解決的
1.ng返回403的情況也就那么幾種,百度一下都能找到,但是ng返回403不一定是ng的問題。
2.最終發(fā)現(xiàn)是在網(wǎng)關(guān)跨域配置中,沒有加上請求方的域名。
3.想探索的可以看看文章
背景
和合作方對接,我們這邊的app開發(fā)完放在合作方的服務(wù)器上,再通過NG,請求我這邊的后臺。
NG配置跨域等信息后(這個很容易找,百度隨便都能找到),發(fā)現(xiàn)測試環(huán)境一切正常,但是到了生產(chǎn),NG一直返回403。
請求都沒通過,網(wǎng)關(guān)zuul沒有日志。雙方開始排查NG,百度了無數(shù)次。
最后都配置與測試環(huán)境一直,但是生產(chǎn)一直不通。
返回403,加上zuul沒日志,一直定位在NG跨域的問題上。
解決
最后發(fā)現(xiàn)是zuul項(xiàng)目的問題,SpringBoot跨域問題。
嘗試排查是否zuul的問題,對比了測試環(huán)境和生產(chǎn)的。
測試環(huán)境zuul的跨域配置CorsConfiguration類屬性allowedOrigins賦值了個*,生產(chǎn)是針對地址進(jìn)行配置的。
其實(shí)就是SpringBoot的跨域配置,源碼CorsConfiguration的allowedOrigins屬性沒有加上第三方的域名地址。
導(dǎo)致直接被拒絕了。加上合作方地址,問題解決。
源碼解析
在配置跨域問題時,我們需要對CorsConfiguration屬性賦值
//對CorsConfiguration屬性賦值 private CorsConfiguration corsConfig(Map.Entry<String, JawsCorsConfig> entry) { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedOrigins(Splitter.on(",").splitToList(entry.getValue().getAllowedOrigins())); corsConfiguration.setAllowedHeaders(Splitter.on(",").splitToList(entry.getValue().getAllowedHeaders())); corsConfiguration.setAllowedMethods(Splitter.on(",").splitToList(entry.getValue().getAllowedMethods())); corsConfiguration.setAllowCredentials(entry.getValue().getAllowCredentials()); corsConfiguration.setMaxAge(entry.getValue().getMaxAge()); return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); for (Map.Entry<String, JawsCorsConfig> entry : jawsZuulProperites.getCors().entrySet()) { source.registerCorsConfiguration(entry.getValue().getUrls(), corsConfig(entry)); } return new CorsFilter(source); }
源碼中 org.springframework.web.cors.DefaultCorsProcessor#handleInternal 方法
protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response, CorsConfiguration config, boolean preFlightRequest) throws IOException { String requestOrigin = request.getHeaders().getOrigin(); String allowOrigin = checkOrigin(config, requestOrigin); HttpMethod requestMethod = getMethodToUse(request, preFlightRequest); List<HttpMethod> allowMethods = checkMethods(config, requestMethod); List<String> requestHeaders = getHeadersToUse(request, preFlightRequest); List<String> allowHeaders = checkHeaders(config, requestHeaders); if (allowOrigin == null || allowMethods == null || (preFlightRequest && allowHeaders == null)) { rejectRequest(response); return false; } HttpHeaders responseHeaders = response.getHeaders(); responseHeaders.setAccessControlAllowOrigin(allowOrigin); responseHeaders.add(HttpHeaders.VARY, HttpHeaders.ORIGIN); if (preFlightRequest) { responseHeaders.setAccessControlAllowMethods(allowMethods); } if (preFlightRequest && !allowHeaders.isEmpty()) { responseHeaders.setAccessControlAllowHeaders(allowHeaders); } if (!CollectionUtils.isEmpty(config.getExposedHeaders())) { responseHeaders.setAccessControlExposeHeaders(config.getExposedHeaders()); } if (Boolean.TRUE.equals(config.getAllowCredentials())) { responseHeaders.setAccessControlAllowCredentials(true); } if (preFlightRequest && config.getMaxAge() != null) { responseHeaders.setAccessControlMaxAge(config.getMaxAge()); } response.flush(); return true; }
進(jìn)入checkOrigin(config, requestOrigin);校驗(yàn)請求來源
public static final String ALL = "*"; /** * Check the origin of the request against the configured allowed origins. * @param requestOrigin the origin to check * @return the origin to use for the response, or {@code null} which * means the request origin is not allowed */ public String checkOrigin(String requestOrigin) { if (!StringUtils.hasText(requestOrigin)) { return null; } if (ObjectUtils.isEmpty(this.allowedOrigins)) { return null; } if (this.allowedOrigins.contains(ALL)) { if (this.allowCredentials != Boolean.TRUE) { return ALL; } else { return requestOrigin; } } //遍歷我們賦值的allowedOrigins,判斷請求來源是否包含,包含則返回 for (String allowedOrigin : this.allowedOrigins) { if (requestOrigin.equalsIgnoreCase(allowedOrigin)) { return requestOrigin; } } return null; }
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java遍歷http請求request的所有參數(shù)實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava遍歷http請求request的所有參數(shù)實(shí)現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09Java開發(fā)Oracle數(shù)據(jù)庫連接JDBC Thin Driver 的三種方法
這篇文章主要介紹了Java開發(fā)Oracle數(shù)據(jù)庫連接JDBC Thin Driver 的三種方法,需要的朋友可以參考下2015-12-12SpringCloud OpenFeign Post請求400錯誤解決方案
這篇文章主要介紹了SpringCloud OpenFeign Post請求400錯誤解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09SpringBoot之那些注入不了的Spring占位符(${}表達(dá)式)問題
這篇文章主要介紹了SpringBoot之那些注入不了的Spring占位符(${}表達(dá)式)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04子類繼承父類時構(gòu)造函數(shù)相關(guān)問題解析
這篇文章主要介紹了子類繼承父類時構(gòu)造函數(shù)相關(guān)問題解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11學(xué)習(xí)Java之二叉樹的編碼實(shí)現(xiàn)過程詳解
本文將通過代碼來進(jìn)行二叉樹的編碼實(shí)現(xiàn),文中的代碼示例介紹的非常詳細(xì),對我們學(xué)習(xí)Java二叉樹有一定的幫助,感興趣的同學(xué)跟著小編一起來看看吧2023-08-08詳解JAVA使用Comparator接口實(shí)現(xiàn)自定義排序
這篇文章主要介紹了JAVA使用Comparator接口實(shí)現(xiàn)自定義排序,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03