Spring Security – 允許列表 IP 範圍

Spring Security
Remote
1
04:56 AM · Nov 30 ,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"));
}

請注意,由於 IP 地址為“127.0.0.1”,我們無法訪問“/foos”資源,因為只有擁有“11.11.11.11”的 IP 地址的用户才能訪問它。

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();
    }
}

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

作為結果,只有具有白列的 IP 地址的用户才能訪問我們的系統。

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

6. 結論

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

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

發佈 評論

Some HTML is okay.