简体   繁体   English

动态检索 Spring 引导 CORS 从数据库配置 Controller 中的特定方法

[英]Dynamicallly retrieve Spring Boot CORS Configuration from database for specific method in a Controller

I am trying to set the CORS configuration at Controller level using我正在尝试使用 Controller 级别设置 CORS 配置

@CrossOrigin on Controller and Handler Method

public class AccountController {

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

} }

I have tried using below but its set only when the spring boot starts and takes changes only when the service is restarted next time...我尝试在下面使用,但它仅在 spring 引导启动时设置,并且仅在下次重新启动服务时才进行更改...

@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 will fetch data from DB. fetchCorsConfigFromDb将从数据库中获取数据。 Any changes from DB will be reflected only when Spring Boot App is restarted...只有当 Spring Boot App 重新启动时,DB 的任何更改才会反映出来...

To implement this functionality you can use a basic filter in which you can write your custom database logic to add CORS header to your request based on some database attribute value.要实现此功能,您可以使用基本过滤器,您可以在其中编写自定义数据库逻辑,以根据某些数据库属性值将 CORS 标头添加到您的请求中。

You can refer to below example to implement this functionality using spring-data-jpa.您可以参考以下示例使用 spring-data-jpa 实现此功能。

Add DB connection attributes to application.properties file将数据库连接属性添加到 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

Create a entity with below attribute to save URL in DB创建具有以下属性的实体以将 URL 保存在数据库中

Cors.java驱动程序

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

And in the repository added a findByUrl method to get value from DB based on URL并在存储库中添加了一个findByUrl方法以根据 URL 从数据库中获取值

CorsRepository.java CorsRepository.java

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

Below is my filter to intercept request and make DB call and if isAllowed is true then i add cors headers to make a successful request下面是我的过滤器拦截请求并进行数据库调用,如果isAllowed为真,那么我添加 cors 标头以发出成功的请求

CorsFilter.java 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() { }
}

You can create a sample controller like this:您可以像这样创建一个示例控制器:

CorsTesterController.java CorsTesterController.java

@RestController
public class CorsTesterController {

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

and insert values to DB to allow/disallow a url to test this example code.并将值插入 DB 以允许/禁止 url 来测试此示例代码。

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

For CorsService.fetchCorsConfigFromDb;对于CorsService.fetchCorsConfigFromDb; it should load from cache它应该从缓存加载

then you can update your cache at run-time然后你可以在运行时更新你的缓存

you should implement CorsService.fetchCorsConfig();你应该实现CorsService.fetchCorsConfig();

  1. this method should look for any cors configuration in cache first ,if there any configurations found load it directly from cache else you will retrive cors from db and update your cache此方法应首先在缓存中查找任何 cors 配置,如果找到任何配置,则直接从缓存加载它,否则您将从 db 检索 cors 并更新缓存
  2. create update cors at runtime method CorsService.updateCorsConfig();在运行时方法CorsService.updateCorsConfig();创建更新 cors CorsService.updateCorsConfig(); , this should update your cors in db and then update cache . ,这应该更新您在 db 中的 cors ,然后更新缓存。

Usually reading properties from database - not secured variant and if you lost connection to database you service can startup not correct.通常从数据库读取属性 - 不是安全变体,如果您失去与数据库的连接,您的服务可能无法正确启动。

Anyway you can do it, but would like to draw attention to default support by Spring a lot of remote properties sources无论如何你可以做到,但想提请注意默认支持 Spring 很多远程属性来源

For loading custom properties you may use要加载自定义属性,您可以使用
spring.config.import=optional:file:./cors.yml
or from java args或来自 java 参数
-Dspring.config.import=optional:file:./cors.yml
This method support reading from file , from url , config server此方法支持文件读取,从urlconfig server
Spring documentation about this Spring 关于这个的文档

For reading CORS configuration from properties file you may use library (I'm developer of this)要从属性文件中读取 CORS 配置,您可以使用库(我是这个的开发者)

<dependency>
  <groupId>io.github.iruzhnikov</groupId>
  <artifactId>spring-webmvc-cors-properties-autoconfigure</artifactId>
  <version>VERSION</version>
</dependency>

and properties config和属性配置

spring:
  web:
    cors:
      enabled: true
      mappings: #spring.web.cors.mappings.<any_name>.<property>: <value>
        anyName: #just any name, just for grouping properties under the same path pattern (not used in internal logic)
          paths: #ant style path pattern, ATTENTION! not ordered, /** pattern override all other pattern
            - /path/to/api
            - /path/to/api/**
          #allowed-origins: "*"
          allowed-methods: GET #Enable override all defaults! If disabled: a lot more from all the controller methods included from the path pattern matches
          #allowed-headers: "*"
          #exposed-headers: ('*' - not-supported)
          #allow-credentials: true
          allowed-origin-patterns: .*
          #max-age: PT30M

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM