学向勤中得,萤窗万卷书。这篇文章主要讲述#yyds干货盘点#跨域问题之Spring的跨域的方案相关的知识,希望能为你提供帮助。
Spring的跨域的方案
@CrossOrigin@CrossOrigin可以添加到方法上,也可以添加到Controller上
AbstractHandlerMethodMapping的内部类MappingRegistry的register:
public void register(T mapping, Object handler, Method method)
// Assert that the handler method is not a suspending one.
if (KotlinDetector.isKotlinType(method.getDeclaringClass()))
Class<
?>
[] parameterTypes = method.getParameterTypes();
if ((parameterTypes.length >
0) &
&
"kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName()))
throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
this.readWriteLock.writeLock().lock();
try
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
validateMethodMapping(handlerMethod, mapping);
this.mappingLookup.put(mapping, handlerMethod);
List<
String>
directUrls = getDirectUrls(mapping);
for (String url : directUrls)
this.urlLookup.add(url, mapping);
String name = null;
if (getNamingStrategy() != null)
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null)
this.corsLookup.put(handlerMethod, corsConfig);
this.registry.put(mapping, new MappingRegistration<
>
(mapping, handlerMethod, directUrls, name));
finally
this.readWriteLock.writeLock().unlock();
- @CrossOrigin 注解在AbstractHandlerMethodMapping的内部类MappingRegistry的register方法中完成解析,@CrossOrigin注解中的内容会被解析成一个配置对象CorsConfiguration
- 将@CrossOrigin所标记的请求方法对象HandlerMethod和CorsConfiguration一一对应存入corsLookup的map集合中
- 当请求到达DispatcherServlet的doDispatch方法之后,调用AbstractHandlerMapping的getHandler方法获取执行链HandlerExecutionChain时,会从map中获取CorsConfiguration对象
- 根据获取到的CorsConfiguration对象构建一个CorsInterceptor拦截器
- 在CorsInterceptor拦截器中触发对CorsProcessor的processRequest方法调用,跨域请求的校验工作将在该方法中完成。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("*")
.allowedHeaders("*")
.allowCredentials(false)
.exposedHeaders("")
.maxAge(3600);
全局配置和@CrossOrigin注解相同,都是在CorsInterceptor拦截器中触发对CorsProcessor的processRequest方法调用,最终在该方法中完成跨域请求的校验工作
- registry.addMapping(" /**" )方法中配置了一个CorsRegistration对象,该对象中包含了一个路径拦截规则,同时CorsRegistration还包含了一个CorsConfiguration配置对象,该对象用来保存这里跨域相关的配置。
- 在WebMvcConfigurationSupport的requestMappingHandlerMapping方法中触发了addCorsMappings方法执行,将获取到的CorsRegistration对象重新组装成一个UrlBasedCorsConfigurationSource对象,该对象保存了拦截规则和CorsConfiguration对象的映射关系。
- 将新建的UrlBasedCorsConfigurationSource对象赋值给AbstractHandlerMapping的corsConfigurationSource属性
- 当请求到达时的处理方法和@CrossOrigin注解处理流程一样,在AbstractHandlerMapping的getHandler方法处理,从corsConfigurationSource中获取CorsConfiguration配置对象,而@CrossOrigin从map中获取CorsConfiguration对象。如果两处都可以获取到CorsConfiguration对象,则获取到的对象属性值进行合并。
- 根据获取到的CorsConfiguration对象构造CorsInterceptor拦截器
- 在CorsInterceptor拦截器中触发对CorsProcessor的processRequest方法调用,跨域请求的校验工作将在该方法中完成。
CorsFIlter
@Configuration
public class WebMvcConfig
@Bean
FilterRegistrationBean<
CorsFilter>
corsFilter()
FilterRegistrationBean<
CorsFilter>
registrationBean = new FilterRegistrationBean<
>
();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
corsConfiguration.setAllowedMethods(Arrays.asList("*"));
corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
corsConfiguration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
registrationBean.setFilter(new CorsFilter(source));
registrationBean.setOrder(-1);
return registrationBean;
- 手动创建CorsConfiguration对象
- 创建UrlBasedCorsConfigurationSource对象,将过滤器的拦截规则和CorsConfiguration对象之间的映射关系由UrlBasedCorsConfigurationSource中的corsConfiguration变量保存起来。
- 最后创建CorsFilter 设置优先级
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))
filterChain.doFilter(request, response);
触发对CorsProcessor的processRequest方法调用,跨域请求的校验工作将在该方法中完成
推荐阅读
- # yyds干货盘点 # 拼刀刀店铺后台的参数anti-content逆向分析
- #yyds干货盘点#Spring 源码阅读Spring IoCAOP 原理小总结
- Flutter 专题66 图解基本约束 Box#yyds干货盘点#
- Redis哨兵集群主库故障数据恢复思路 #yyds干货盘点#
- Flutter 专题65 图解基本 TextField 文本输入框#yyds干货盘点#
- 容器管理工具docker和容器的规范与依赖
- 带你全面扫盲!
- au3+zabbix打造轻量级计算机安全告警系统(序)
- Effective Java - 静态方法与构造器