In real development, we inevitably encounter cross domain problems. In the past, I only knew about the solution of jsonp. Later, I heard that spring can solve cross domain problems only by joining @ CrossOrigin. In the spirit of curiosity, I read the working principle of @ CrossOrigin and wrote this blog.
Let's start with the principle: actually, it's very simple to use spring's interceptor to add response header information such as access control allow origin to the response. We can see how spring is done
Note: the version of spring used here is 5.0.6
We can first make a breakpoint to the initCorsConfiguration method of RequestMappingHandlerMapping, and find that the method call is as follows
If the controller marks @ CrossOrigin on the class or @ CrossOrigin annotation on the method, spring will record the corresponding cross domain request mapping when recording the mapper mapping. The code is as follows
RequestMappingHandlerMapping protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) { HandlerMethod handlerMethod = createHandlerMethod(handler, method); Class<?> beanType = handlerMethod.getBeanType(); //Get CrossOrigin annotation on handler CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class); //Get CrossOrigin annotation on handler method CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class); if (typeAnnotation == null && methodAnnotation == null) { //If there is no CrossOrigin annotation on the class and method, a null is returned return null; } //Build a CorsConfiguration and return 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(); }
The result is returned to abstracthandlermethodmapping ා, and the main code is as follows
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) { //The configuration of handlerMethod processing cross domain requests will be saved this.corsLookup.put(handlerMethod, corsConfig); }
When a cross domain request comes, spring will judge whether the request is a cross domain request when it gets the handler. If so, it will return a handler that can handle the cross domain
AbstractHandlerMapping#getHandler HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); //If it is a cross domain request if (CorsUtils.isCorsRequest(request)) { //Get cross domain global configuration CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); //Get the cross domain configuration of handler CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); //Processing cross domain (that is, adding access control allow origin information to the response header) and returning the corresponding handler object executionChain = getCorsHandlerExecutionChain(request, executionChain, config); }
We can see how to determine whether a request is a cross domain request,
public static boolean isCorsRequest(HttpServletRequest request) { //Determine whether the request header has Origin attribute return (request.getHeader(HttpHeaders.ORIGIN) != null); }
, it's time to go to bed, write again tomorrow