如何在 Spring 5.7+ 中通过 IP 地址和凭据限制对资源的访问

问题描述 投票:0回答:2

由于 Spring 5.6 中的 WebSecurityConfigurerAdapter 已被弃用,我们如何根据一组 IP 地址限制对 Web 应用程序资源的访问?我的目标是禁用默认的 spring 登录表单,但仍然仅从一组给定的 IP 地址使用某些凭据向应用程序发送发布请求。

我一直在Baeldung这里遵循Eugen的示例https://github.com/eugenp/tutorials/blob/4fa0844faf6f95bbde4a38d0b16cde066fd4d8af/spring-security-modules/spring-security-web-boot-1/src/main/java/com /baeldung/roles/ip/config/CustomIpAuthenticationProvider.java,这是为 Spring 5.6 编写的。我尝试升级到此处推荐的 SecurityFilterChain:https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter。然后,我在使用 SecurityFilterChain 的类上使用 @EnableWebSecurity 时禁用了 SecurityAutoConfiguration,但我无法让我的代码阻止来自某些 IP 地址和给定用户的请求。

下面是我的代码。

主应用程序

@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class MainApp {
    public static void main(String[] args) {
        SpringApplication.run(MainApp.class, args);
    }

}

配置类

@Configuration
@EnableWebSecurity
public class SecurityConfig  {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity security) throws Exception {

        security.csrf().disable().authorizeRequests().anyRequest().permitAll(); // Works for GET, POST, PUT, DELETE
        security.authenticationProvider(new CustomIpAuthenticationProvider());
        security.formLogin().disable();

        return security.build();
    }
}
    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

        UserDetails user = User.withUsername("test_user")
                .password(encoder.encode("password"))
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }
}

自定义身份验证提供商

public class CustomIpAuthenticationProvider implements AuthenticationProvider {

    Set<String> whitelist = new HashSet<>();

    public CustomIpAuthenticationProvider() {
        super();
        whitelist.add("11.11.11.11");
//        whitelist.add("0.0.0.0");
//        whitelist.add("127.0.0.1");
    }

    @Override
    public Authentication authenticate(Authentication auth){
        WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
        String userIp = details.getRemoteAddress();

        System.out.println(userIp);

        if (!whitelist.contains(userIp)) {
            throw new BadCredentialsException("Invalid IP Address");
        }

        final String name = auth.getName();
        final String password = auth.getCredentials().toString();

        if (name.equals("test_user") && password.equals("password")) {
            List<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new UsernamePasswordAuthenticationToken(name, password, authorities);
        }
        else{
            throw new BadCredentialsException("Invalid username or password");
        }


    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }
    }

单元测试来测试应用程序

@Test
    public void givenUserWithWrongIPForbidden() {
        Response response = RestAssured.given().auth().form("test_user", "password")
                .get(base + "/login");

        assertEquals(403, response.getStatusCode());
        assertTrue(response.asString().contains("Forbidden"));
    }
java spring authentication web-applications ip
2个回答
1
投票

我也有同样的问题。我最终改变了主意并使用了过滤器。这是一个示例


0
投票

我通过 Spring Security 版本 6.1 中的这个解决方案解决了这个问题

http.authorizeHttpRequests(requests -> requests
                .requestMatchers(
                .requestMatchers(HttpMethod.GET, "/actuator/**").access(new WebExpressionAuthorizationManager("hasIpAddress('127.0.0.1') or hasIpAddress('172.9.9.9')"))

使用此配置,您可以指定哪个端点限制在哪个 IP 列表中。 对于这部分

"hasIpAddress('127.0.0.1') or hasIpAddress('172.9.9.9')"
我编写了一个函数,它将生成受限制的IP:

private String convertActuatorIps(List<String> actuatorIps) {
    return actuatorIps.stream()
            .map("hasIpAddress('%s')"::formatted)
            .collect(Collectors.joining(" or "));
}
© www.soinside.com 2019 - 2024. All rights reserved.