spring boot corsFilter 跨域配置 无法使用 refresh 刷新问题

为解决H5页面跨域调用后台服务接口问题,使用spring boot corsFilter 设置 跨域方法:代码如下
@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        if(RString.isBlank(AppResource.getProperty("AllowedOrigins"))){
        	corsConfiguration.addAllowedOrigin("*");
        }else{
        	corsConfiguration.setAllowedOrigins(Arrays.asList(AppResource.getProperty("AllowedOrigins").split(",")));
        }
        
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
        return new CorsFilter(source);
    }
}

 该方法实现了H5跨域功能,目前使用  静态文件读取配置文件并在启动时加载该拦截器

if(RString.isBlank(AppResource.getProperty("AllowedOrigins"))){//如果配置文件没有该数据,则所有页面都能跨域访问
        	corsConfiguration.addAllowedOrigin("*");
        }else{//指定部分域名允许跨域访问
        	corsConfiguration.setAllowedOrigins(Arrays.asList(AppResource.getProperty("AllowedOrigins").split(",")));
        }

该功能也实现了跨域设置,但是问题来了,我想要实时更新允许的域名,该怎么办:

想到了spring boot 安全检测的包 spring-boot-starter-actuator   使用refresh 方法功能

application.properties   启动配置文件   配置文件

#关闭安全校验校验   
management.security.enabled=false
#指定访问这些监控方法的端口,与逻辑接口端口分离。
management.port=18016
#指定地址,比如只能通过本机监控
management.address=
#启用shutdown
endpoints.shutdown.enabled=true

但是使用  refresh功能刷新程序后,允许跨域的域名没有发生改变

查询corsFilter  源码分析后发现

new CorsFilter(source)
源码
 * Copyright 2002-2016 the original author or authors.

package org.springframework.web.filter;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.Assert;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsProcessor;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.DefaultCorsProcessor;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * {@link javax.servlet.Filter} that handles CORS preflight requests and intercepts
 * CORS simple and actual requests thanks to a {@link CorsProcessor} implementation
 * ({@link DefaultCorsProcessor} by default) in order to add the relevant CORS
 * response headers (like {@code Access-Control-Allow-Origin}) using the provided
 * {@link CorsConfigurationSource} (for example an {@link UrlBasedCorsConfigurationSource}
 * instance.
 *
 * 

This is an alternative to Spring MVC Java config and XML namespace CORS configuration, * useful for applications depending only on spring-web (not on spring-webmvc) or for * security constraints requiring CORS checks to be performed at {@link javax.servlet.Filter} * level. * *

This filter could be used in conjunction with {@link DelegatingFilterProxy} in order * to help with its initialization. * * @author Sebastien Deleuze * @since 4.2 * @see CORS W3C recommendation */ public class CorsFilter extends OncePerRequestFilter { private final CorsConfigurationSource configSource; private CorsProcessor processor = new DefaultCorsProcessor(); /** * Constructor accepting a {@link CorsConfigurationSource} used by the filter * to find the {@link CorsConfiguration} to use for each incoming request. * @see UrlBasedCorsConfigurationSource */ public CorsFilter(CorsConfigurationSource configSource) { Assert.notNull(configSource, "CorsConfigurationSource must not be null"); this.configSource = configSource; } /** * Configure a custom {@link CorsProcessor} to use to apply the matched * {@link CorsConfiguration} for a request. *

By default {@link DefaultCorsProcessor} is used. */ public void setCorsProcessor(CorsProcessor processor) { Assert.notNull(processor, "CorsProcessor must not be null"); this.processor = processor; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (CorsUtils.isCorsRequest(request)) { CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request); if (corsConfiguration != null) { boolean isValid = this.processor.processRequest(corsConfiguration, request, response); if (!isValid || CorsUtils.isPreFlightRequest(request)) { return; } } } filterChain.doFilter(request, response); } }

以上红色标记为拦截器用到配置文件的方法

发现在初始化实例的时候,

private final CorsConfigurationSource configSource;

该配置类为final类型,在刷新程序实例后,该数据还是不会发生改变

问题找到了,那么接下来我们把final去掉就可以了

一下为解决方案

重写CorsFilter 方法,自定义  MyCorsFilter 方法

注入自定义配置文件类

CorsConfiguration 配置从自定义配置类中读取
package com.smk.common.interceptor;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsProcessor;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.DefaultCorsProcessor;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.OncePerRequestFilter;

import com.smk.common.interceptor.bean.CorsConfigBean;

public class MyCorsFilter extends OncePerRequestFilter{

	private CorsProcessor processor = new DefaultCorsProcessor();
	
	@Autowired
	private CorsConfigBean corsConfigBean;
	private final CorsConfigurationSource configSource;

	/**
	 * Constructor accepting a {@link CorsConfigurationSource} used by the filter
	 * to find the {@link CorsConfiguration} to use for each incoming request.
	 * @see UrlBasedCorsConfigurationSource
	 */
	public MyCorsFilter(CorsConfigurationSource configSource) {
		Assert.notNull(configSource, "CorsConfigurationSource must not be null");
		this.configSource = configSource;
	}

	

	/**
	 * Configure a custom {@link CorsProcessor} to use to apply the matched
	 * {@link CorsConfiguration} for a request.
	 * 

By default {@link DefaultCorsProcessor} is used. */ public void setCorsProcessor(CorsProcessor processor) { Assert.notNull(processor, "CorsProcessor must not be null"); this.processor = processor; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (CorsUtils.isCorsRequest(request)) { CorsConfiguration corsConfiguration = corsConfigBean.getCorsConfiguration(); //.getCorsConfiguration(request); if (corsConfiguration != null) { boolean isValid = this.processor.processRequest(corsConfiguration, request, response); if (!isValid || CorsUtils.isPreFlightRequest(request)) { return; } } } filterChain.doFilter(request, response); } }


自定义配置文件类 初始化 
CorsConfiguration 类
package com.smk.common.interceptor.bean;


import java.util.Arrays;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;

import com.smk.common.lang.RString;

import lombok.Data;

@RefreshScope
@Data
@Component
public class CorsConfigBean{
	
	
	@Value("${AllowedOrigins}")
	private  String allowedOrigins;
	
	private CorsConfiguration corsConfiguration;
	
	
	@PostConstruct
    public void init() {
		this.corsConfiguration =buildConfig();
    }
	
	public CorsConfiguration buildConfig() {
		  CorsConfiguration corsConfiguration = new CorsConfiguration();
		  if(RString.isBlank(allowedOrigins)){
		  	corsConfiguration.addAllowedOrigin("*");
		  }else{
		  	corsConfiguration.setAllowedOrigins(Arrays.asList(allowedOrigins.split(",")));
		  }
		  
		  corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
		  corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
		  return corsConfiguration;
		}
}
启动时实例化
@Bean
    public MyCorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        if(RString.isBlank(corsConfigBean.getAllowedOrigins())){
        	corsConfiguration.addAllowedOrigin("*");
        }else{
        	corsConfiguration.setAllowedOrigins(Arrays.asList(corsConfigBean.getAllowedOrigins().split(",")));
        }
        
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
        source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
        return new MyCorsFilter(source);
    }

你可能感兴趣的:(spring boot corsFilter 跨域配置 无法使用 refresh 刷新问题)