java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > 解决跨域请求,NG返回403

解决跨域请求,NG返回403(403并不一定是NG问题)

作者:zero

这篇文章主要介绍了解决跨域请求,NG返回403(403并不一定是NG问题),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

先说问题怎么解决的

1.ng返回403的情况也就那么几种,百度一下都能找到,但是ng返回403不一定是ng的问题。

2.最终发现是在网关跨域配置中,没有加上请求方的域名。

3.想探索的可以看看文章

背景

和合作方对接,我们这边的app开发完放在合作方的服务器上,再通过NG,请求我这边的后台。

NG配置跨域等信息后(这个很容易找,百度随便都能找到),发现测试环境一切正常,但是到了生产,NG一直返回403。

请求都没通过,网关zuul没有日志。双方开始排查NG,百度了无数次。

最后都配置与测试环境一直,但是生产一直不通。

返回403,加上zuul没日志,一直定位在NG跨域的问题上。

解决

最后发现是zuul项目的问题,SpringBoot跨域问题。

尝试排查是否zuul的问题,对比了测试环境和生产的。

测试环境zuul的跨域配置CorsConfiguration类属性allowedOrigins赋值了个*,生产是针对地址进行配置的。

其实就是SpringBoot的跨域配置,源码CorsConfiguration的allowedOrigins属性没有加上第三方的域名地址。

导致直接被拒绝了。加上合作方地址,问题解决。

源码解析

在配置跨域问题时,我们需要对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;
	}
	

进入checkOrigin(config, requestOrigin);校验请求来源

	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;
}
		

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文