春@CrossOriginのワイルドカードは、クロスドメインの問題を解決します

@CrossOriginワイルドカードは、クロスドメインの問題を解決します

痛みのポイント:

多くのAPIインタフェースが異なる環境によるH5 Ajaxサポートクロスドメインリクエストをオープンする必要があるドメイン名を設定し、CrossOriginのネイティブのみクロスドメインのサポート*、または特定のドメイン名をサポートするためにそう* .abc.com、ABCなど、すべての起源をサポートするCrossOriginサポートワイルドカードを失望クロスドメインAjaxリクエストをサポートするために(様々なサブドメインを含む).comドメインは、名前。

ソリューション:

サポートワイルドカード

@CrossOrigin(原点= { "* .abc.com"})

春のデフォルトサポートのCORSは、クロスドメイン処理春のカテゴリの下に拡大します

ソリューション:

提供の代わりに、カスタムMyCorsProcessor DefaultCorsProcessor RequestMappingHandlerMapping取得

/**
 * 给requestMappingHandlerMapping 对象注入自定义 MyCorsProcessor
 * @author tomas
 * @create 2019/8/12
 **/
@Configuration
@EnableWebMvc
public class MyWebMvcConfig extends DelegatingWebMvcConfiguration {
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
        handlerMapping.setCorsProcessor(new MyCorsProcessor());
        return handlerMapping;
    }
}
/**
 * MyCorsProcessor 描述
 * 自定义 如果xxx.com域下的请求允许跨域
 *
 * @author tomas
 * @create 2019/8/12
 **/
public class MyCorsProcessor extends DefaultCorsProcessor {

    /**
     * Check the origin of the request against the configured allowed origins.
     * @param requestOrigin the origin to check
     * @return the origin to use for the response, or {@code null} which
     * means the request origin is not allowed
     */
    @Nullable
    public String checkOrigin(CorsConfiguration config, @Nullable String requestOrigin) {
        if (!StringUtils.hasText(requestOrigin)) {
            return null;
        }
        if (ObjectUtils.isEmpty(config.getAllowedOrigins())) {
            return null;
        }
        if (config.getAllowedOrigins().contains(CorsConfiguration.ALL)) {
            if (config.getAllowCredentials() != Boolean.TRUE) {
                return CorsConfiguration.ALL;
            }
            else {
                return requestOrigin;
            }
        }
        for (String allowedOrigin :config.getAllowedOrigins()) {
            if (requestOrigin.equalsIgnoreCase(allowedOrigin)) {
                return requestOrigin;
            }
             //https://blog.abc.com/api/getXxx?id=1
            //推荐方式:正则 注意(CrossOrigin(origins = {"*.abc.com"}) ) 此方法会匹配上面的 url 
            if(requestOrigin.matches(new StringBuffer(".").append(allowedOrigin).append(".*").toString())){
                return requestOrigin;
            }
            //不推荐方式:写死
            if(allowedOrigin.contains("*.abc.com")&& requestOrigin.contains("abc.com")){
                return requestOrigin;
            }
        }
        return null;
    }
}

原理分析:

Spring MVCのCORS

Spring MVCのドキュメントは言う:
成功したハンドラに要求をマッピングした後、ビルトインサポートCORSのSpring MVCのHandlerMappingの実現を、HandlerMappingは、次のアクションを取るためにCORS設定をチェックします。
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-cors-processing
Spring MVCのは、ブロッカーを追加することにより、ハンドラCORS設定を発見した後にチェックされます。

CORSのSpring MVCの実現で次の一見。
()メソッドでgetHandler AbstractHandlerMappingを呼び出すのDispatcherServlet:

  /**
     * Look up a handler for the given request, falling back to the default
     * handler if no specific one is found.
     * @param request current HTTP request
     * @return the corresponding handler instance, or the default handler
     * @see #getHandlerInternal
     */
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Object handler = getHandlerInternal(request);
        if (handler == null) {
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // Bean name or resolved handler?
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = obtainApplicationContext().getBean(handlerName);
        }

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

Ajaxリクエストのために自動的にCorsInterceptorインターセプタを追加getCorsHandlerExecutionChain:

 /**
     * Update the HandlerExecutionChain for CORS-related handling.
     * <p>For pre-flight requests, the default implementation replaces the selected
     * handler with a simple HttpRequestHandler that invokes the configured
     * {@link #setCorsProcessor}.
     * <p>For actual requests, the default implementation inserts a
     * HandlerInterceptor that makes CORS-related checks and adds CORS headers.
     * @param request the current request
     * @param chain the handler chain
     * @param config the applicable CORS configuration (possibly {@code null})
     * @since 4.2
     */
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
            HandlerExecutionChain chain, @Nullable CorsConfiguration config) {

        if (CorsUtils.isPreFlightRequest(request)) {
            HandlerInterceptor[] interceptors = chain.getInterceptors();
            chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
        }
        else {
            chain.addInterceptor(new CorsInterceptor(config));
        }
        return chain;
    }

プライベートクラスCorsInterceptorにAbstractHandlerMapping

 
private class CorsInterceptor extends HandlerInterceptorAdapter implements CorsConfigurationSource {

        @Nullable
        private final CorsConfiguration config;
        public CorsInterceptor(@Nullable CorsConfiguration config) {
            this.config = config;
        }
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            return corsProcessor.processRequest(this.config, request, response);
        }
        @Override
        @Nullable
        public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
            return this.config;
        }
    }

実際の処理方法でCorsInterceptor preHandleのprocessRequestはAbstractHandlerMapping.this.corsProcessorあります

このcorsProcessor =新しいDefaultCorsProcessorは、()クロスドメイン処理のデフォルトのクラスです

我々の焦点は、DefaultCorsProcessorのcheckOrigin方法を書き換えることです

 
    @Override
    @SuppressWarnings("resource")
    public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        if (!CorsUtils.isCorsRequest(request)) {
            return true;
        }
                ......
        return handleInternal(serverRequest, serverResponse, config, preFlightRequest);
    }


    /**
     * Handle the given request.
     */
    protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response,
            CorsConfiguration config, boolean preFlightRequest) throws IOException {

        String requestOrigin = request.getHeaders().getOrigin();
        String allowOrigin = checkOrigin(config, requestOrigin);
        HttpHeaders responseHeaders = response.getHeaders();

        responseHeaders.addAll(HttpHeaders.VARY, Arrays.asList(HttpHeaders.ORIGIN,
                HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS));

        if (allowOrigin == null) {
            logger.debug("Rejecting CORS request because '" + requestOrigin + "' origin is not allowed");
            rejectRequest(response);
            return false;
        }

        ..........
        response.flush();
        return true;
    }

    /**
     * Check the origin and determine the origin for the response. The default
     * implementation simply delegates to
     * {@link org.springframework.web.cors.CorsConfiguration#checkOrigin(String)}.
     */

       // 重写此方法 支持通配符 或者支持正则表达式 写法见开头解决方案
    @Nullable
    protected String checkOrigin(CorsConfiguration config, @Nullable String requestOrigin) {
        return config.checkOrigin(requestOrigin);
    }
}

インターセプタを追加することによって防止CORS要求:実際にハンドラを呼び出す前のDispatcherServletは最初のインターセプタを呼び出します。
doDispatch方法:

 // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);

問題への注意:

  1. あなたは春のセキュリティを使用している場合は、春にCORSのセキュリティレベルを有効にし、それはSpring MVCのレベル定義された構成を使用することを可能にしてください。春のセキュリティレベルでCORSを有効にします

@EnableWebSecurity

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

​    @Override

​    protected void configure(HttpSecurity http) throws Exception {

​        http.cors().and()...

​    }

}
  1. グローバルコンフィギュレーションCORS

  きめの細かい、注釈ベースの構成に加えて、あなたはまた、いくつかのグローバルCORSの構成を定義する必要があるかもしれません。これは、フィルタを使用することに似ているが、スプリングMVCはきめ細かい@CrossOrigin構成と組み合わせて、それを宣言することができます。デフォルトでは、すべての起源やGETは、HEADとPOSTメソッドが許可されています。

に簡略化され、アプリケーション全体のCORS:


@Configuration

@EnableWebMvc

public class WebConfig extends WebMvcConfigurer {

​    @Override

​    public void addCorsMappings(CorsRegistry registry) {

​        registry.addMapping("/**");

​    }

}
  1. CORSサポートフィルタに基づいて

  上述した他の方法に代わるものとして、Springフレームワークを提供CorsFilterをこの場合、使用しなくても@CrossOrigin或``WebMvcConfigurer#addCorsMappings(CorsRegistry),,例えば、フィルタは、次の春ブートアプリケーション内で宣言することができます。


@Configuration

public class MyConfiguration {

​    @Bean

​    public FilterRegistrationBean corsFilter() {

​        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

​        CorsConfiguration config = new CorsConfiguration();

​        config.setAllowCredentials(true);

​        config.addAllowedOrigin("http://domain1.com");

​        config.addAllowedHeader("*");

​        config.addAllowedMethod("*");

​        source.registerCorsConfiguration("/**", config);

​        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));

​        bean.setOrder(0);

​        return bean;

​    }

}

1、公式文書https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

2、https://blog.csdn.net/weixin_33713503/article/details/88039675

https://www.jianshu.com/p/d05303d34222

https://www.cnblogs.com/helloz/p/10961039.html

2、https://blog.csdn.net/taiyangnimeide/article/details/78305131

3、https://blog.csdn.net/snowin1994/article/details/53035433

* * *

おすすめ

転載: www.cnblogs.com/wangdaijun/p/11348463.html