Spring @CrossOrigin 注解原理(转)


现实开发中,我们难免遇到跨域问题,以前笔者只知道jsonp这种解决方式,后面听说spring只要加入@CrossOrigin即可解决跨域问题。本着好奇的心里,笔者看了下@CrossOrigin 作用原理,写下这篇博客。

先说原理:其实很简单,就是利用spring的拦截器实现往response里添加 Access-Control-Allow-Origin等响应头信息,我们可以看下spring是怎么做的

注:这里使用的spring版本为5.0.6

我们可以先往RequestMappingHandlerMapping 的initCorsConfiguration方法打一个断点,发现方法调用情况如下

 

如果controller在类上标了@CrossOrigin或在方法上标了@CrossOrigin注解,则spring 在记录mapper映射时会记录对应跨域请求映射,代码如下

RequestMappingHandlerMapping protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) { HandlerMethod handlerMethod = createHandlerMethod(handler, method); Class<?> beanType = handlerMethod.getBeanType(); //获取handler上的CrossOrigin 注解 CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class); //获取handler 方法上的CrossOrigin 注解 CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class); if (typeAnnotation == null && methodAnnotation == null) { //如果类上和方法都没标CrossOrigin 注解,则返回一个null return null; } //构建一个CorsConfiguration 并返回 CorsConfiguration config = new CorsConfiguration(); updateCorsConfig(config, typeAnnotation); updateCorsConfig(config, methodAnnotation); if (CollectionUtils.isEmpty(config.getAllowedMethods())) { for (RequestMethod allowedMethod : mappingInfo.getMethodsCondition().getMethods()) { config.addAllowedMethod(allowedMethod.name()); } } return config.applyPermitDefaultValues(); }

将结果返回到了AbstractHandlerMethodMapping#register,主要代码如下

	CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
				if (corsConfig != null) { //会保存handlerMethod处理跨域请求的配置 this.corsLookup.put(handlerMethod, corsConfig); } 

当一个跨域请求过来时,spring在获取handler时会判断这个请求是否是一个跨域请求,如果是,则会返回一个可以处理跨域的handler

AbstractHandlerMapping#getHandler	
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		//如果是一个跨域请求 if (CorsUtils.isCorsRequest(request)) { //拿到跨域的全局配置 CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); //拿到hander的跨域配置 CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); //处理跨域(即往响应头添加Access-Control-Allow-Origin信息等),并返回对应的handler对象 executionChain = getCorsHandlerExecutionChain(request, executionChain, config); }

我们可以看下如何判定一个请求是一个跨域请求,

public static boolean isCorsRequest(HttpServletRequest request) { //判定请求头是否有Origin 属性即可 return (request.getHeader(HttpHeaders.ORIGIN) != null); }


转自:https://www.liangzl.com/get-article-detail-114619.html


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM