Spring Security multiple url ruleset not working together
I have an HTTP Spring Security configuration that appears to work when I comment out each individual aspect but it doesn't work when I combine the Spring Security rules together, so I know the problem is not with the regexMatcher
or the antMatcher
but with the rules applied in combination.
Here is my Spring Security class:
package com.driver.website.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.servlet.http.HttpServletRequest;
import java.security.AccessControlContext;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${widget.headers.xframeoptions.domains.allowed}")
private String allowedXFrameOptions;
@Value("${widget.headers.origins.allowed}")
private String allowedOrigins;
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.exceptionHandling().accessDeniedPage("/login")
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/myaccount", true).permitAll()
.and()
.authorizeRequests()
.antMatchers("/**").permitAll();
http.regexMatcher("^((?!(/widget|/assistedSearch)).)*$")
.headers().frameOptions().disable()
.regexMatcher("^((?!(/widget|/assistedSearch)).)*$")
.headers()
.xssProtection()
.contentTypeOptions()
.addHeaderWriter(new StaticHeadersWriter("X-FRAME-OPTIONS", "SAMEORIGIN"));
http.antMatcher("/widget")
.headers()
.frameOptions()
.disable()
.antMatcher("/widget")
.headers()
.addHeaderWriter(new StaticHeadersWriter("X-FRAME-OPTIONS", "ALLOW-FROM " + allowedXFrameOptions));
http.requestMatchers().antMatchers("/assistedSearch", "/widget")
.and()
.headers()
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", allowedOrigins))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "GET, POST"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Content-Type"));
// @formatter:on
}
}
The rules should be...
- For all urls but not /widget and /assistedSearch we should add the SAMEORIGIN X-Frame-Options header
- For the
/widget
endpoint we should add the X-Frame-Options: ALLOW-FROM header - For the
/widget
and/assistedSearch
endpoints we should add theAccess-Control-Allow-Origin
,Access-Control-Allow-Methods
andAccess-Control-Allow-Headers
headers
As I mentioned above if I comment out the For all urls
ruleset then the other two work in unison, but with the For all urls
rule uncommented none of the headers appear.
Does anyone have any ideas why this might be? How do you add multiple rulesets in Spring Security and override existing rulesets with new ones?
I tried
http.antMatcher("/widget")
.headers()
.frameOptions()
.disable()
Which again appears to work on it's own but not in combination.
Thanks in advance!
You override your previous matchers, see HttpSecurity.html#antMatcher:
Invoking
antMatcher(String)
will override previous invocations ofmvcMatcher(String)}
,requestMatchers()
,antMatcher(String)
,regexMatcher(String)
, andrequestMatcher(RequestMatcher)
.
and HttpSecurity.html#regexMatcher:
Invoking
regexMatcher(String)
will override previous invocations ofmvcMatcher(String)}
,requestMatchers()
,antMatcher(String)
,regexMatcher(String)
, andrequestMatcher(RequestMatcher)
.
If you want more than one configuration of HttpSecurity
, see Spring Security Reference:
We can configure multiple HttpSecurity instances just as we can have multiple
<http>
blocks. The key is to extend theWebSecurityConfigurationAdapter
multiple times. For example, the following is an example of having a different configuration for URL’s that start with/api/
.@EnableWebSecurity public class MultiHttpSecurityConfig { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { 1 auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); } @Configuration @Order(1) 2 public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http .antMatcher("/api/**") 3 .authorizeRequests() .anyRequest().hasRole("ADMIN") .and() .httpBasic(); } } @Configuration 4 public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin(); } } }