解決跨域請(qǐng)求,NG返回403(403并不一定是NG問(wèn)題)
先說(shuō)問(wèn)題怎么解決的
1.ng返回403的情況也就那么幾種,百度一下都能找到,但是ng返回403不一定是ng的問(wèn)題。
2.最終發(fā)現(xiàn)是在網(wǎng)關(guān)跨域配置中,沒(méi)有加上請(qǐng)求方的域名。
3.想探索的可以看看文章
背景
和合作方對(duì)接,我們這邊的app開(kāi)發(fā)完放在合作方的服務(wù)器上,再通過(guò)NG,請(qǐng)求我這邊的后臺(tái)。
NG配置跨域等信息后(這個(gè)很容易找,百度隨便都能找到),發(fā)現(xiàn)測(cè)試環(huán)境一切正常,但是到了生產(chǎn),NG一直返回403。
請(qǐng)求都沒(méi)通過(guò),網(wǎng)關(guān)zuul沒(méi)有日志。雙方開(kāi)始排查NG,百度了無(wú)數(shù)次。
最后都配置與測(cè)試環(huán)境一直,但是生產(chǎn)一直不通。
返回403,加上zuul沒(méi)日志,一直定位在NG跨域的問(wèn)題上。
解決
最后發(fā)現(xiàn)是zuul項(xiàng)目的問(wèn)題,SpringBoot跨域問(wèn)題。
嘗試排查是否zuul的問(wèn)題,對(duì)比了測(cè)試環(huán)境和生產(chǎn)的。
測(cè)試環(huán)境zuul的跨域配置CorsConfiguration類屬性allowedOrigins賦值了個(gè)*,生產(chǎn)是針對(duì)地址進(jìn)行配置的。
其實(shí)就是SpringBoot的跨域配置,源碼CorsConfiguration的allowedOrigins屬性沒(méi)有加上第三方的域名地址。
導(dǎo)致直接被拒絕了。加上合作方地址,問(wèn)題解決。
源碼解析
在配置跨域問(wèn)題時(shí),我們需要對(duì)CorsConfiguration屬性賦值
//對(duì)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)請(qǐng)求來(lái)源
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,判斷請(qǐng)求來(lái)源是否包含,包含則返回 for (String allowedOrigin : this.allowedOrigins) { if (requestOrigin.equalsIgnoreCase(allowedOrigin)) { return requestOrigin; } } return null; }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java遍歷http請(qǐng)求request的所有參數(shù)實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇java遍歷http請(qǐng)求request的所有參數(shù)實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09Java開(kāi)發(fā)Oracle數(shù)據(jù)庫(kù)連接JDBC Thin Driver 的三種方法
這篇文章主要介紹了Java開(kāi)發(fā)Oracle數(shù)據(jù)庫(kù)連接JDBC Thin Driver 的三種方法,需要的朋友可以參考下2015-12-12SpringCloud OpenFeign Post請(qǐng)求400錯(cuò)誤解決方案
這篇文章主要介紹了SpringCloud OpenFeign Post請(qǐng)求400錯(cuò)誤解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09SpringBoot之那些注入不了的Spring占位符(${}表達(dá)式)問(wèn)題
這篇文章主要介紹了SpringBoot之那些注入不了的Spring占位符(${}表達(dá)式)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04子類繼承父類時(shí)構(gòu)造函數(shù)相關(guān)問(wèn)題解析
這篇文章主要介紹了子類繼承父類時(shí)構(gòu)造函數(shù)相關(guān)問(wèn)題解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11學(xué)習(xí)Java之二叉樹(shù)的編碼實(shí)現(xiàn)過(guò)程詳解
本文將通過(guò)代碼來(lái)進(jìn)行二叉樹(shù)的編碼實(shí)現(xiàn),文中的代碼示例介紹的非常詳細(xì),對(duì)我們學(xué)習(xí)Java二叉樹(shù)有一定的幫助,感興趣的同學(xué)跟著小編一起來(lái)看看吧2023-08-08詳解JAVA使用Comparator接口實(shí)現(xiàn)自定義排序
這篇文章主要介紹了JAVA使用Comparator接口實(shí)現(xiàn)自定義排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03