DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Building a CRUD Application With Spring and SimpleJdbcMapper
  • How to Marry MDC With Spring Integration
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux

Trending

  • Chaos Engineering Has a Blind Spot. Agentic AI Lives in It.
  • Stateless JWT Auth Microservice Architecture With Spring Boot 3 and Redis Sentinel
  • Pragmatica Aether: Let Java Be Java
  • Event-Driven Pipelines With Apache Pulsar and Go
  1. DZone
  2. Coding
  3. Frameworks
  4. Customizing CORS Filtering at Runtime

Customizing CORS Filtering at Runtime

Let's make CORS work for you.

By 
Oguzhan Dogan user avatar
Oguzhan Dogan
·
Feb. 01, 21 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
11.5K Views

Join the DZone community and get the full member experience.

Join For Free

Cross-origin resource sharing (CORS) is a mechanism that controls the AJAX calls to your resources outside the current origin. In some cases, you need to allow some origins to make these kinds of calls. For example, if you have a SAAS based product, there will be some clients who are connecting to your API and making AJAX calls.

In Spring, there are several ways to check the origin, method, headers, etc., of incoming requests.

You can use WebSecurityConfigurerAdapter in Spring Security, and WebMvcConfigurer, @CrossOrigin annotation, CorsFilter in Spring MVC.

We are providing a SaaS-based payment and wallet application. We're serving our payment page via JavaScript, and so many CORS requests come from our clients. In our case, we needed to change allowed origins dynamically because some merchants may be added, deleted, or updated.

Our tech stack in this project consists of Spring Boot, Spring Cloud, Netflix OSS, and our gateway is Netflix Zuul.

I thought filtering CORS requests in our gateway was the best choice, and I started to review the solutions which Spring provided us, and I selected creating a CorsFilter bean in one of our Configuration classes. Our configuration is like below.

Java
 




x


 
1
@Bean
2
public CorsFilter corsFilter() {
3
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
4
    final CorsConfiguration config = new CorsConfiguration();
5
    config.setAllowCredentials(true);
6
    config.setAllowedOrigins(clientService.getClientOrigins());
7
    config.addAllowedHeader("*");
8
    config.addAllowedMethod("OPTIONS");
9
    config.addAllowedMethod("HEAD");
10
    config.addAllowedMethod("GET");
11
    config.addAllowedMethod("PUT");
12
    config.addAllowedMethod("POST");
13
    config.addAllowedMethod("DELETE");
14
    config.addAllowedMethod("PATCH");
15
    source.registerCorsConfiguration("/**", config);
16
    return new CorsFilter(source);
17
}



After making some tests, I noticed that allowed origins can not be updated after the bean is created, as you guess. Because CorsFilter's configSource attribute is set while the bean is created and can not be changed after.

I reviewed the CorsFilter class and see what it does inside. It simply extends OncePerRequestFilter, sets the CorsConfigurationSource object in its constructor, and does all the filtering in doFilterInternal method with the help of DefaultCorsProcessor.

I decided to write our CorsFilter which extends OncePerRequestFilter, uses DefaultCorsProcessor to process the CORS requests, does the same thing as CorsFilter does in doFilterInternal method, and creates CorsConfiguration at runtime. Also, I needed to create a new service and added it as a dependency to get the origins dynamically from the data source. I created OriginService class, which gets the origins of the clients from our data source. The main difference of our custom cors filter is creating CorsConfiguration at runtime by getting the origins via OriginService.

Our CustomCorsFilter class is like below.

Java
 




x
1
29


 
1
@Component
2
public class CustomCorsFilter extends OncePerRequestFilter {
3

          
4
    @Autowired
5
    OriginService originService;
6

          
7
    private final CorsProcessor processor = new DefaultCorsProcessor();
8

          
9
    @Override
10
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
11

          
12
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
13
        CorsConfiguration config = new CorsConfiguration();
14
        config.setAllowCredentials(true);
15
        List<String> origins = originService.getOrigins();
16
        config.setAllowedOrigins(origins);
17
        config.setAllowedMethods(List.of("OPTIONS", "HEAD", "GET", "POST"));
18
        config.addAllowedHeader("*");
19
        source.registerCorsConfiguration("/**", config);
20
        CorsConfiguration corsConfiguration = source.getCorsConfiguration(request);
21
        boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
22
        if (!isValid || CorsUtils.isPreFlightRequest(request)) {
23
            return;
24
        }
25
        filterChain.doFilter(request, response);
26
    }
27
}



Our CorsFilter is doing exactly what we want. When clients' origins are changed, CorsConfiguration is changed and Cors filtering starts to be done for the new origin list.

This is our solution for our problem, there may be some different and simpler solutions for this case. But our solution is working fine. The class may be changed for a very flexible configuration. It depends on your needs.

Spring Framework

Opinions expressed by DZone contributors are their own.

Related

  • Building a CRUD Application With Spring and SimpleJdbcMapper
  • How to Marry MDC With Spring Integration
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook