从数据库中动态检索 Spring Boot CORS 配置以获取控制器中的特定方法

Posted

技术标签:

【中文标题】从数据库中动态检索 Spring Boot CORS 配置以获取控制器中的特定方法【英文标题】:Dynamicallly retrieve Spring Boot CORS Configuration from database for specific method in a Controller 【发布时间】:2020-06-02 02:17:46 【问题描述】:

我正在尝试使用

在控制器级别设置 CORS 配置
@CrossOrigin on Controller and Handler Method

public class AccountController 

@CrossOrigin("retreive data from DB")
@RequestMapping("/id")
public Account retrieve(@PathVariable Long id) 
    // ...

我尝试过使用下面,但它仅在 spring boot 启动时设置,并且仅在下次重新启动服务时才进行更改...

@Bean
public CorsFilter corsFilter() 
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
   // CorsConfiguration config = jHipsterProperties.getCors();

       CorsConfiguration config=CorsService.fetchCorsConfigFromDb;
    if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) 
        log.debug("Registering CORS filter");
        source.registerCorsConfiguration("/api/**", config);
        source.registerCorsConfiguration("/management/**", config);
        source.registerCorsConfiguration("/v2/api-docs", config);
    
    return new CorsFilter(source);

fetchCorsConfigFromDb 将从数据库中获取数据。仅当 Spring Boot App 重新启动时才会反映来自 DB 的任何更改...

【问题讨论】:

【参考方案1】:

要实现此功能,您可以使用基本过滤器,您可以在其中编写自定义数据库逻辑,以根据某些数据库属性值将 CORS 标头添加到您的请求中。

您可以参考下面的示例来使用 spring-data-jpa 实现此功能。

将数据库连接属性添加到 application.properties 文件

application.properties

spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update

spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=root

创建具有以下属性的实体以将 URL 保存在数据库中

Cors.java

@Entity
@Getter
@Setter
public class Cors 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String url;
    private boolean isAllowed;

并且在存储库中添加了一个findByUrl 方法来根据 URL 从数据库中获取价值

CorsRepository.java

public interface CorsRepository extends JpaRepository<Cors,Long> 
    Optional<Cors> findByUrl(String url);

下面是我的过滤器来拦截请求并进行 DB 调用,如果 isAllowed 为真,那么我添加 cors 标头以发出成功的请求

CorsFilter.java

@Component
public class CorsFilter implements Filter 
    @Autowired
    CorsRepository corsRepository;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException  

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
        HttpServletRequest request = (HttpServletRequest) req;
        String url = request.getRequestURI().toString();
        System.out.println(url);

        Optional<Cors> cors = corsRepository.findByUrl(url);
        if(cors.isPresent() && cors.get().isAllowed())
            HttpServletResponse response = (HttpServletResponse) res;

            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
        
        chain.doFilter(req, res);
    

    @Override
    public void destroy()  

您可以像这样创建示例控制器:

CorsTesterController.java

@RestController
public class CorsTesterController 

    @GetMapping("/api/v1/test")
    String getResponse()
        return "test response";
    

并将值插入 DB 以允许/禁止 url 来测试此示例代码。

testdb=# select * from cors;
 id | is_allowed |       url
----+------------+-----------------
  1 | f          | /api/v1/block
  2 | t          | /api/v1/allowed

【讨论】:

太棒了!!好主意 。如果您发现问题相关。请支持@Ajit Soman 的问题 为什么不自动装配 CorsRepository 而不是在 ApplicationCONtext 上使用 getBean()? 你可以查看这个链接:***.com/questions/32494398/… @GaëlMarziou,你是对的。 @Autowiring 将在带有@Component 的过滤器中工作。注释。 @MohammadJaved。我已经根据评论更新了答案【参考方案2】:

发给 CorsService.fetchCorsConfigFromDb; 它应该从缓存中加载

然后您可以在运行时更新您的缓存

你应该实现CorsService.fetchCorsConfig();

    此方法应首先在缓存中查找任何 cors 配置,如果找到任何配置,则直接从缓存中加载它,否则您将从 db 中检索 cors 并更新您的缓存 create update cors at runtime method CorsService.updateCorsConfig(); ,这应该更新你在 db 中的 cors 然后更新缓存。

【讨论】:

谢谢!!如果您发现问题相关。请为问题投票

以上是关于从数据库中动态检索 Spring Boot CORS 配置以获取控制器中的特定方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Spring Boot 项目中的子子表中检索数据?

如何在 Spring Boot 中使用特定日期范围和聚合从 MongoDB 数据库中检索数据?

如何从 AWS API Gateway 自定义授权方检索 Spring Boot 中的上下文对象?

从其他实体检索ID时的Spring Boot JPA反序列化问题

spring boot 并行传出请求的最佳实践是啥?

在 Spring Boot 中使用 Copy 命令从 Postgres 导出数据