Single role multiple IP addresses in Spring Security configuration
In my Spring Boot project I am trying to give access to several admin users with specific IP address.
Is it possible to map a single role to multiple IP addresses?
Here is the code from my security configuration which didn't work. (I am giving hard coded role name and ip addresses for simplicity)
@SuppressWarnings("ALL")
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
List<String> ipAddresses = new ArrayList<>();
ipAddresses.add("127.0.0.1");
ipAddresses.add("192.168.1.0/24");
ipAddresses.add("0:0:0:0:0:0:0:1");
for (String ip : ipAddresses) {
http.authorizeRequests().
antMatchers("/admin" + "/**")
.access("hasRole('admin') and hasIpAddress('" + ip + "')");
}
}
//some other configurations
}
URL of my request: http://localhost:9595/admin/checkappeals/211
Your for
loop results in following configuration:
@SuppressWarnings("ALL")
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('127.0.0.1')")
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('192.168.1.0/24')")
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('0:0:0:0:0:0:0:1')");
}
//some other configurations
}
So for URL:
http://localhost:9595/admin/checkappeals/211
only the first matcher is considered, see HttpSecurity#authorizeRequests:
Note that the matchers are considered in order. Therefore, the following is invalid because the first matcher matches every request and will never get to the second mapping:
http.authorizeRequests().antMatchers("/**").hasRole("USER").antMatchers("/admin/**") .hasRole("ADMIN")
You have to build something like:
http
.authorizeRequests()
.antMatchers("/admin/**").acces("hasRole('admin') and (hasIpAddress('127.0.0.1') or hasIpAddress('192.168.1.0/24') or hasIpAddress('0:0:0:0:0:0:0:1'))";
This is how you can join your comma separated ips into an expression for the .access() method:
private String createHasIpRangeExpression() {
String ipRanges= "127.0.0.1,192.168.1.0/24,0:0:0:0:0:0:0:1"
List<String> validIps = Arrays.asList(ipRanges.split("\\s*,\\s*"));
String hasIpRangeAccessExpresion = validIps.stream()
.collect(Collectors.joining("') or hasIpAddress('", "hasIpAddress('","')"));
return hasIpRangeAccessExpresion;
}