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.
 *
 * <p>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.
 *
 * <p>This filter could be used in conjunction with {@link DelegatingFilterProxy} in order
 * to help with its initialization.
 *
 * @author Sebastien Deleuze
 * @since 4.2
 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommendation</a>
 */
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.
	 * <p>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.
	 * <p>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);
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值