SpringBoot配置cors

本文介绍了浏览器的同源策略以及跨域资源共享CORS标准,详细阐述了SpringBoot如何配置CORS以解决跨域问题。文中提到在SpringBoot中通过`@Bean`注解配置`CorsConfigurationSource`和`CorsFilter`,并展示了如何创建自定义的`CorsProcessor`以增强默认处理器的功能,以适应项目中特定的检查需求。
摘要由CSDN通过智能技术生成

先简单介绍一下CORS的背景

同源策略

跨域问题的产生是因为浏览器的同源策略。同源策略将协议+域名+端口构成的三元作为一个整体,只有三者均相同的情况下才属于一个源。跨域问题也就是不同源之间访问导致的问题。

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

跨域资源共享 CORS

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

公司有一个查询接口,该接口本身用于end to end一直没有产生跨域的问题,后来了解到还有一个JS SDK,该SDK也会通过AJAX调用这个接口就产生了跨域问题,需要后端进行支持。

简单请求与非简单请求

(1)工作中比较常见 【简单请求】:
方法为:

  • GET
  • HEAD
  • POST

(2)请求header里面:
无自定义头

          Content-Type为以下几种:

                text/plain

                multipart/form-data

                application/x-www-form-urlencoded

除此以外的请求都为非简单请求,最常见的场景中由ajax发送json报文。这两种请求浏览器会有不同的行为,具体可以参考CORS详解。本文主要介绍如何在SpringBoot中如何处理CORS。

SpringBoot配置

	@Bean
    public CorsConfigurationSource corsConfigurationSource(){
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("POST"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/test",configuration);
        return source;
    }

由于我们项目中使用了SpringSecurity,还需要一个额外的配置上面才能生效

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http 
        	.....
            .and().cors();
    }
}

上述完成之后,会在filterChain中加入一个新的CorsFilter,该filter中有一个map存放url和CorsConfiguration,当有新的request时,会通过url获取到对应的CorsConfiguration,然后交给DefaultCorsProcessor来进行处理,主要是检查headers,origin,HttpMethod是否匹配,不匹配的话就返回http403的错误,下面是源代码。

public class CorsFilter extends OncePerRequestFilter {

	private final CorsConfigurationSource configSource;

	private CorsProcessor processor = new DefaultCorsProcessor();


	/**
	 * Constructor accepting a {@link CorsConfigurationSource} used by the filter
	 * to find the {@link CorsConfiguration} to use for each incoming request.
	 * @see UrlBasedCorsConfigurationSource
	 */
	public CorsFilter(CorsConfigurationSource configSource) {
		Assert.notNull(configSource, "CorsConfigurationSource must not be null");
		this.configSource = configSource;
	}


	/**
	 * Configure a custom {@link CorsProcessor} to use to apply the matched
	 * {@link CorsConfiguration} for a request.
	 * <p>By default {@link DefaultCorsProcessor} is used.
	 */
	public void setCorsProcessor(CorsProcessor processor) {
		Assert.notNull(processor, "CorsProcessor must not be null");
		this.processor = processor;
	}


	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
			FilterChain filterChain) throws ServletException, IOException {

		CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
		boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
		if (!isValid || CorsUtils.isPreFlightRequest(request)) {
			return;
		}
		filterChain.doFilter(request, response);
	}

}

到这里其实CORS就已经结束了,但是DefaultCorsProcessor不太符合我们的需要,我们在interceptor增加了各种检查,而options类型的请求不会进入到interceptor中,我们需要定制化的Processor来完善这一功能。

仔细看CorsFilter,可以发现其实有一个方法setCorsProcessor(CorsProcessor processor)可以进行替换,我们先定义一个CustomCorsProcessor

public class CustomCorsProcessor extends DefaultCorsProcessor {

  private static Logger logger = LoggerFactory.getLogger(DefaultCorsProcessor.class);

  @Override
  protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response,
      CorsConfiguration config, boolean preFlightRequest) throws IOException{
    logger.info("worked");
    return super.handleInternal(request, response, config, preFlightRequest);
  }

}

最初的想法是通过@Bean注解,看Spring本身会不会有机制进行方法注入,不过该尝试没有成功,最后干脆直接new一个CorsFilter

    @Bean
    public CorsFilter corsFilter(){
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("POST"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/test",configuration);
        CorsFilter corsFilter = new CorsFilter(source);
        corsFilter.setCorsProcessor(new CustomCorsProcessor());
        return corsFilter;
    }

更新,手动创建CorsFilter 的话,可以省略.and().cors()的设置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值