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
Newsletter
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

  • How to Build Your Own AI SRE From Scratch
  • Searching Kafka Without an Index: Lessons From Building Message Search for Kafdrop
  • Share Delta Lake Tables Between Databricks and Snowflake
  • DuckDB for Python Developers

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  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
·
Feb. 01, 21 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
11.6K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

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

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • 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