1. Overview
1.概述
In this tutorial, we’ll discuss how to whitelist IP ranges in Spring Security.
在本教程中,我们将讨论如何在Spring Security中白名单IP范围。
We’ll take a look at both Java and XML configurations. We’ll also see how to whitelist IP range using a custom AuthenticationProvider.
我们将看一下Java和XML的配置。我们还将看到如何使用一个自定义的AuthenticationProvider来白名单IP范围。
2. Java Configuration
2.Java配置
First, let’s explore the Java configuration.
首先,我们来探讨一下Java的配置。
We can use hasIpAddress() to allow only users with a given IP address to access a specific resource.
我们可以使用hasIpAddress()来只允许拥有特定IP地址的用户访问特定资源。
Here’s a simple security configuration using hasIpAddress():
下面是一个使用hasIpAddress()的简单安全配置。
@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();
}
// ...
}
In this configuration, only users with the IP address “11.11.11.11” will be able to access the ”/foos” resource. There’s also no need for users with the whitelisted IP to log in before they access the “/foos/” URL.
在这个配置中,只有IP地址为 “11.11.11.11 “的用户才能够访问”/foos “资源。也不需要让拥有白名单IP的用户在访问”/foos/”URL前登录。
If we want users with “11.11.11.11” IP to log in first, we can use the method in an expression of the form:
如果我们想让IP为 “11.11.11.11 “的用户先登录,我们可以在一个表达式中使用该方法。
//...
.antMatchers("/foos/**")
.access("isAuthenticated() and hasIpAddress('11.11.11.11')")
//...
3. XML Configuration
3.XML配置
Next, let’s see how to whitelist an IP range using XML configuration:
接下来,让我们看看如何使用XML配置将一个IP范围列入白名单。
We’ll use hasIpAddress() here as well:
我们在这里也将使用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. Live Test
4.现场测试
Now, here’s a simple live test to make sure everything is working properly.
现在,这里有一个简单的现场测试,以确保一切都在正常工作。
First, we’ll make sure any user can access the home page after login:
首先,我们要确保任何用户在登录后都能访问主页。
@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"));
}
Next, we’ll make sure even authenticated users can’t access the “/foos” resource unless their IP is whitelisted:
接下来,我们将确保即使是认证用户也不能访问”/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"));
}
Note that we aren’t able to access “/foos” resource from localhost “127.0.0.1” as only users with “11.11.11.11” are able to access it.
注意,我们无法从本地主机 “127.0.0.1 “访问”/foos “资源,因为只有 “11.11.11.11 “的用户能够访问它。
5. Whitelisting Using a Custom AuthenticationProvider
5.使用自定义AuthenticationProvider的白名单
Finally, we’ll see how to whitelist an IP range by building a custom AuthenticationProvider.
最后,我们将看到如何通过建立一个自定义的AuthenticationProvider来白名单一个IP范围。
We’ve seen how we can use hasIpAddress() to whitelist an IP range and how to mix it with other expressions. But sometimes, we need more customization.
我们已经看到我们如何使用hasIpAddress()来对一个IP范围进行白名单,以及如何将其与其他表达式混合。但有时,我们需要更多的定制。
In the following example, we have multiple IP addresses whitelisted and only users from those IP addresses can log in to our system:
在下面的例子中,我们有多个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");
}
//...
}
Now, we’ll use our CustomIpAuthenticationProvider in our security configuration:
现在,我们将在安全配置中使用我们的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();
}
}
Here, we used the WebAuthenticationDetails getRemoteAddress() method to obtain a user’s IP address.
这里,我们使用WebAuthenticationDetails getRemoteAddress()方法来获取用户的IP地址。
As a result, only users with whitelisted IP will be able to access our system.
因此,只有拥有白名单IP的用户才能够访问我们的系统。
This is a basic implementation, but we can customize our AuthenticationProvider as much as we want using a user’s IP. For example, we can store the IP address with user details on signup and compare it during authentication in our AuthenticationProvider.
这是一个基本的实现,但是我们可以使用用户的IP来定制我们的AuthenticationProvider,只要我们想。例如,我们可以在注册时将IP地址与用户的详细信息存储在一起,并在我们的AuthenticationProvider.验证过程中进行比较。
6. Conclusion
6.结论
We learned how to whitelist an IP range in Spring Security using Java and XML configuration. We also learned how to whitelist an IP range by building a custom AuthenticationProvider.
我们学习了如何使用Java和XML配置在Spring Security中对IP范围进行白名单。我们还学习了如何通过建立一个自定义的AuthenticationProvider来白名单一个IP范围。
The full source code can be found over on GitHub.
完整的源代码可以在GitHub上找到over。