知識庫 / Spring / Spring Security RSS 訂閱

Spring Security – 允許列表 IP 地址範圍

Spring Security
HongKong
6
01:40 PM · Dec 06 ,2025

1. 概述

本教程將討論如何在 Spring Security 中使用白名單(IP 範圍)。

我們將研究 Java 和 XML 配置。 此外,我們還將看到如何使用自定義 AuthenticationProvider 來白名單 IP 範圍。

2. Java 配置文件

首先,讓我們探討 Java 配置文件。

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.requestMatchers("/login").permitAll()
                        .requestMatchers("/foos/**")
                        .access(new WebExpressionAuthorizationManager("isAuthenticated() and hasIpAddress('11.11.11.11')")).anyRequest().authenticated())
            .formLogin(AbstractAuthenticationFilterConfigurer::permitAll)
            .csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }
}

在這種配置下,僅限擁有 IP 地址“11.11.11.11”的用户才能訪問“/foos”資源。同時,擁有白名單 IP 地址的用户無需在訪問“/foos/” URL 之前進行登錄。

如果我們希望擁有“11.11.11.11” IP 地址的用户首先進行登錄,則可以使用以下形式的表達式中的方法:

//...
.requestMatchers("/foos/**")
.access(new WebExpressionAuthorizationManager("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"));
}

接下來,我們確保即使是經過身份驗證的用户也無法訪問“/foos”資源,除非他們的 IP 地址已添加到白名單中:

@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"));
}

請注意,我們無法從 localhost “127.0.0.1” 訪問 “/foos” 資源,因為只有擁有 “11.11.11.11” 權限的用户才能訪問該資源。

5. 使用自定義 AuthenticationProvider 進行白名單

最後,我們將看到如何通過構建自定義 AuthenticationProvider 來白名單一個 IP 範圍。

我們已經瞭解瞭如何使用 hasIpAddress() 來白名單一個 IP 範圍,以及如何將其與其他表達式混合使用。但有時,我們需要更多的自定義。

在以下示例中,我們白名單了多個 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");
        }
        //...
}

現在,我們將使用我們的 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.authorizeHttpRequests(
                authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.requestMatchers("/login").permitAll()
                        .requestMatchers("/foos/**")
                        .access(new WebExpressionAuthorizationManager("isAuthenticated() and hasIpAddress('11.11.11.11')")).anyRequest().authenticated())
            .formLogin(AbstractAuthenticationFilterConfigurer::permitAll)
            .csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }
}

在這裏,我們使用 getRemoteAddress() 方法獲取用户的 IP 地址。

因此,只有白名單中的 IP 地址的用户才能訪問我們的系統。

這是一個基本的實現,但我們可以通過使用用户的 IP 地址自定義我們的 AuthenticationProvider,例如,我們可以將 IP 地址與用户詳情一起存儲在註冊時,並在我們的 AuthenticationProvider 中進行身份驗證時進行比較。

6. 結論

我們學習瞭如何使用 Java 和 XML 配置在 Spring Security 中白名單 IP 地址範圍。我們還學習了通過構建自定義 AuthenticationProvider 來白名單 IP 地址範圍的方法。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.