自定义WebMvcConfigurer实现CORS配置--原理分析

基于自定义WebMvcConfigurer实现CORS配置–原理分析

原理分析

说明

​ If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. ->摘要自spring boot reference guide

通过spring官方说明明白可以通过WebMvcConfigurer实现额外的MVC配置。

代码实现

@Configuration
public class ExampleConfig implements WebMvcConfigurer
{  
    @Override
    public void addCorsMappings(CorsRegistry registry)
    {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOrigins("*")
                // 是否允许证书
                .allowCredentials(true)
                // 设置允许的方法
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间
                .maxAge(3600);
    }
}

步骤分析

​ spring初始化时加载corsMapping的配置信息并注册到实现于IOC容器,具体实例以及信息封装:RequestMappingHandlerMapping -> corsConfigurationSource -> corsConfigurations

​ 接口访问时,在DispatchServlet中doDispatch方法里,通过getHandler拿到HandlerExecutionChain,cors配置信息封装在HandlerExecutionChain实例中,在getHandler方法中的this.handlerMappings集合中可以看到之前注册的RequestMappingHandlerMapping。这里需要注意,请求访问的header头中需要包含Origin,因为在getHandler时会判断header中是否存在Origin,然后才包装cors配置信息。具体代码如下:

if (CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
                CorsConfiguration config = globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig;
                executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
  }

接着回到通过getHandler得到的mappedHandler对象处,往下可以看到执行了mappedHandler.applyPreHandle(processedRequest, response),而我们的cors配置封装在HandlerInterceptor数组中,这里通过调用interceptor的preHandle,通过调用链:CorsInterceptor.preHandle ->DefaultCorsProcessor.processRequest ->DefaultCorsProcessor.handleInternal 在这里将配置的cors信息写入response的header中完成跨域信息响应注入。

这块其实spring官方也有给出解释(摘要自CORS support in Spring Framework):

How does it work?

CORS requests (including preflight ones with an OPTIONS method) are automatically dispatched to the various HandlerMappings registered. They handle CORS preflight requests and intercept CORS simple and actual requests thanks to a CorsProcessor implementation (DefaultCorsProcessor by default) in order to add the relevant CORS response headers (like Access-Control-Allow-Origin). CorsConfiguration allows you to specify how the CORS requests should be processed: allowed origins, headers, methods, etc. It can be provided in various ways:

  • AbstractHandlerMapping#setCorsConfiguration() allows to specify a Map with several CorsConfiguration mapped on path patterns like /api/**
  • Subclasses can provide their own CorsConfiguration by overriding AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest) method
  • Handlers can implement CorsConfigurationSource interface (like ResourceHttpRequestHandler now does) in order to provide a CorsConfiguration for each request.

你可能感兴趣的:(#,spring,java)