Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 884
valijon Avatar asked Jun 01 '17 08:06

valijon


People also ask

What is the use of WebSecurityConfigurerAdapter in spring boot?

configure. Deprecated. Used by the default implementation of authenticationManager() to attempt to obtain an AuthenticationManager . If overridden, the AuthenticationManagerBuilder should be used to specify the AuthenticationManager .

How do I whitelist an IP address in spring boot?

We can use hasIpAddress() to allow only users with a given IP address to access a specific resource. In this configuration, only users with the IP address “11.11. 11.11” will be able to access the ”/foos” resource.

What is the use of @EnableWebSecurity?

If you are using Spring and Spring Security WITHOUT Spring Boot, The @EnableWebSecurity does just you described in your original question: it will automatically define and configure several beans, the filter chain, etc. to enable basic security for a web application.

What is the use of WebSecurityConfigurerAdapter?

It allows configuring things that impact all of web security. WebSecurityConfigurerAdapter is a convenience class that allows customization to both WebSecurity and HttpSecurity. We can extend WebSecurityConfigurerAdapter multiple times (in distinct objects) to replicate the behavior of having multiple http elements.


2 Answers

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'))";
like image 71
dur Avatar answered Nov 05 '22 08:11

dur


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;
}
like image 24
superheroicCoding Avatar answered Nov 05 '22 09:11

superheroicCoding