Java跨域问题处理

1,887 阅读2分钟

在线测试跨域请求

  1. 打开浏览器,打开一个网页(比如掘金), 按F12调出开发者工具,google 浏览器开发者工具界面如下:

  1. 在 Console 输入下面的代码:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://xxx.com/common/listCity');
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

  1. 回车运行代码,如果出现跨域问题,会提示下面的信息

注意 掘金网址是https,只能调试https的接口,如果要调试http的,需要打开一个http的网址

JAVA 处理跨域

基于WebMvcConfigurerAdapter配置加入Cors的跨域

import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.config.annotation.CorsRegistry; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 


@Configuration 
public class CorsConfig extends WebMvcConfigurationSupport { 

    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
        registry.addMapping("/**"); 
    } 
}

集成 HandlerInterceptorAdapter 拦截器

@Component
public class CorsInterceptor extends HandlerInterceptorAdapter {

    private final Logger logger = LoggerFactory.getLogger(CorsInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
	response.setHeader("Access-Control-Allow-Origin",request.getHeader("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", "*");

        // 如果是OPTIONS则结束请求
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return false;
        }

        return true;
    }
}
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport{
	@Recourse
	private CorsInterceptor corsInterceptor;

	/**
	* 添加拦截器
	*/
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
	   registry.addInterceptor(corsInterceptor);
	}
}

创建一个filter解决跨域

@Component
public class SimpleCORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {}

    public void destroy() {}

}

SpringBoot 配置 CorsFilter(推荐)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许任何域名
        corsConfiguration.addAllowedOrigin("*");
        // 允许任何头
        corsConfiguration.addAllowedHeader("*");
        // 允许任何方法
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 注册
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }
}

问题

  1. 配置多个跨域
Access to XMLHttpRequest at 'http://shidemo.vaiwan.com/api/activityOrder/listStoreOrder' from origin 'http://api.demo.cn' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, http://api.demo.cn', but only one is allowed.

image.png

代码里面配置了多个跨域处理,但是只有一个是允许的,移除其中的任意一个就好了

  1. https网页不能调试http
Mixed Content: The page at 'https://juejin.cn/user/3861140566970237/posts' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://shidemo.vaiwan.com/api/area/cityList?cityChar=&cityId=&cityName=&provinceId='. This request has been blocked; the content must be served over HTTPS.

  1. 不安全的证书

image.png

参考

九种跨域方式实现原理(完整版)