1. 개요

이 예제에서는 Spring Security에서 IP 범위를 화이트리스트에 추가하는 방법에 대해 설명합니다 .

Java 및 XML 구성을 모두 살펴보겠습니다. 또한 사용자 지정 AuthenticationProvider 를 사용하여 IP 범위를 화이트리스트에 추가하는 방법도 알아봅니다 .

2. 자바 구성

먼저 Java 구성을 살펴보겠습니다.

hasIpAddress() 를 사용  하여 주어진 IP 주소를 가진 사용자만 특정 리소스에 액세스할 수 있도록 허용할 수 있습니다 .

다음은 hasIpAddress() 를 사용한 간단한 Security 구성 입니다 .

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/login").permitAll()
          .antMatchers("/foos/**").hasIpAddress("11.11.11.11")
          .anyRequest().authenticated()
          .and()
          .formLogin().permitAll()
          .and()
          .csrf().disable();
    }

    // ...

}

이 구성에서는 IP 주소가 "11.11.11.11"인 사용자만 "/foos" 리소스에 액세스할 수 있습니다. 또한 허용된 IP를 가진 사용자는 "/foos/" URL에 액세스하기 전에 로그인할 필요가 없습니다.

"11.11.11.11" IP를 가진 사용자가 먼저 로그인하도록 하려면 다음과 같은 형식의 식으로 메서드를 사용할 수 있습니다.

//...
.antMatchers("/foos/**")
.access("isAuthenticated() and hasIpAddress('11.11.11.11')")
//...

3. XML 구성

다음으로 XML 구성을 사용하여 IP 범위를 화이트리스트에 추가하는 방법을 살펴보겠습니다.

여기서도 hasIpAddress() 를 사용   합니다.

<security:http>
    <security:form-login/>
    <security:intercept-url pattern="/login" access="permitAll()" />
    <security:intercept-url pattern="/foos/**" access="hasIpAddress('11.11.11.11')" />
    <security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>

// ...

4. 라이브 테스트

이제 모든 것이 제대로 작동하는지 확인하는 간단한 라이브 테스트가 있습니다.

먼저 모든 사용자가 로그인 후 홈페이지에 액세스할 수 있는지 확인합니다.

@Test
public void givenUser_whenGetHomePage_thenOK() {
    Response response = RestAssured.given().auth().form("john", "123")
      .get("http://localhost:8082/");

    assertEquals(200, response.getStatusCode());
    assertTrue(response.asString().contains("Welcome"));
}

다음으로 인증된 사용자도 IP가 허용되지 않는 한 "/foos" 리소스에 액세스할 수 없도록 합니다.

@Test
public void givenUserWithWrongIP_whenGetFooById_thenForbidden() {
    Response response = RestAssured.given().auth().form("john", "123")
      .get("http://localhost:8082/foos/1");

    assertEquals(403, response.getStatusCode());
    assertTrue(response.asString().contains("Forbidden"));
}

"11.11.11.11"이 있는 사용자만 액세스할 수 있으므로 localhost "127.0.0.1"에서 "/foos" 리소스에 액세스할 수 없습니다.

5. 커스텀 AuthenticationProvider 를 사용한 화이트리스트

마지막으로 사용자 지정 AuthenticationProvider 를 빌드하여 IP 범위를 화이트리스트에 추가하는 방법을 살펴보겠습니다 .

우리는  hasIpAddress() 를 사용하여 IP 범위를 화이트리스트에 추가하는 방법과 이를 다른 표현식과 혼합하는 방법을 살펴보았습니다. 그러나 때로는 더 많은 Custom설정이 필요합니다 .

다음 예에서는 허용된 여러 IP 주소가 있으며 해당 IP 주소의 사용자만 시스템에 로그인할 수 있습니다.

@Component
public class CustomIpAuthenticationProvider implements AuthenticationProvider {
    
   Set<String> whitelist = new HashSet<String>();

    public CustomIpAuthenticationProvider() {
        whitelist.add("11.11.11.11");
        whitelist.add("12.12.12.12");
    }

    @Override
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
        String userIp = details.getRemoteAddress();
        if(! whitelist.contains(userIp)){
            throw new BadCredentialsException("Invalid IP Address");
        }
        //...
}

이제 Security 구성에서 CustomIpAuthenticationProvider 를 사용합니다.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private CustomIpAuthenticationProvider authenticationProvider;

    @Bean
    public InMemoryUserDetailsManager userDetailsService(HttpSecurity http) throws Exception {
        UserDetails user = User.withUsername("john")
            .password("{noop}123")
            .authorities("ROLE_USER")
            .build();
        http.getSharedObject(AuthenticationManagerBuilder.class)
            .authenticationProvider(authenticationProvider)
            .build();
        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/login")
            .permitAll()
            .antMatchers("/foos/**")
            .access("isAuthenticated() and hasIpAddress('11.11.11.11')")
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .permitAll()
            .and()
            .csrf()
            .disable();
        return http.build();
    }
}

여기서는 WebAuthenticationDetails getRemoteAddress() 메서드를 사용하여 사용자의 IP 주소를 얻었습니다.

결과적으로 허용된 IP를 가진 사용자만 시스템에 액세스할 수 있습니다.

이것은 기본 구현이지만  사용자의 IP를 사용하여 원하는 만큼 AuthenticationProvider 를 사용자 정의할 수 있습니다. 예를 들어 가입 시 사용자 세부 정보와 함께 IP 주소를 저장하고  AuthenticationProvider에서 인증하는 동안 이를 비교할 수 있습니다.

6. 결론

Java 및 XML 구성을 사용하여 Spring Security에서 IP 범위를 화이트리스트에 추가하는 방법을 배웠습니다. 또한 사용자 지정 AuthenticationProvider 를 구축하여 IP 범위를 화이트리스트에 추가하는 방법도 배웠습니다  .

전체 소스 코드는 GitHub 에서 찾을 수 있습니다 .

Security footer banner