在运行时将 CORS 映射动态添加到 Rest Controller

Posted

技术标签:

【中文标题】在运行时将 CORS 映射动态添加到 Rest Controller【英文标题】:Dynamically add CORS Mappings to Rest Controller at runtime 【发布时间】:2018-05-19 01:42:52 【问题描述】:

你好!我是 Spring Boot 的初学者。我有一个使用 Rest Controller 的简单 Java Spring Boot 应用程序。一些控制器的端点暴露给 CORS 请求。我发现可以通过在方法上方添加 @CrossOrigin(origins ="..") 注释来允许 CORS 请求。 我的问题是我目前不知道所有的起源,并且必须稍后在我的 Spring Boot 应用程序运行时添加其中一些。 是否有一种方法可以手动将新的源地址添加到我的 Rest Controller 的某些端点?例如。在我的休息控制器中有一个端点,允许特定用户(例如管理员)将新的 cors-origins 添加到休息端点?如果是:请举一个简单的例子。

【问题讨论】:

您是否考虑过使用过滤器将这种横切关注点外部化? 问题解决了吗?如果有,请您回答一下好吗? 【参考方案1】:

以下内容在 Spring 2.4 中为我工作:

import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig 

    @Bean
    public CorsFilter corsFilter() 
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();

        final String corsAllowedOrigins = System.getenv("CORS_ALLOWED_ORIGINS");

        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setAllowedOrigins(Arrays.asList(corsAllowedOrigins.split(",")));
        corsConfiguration.setAllowedMethods(Arrays.asList(CorsConfiguration.ALL));
        corsConfiguration.setAllowedHeaders(Arrays.asList(CorsConfiguration.ALL));

        source.registerCorsConfiguration("/**", corsConfiguration);

        return new CorsFilter(source);
    


【讨论】:

【参考方案2】:

我认为这可以通过实现您自己的org.springframework.web.cors.CorsProcessor 来实现。查看org.springframework.web.filter.CorsFilter 的实现,可以通过方法public void setCorsProcessor(CorsProcessor processor) 使用您的自定义CorsProcessor 进行配置。

然后我会建议实现您自己的 CorsProcessor 并在方法 process 中处理您的自定义规则。

或者另一种选择是在 Spring Security Config 中设置自己的 CorsConfigurationSource。例如

@Override
 protected void configure(HttpSecurity http) throws Exception 
        http.cors().configurationSource(new CustomConfigSource());

CorsConfigurationSource 提供了一种方法 CorsConfiguration getCorsConfiguration(HttpServletRequest request);,您可以在其中处理特定的 CORS 处理。

【讨论】:

感谢您的回答。不幸的是,我有点困惑。我应该把自己的 CorsProcessor 放在哪里,我应该如何调用 getCorsConfiguration(HttpServletRequest req) 方法?我的 Rest Controller 中的任何地方都没有 HttpServletRequest 类型的参数。 ...如您所见,我是一个真正的初学者 我建议采用我提供的第二个选项。在 Spring Security Config 中将您自己的 ConfigurationSource 添加到您的 cors 配置中。然后框架将为每个请求调用方法getCorsConfiguration(HttpServletRequest request);【参考方案3】:

您可以通过res.addHeader("Access-Control-Allow-Origin","what you want here like http/.....");直接将其添加到HttpServletResponse res中

@RequestMapping(value="/getbot/id", 
       method = RequestMethod.POST,
       headers="Accept=application/json") 
@ResponseBody public String getbot(HttpServletResponse res)  
          res.addHeader("Access-Control-Allow-Origin","*");
          ...

我试过用springboot没有办法做到这一点,因为默认的cors处理程序会覆盖你的标题,我没有找到阻止它的方法 我认为我们需要为我们无法动态执行的 springboot 编写 servlet

【讨论】:

【参考方案4】:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException 
    response.addHeader("Access-Control-Allow-Origin", "*");

    if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) 
        LOG.trace("Sending Header....");
        // CORS "pre-flight" request
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");

        response.addHeader("Access-Control-Allow-Headers", "Content-Type");
        response.addHeader("Access-Control-Max-Age", "1");
    

    filterChain.doFilter(request, response);

请使用过滤器cros_filter

【讨论】:

以上是关于在运行时将 CORS 映射动态添加到 Rest Controller的主要内容,如果未能解决你的问题,请参考以下文章

在C语言中,如何给函数分配内存?

Angular 2 + CORS + 带有 Spring Security 的 Spring Boot Rest Controller

django-cors-headers 不适用于 DRF(Django Rest 框架)

无法为JAX-B生成架构,仅在CORS调用REST服务期间发生

在运行时(动态)将 EditorAttribute 添加到对象的特殊属性

单击按钮时将单元格动态添加到 UItableview