Merge Formatting Changes
Issue gh-8945
This commit is contained in:
@@ -16,8 +16,16 @@
|
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -39,16 +47,14 @@ import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.List;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import static java.util.Collections.singleton;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
|
||||
public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
|
||||
static Integer port;
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@@ -72,37 +78,13 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("ROLE_");
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class DefaultLdapConfig extends BaseLdapProviderConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
}
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void groupRolesCustom() {
|
||||
this.spring.register(GroupRolesConfig.class).autowire();
|
||||
LdapAuthenticationProvider provider = ldapProvider();
|
||||
|
||||
assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute")).isEqualTo("group");
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupRolesConfig extends BaseLdapProviderConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupRoleAttribute("group");
|
||||
}
|
||||
// @formatter:on
|
||||
assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute"))
|
||||
.isEqualTo("group");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,20 +92,8 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
this.spring.register(GroupSearchConfig.class).autowire();
|
||||
LdapAuthenticationProvider provider = ldapProvider();
|
||||
|
||||
assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter")).isEqualTo("ou=groupName");
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupSearchConfig extends BaseLdapProviderConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchFilter("ou=groupName");
|
||||
}
|
||||
// @formatter:on
|
||||
assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter"))
|
||||
.isEqualTo("ou=groupName");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -135,20 +105,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
.extracting("searchScope").isEqualTo(SearchControls.SUBTREE_SCOPE);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchFilter("ou=groupName")
|
||||
.groupSearchSubtree(true);
|
||||
}
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rolePrefixCustom() {
|
||||
this.spring.register(RolePrefixConfig.class).autowire();
|
||||
@@ -157,39 +113,13 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("role_");
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class RolePrefixConfig extends BaseLdapProviderConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.rolePrefix("role_");
|
||||
}
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindAuthentication() throws Exception {
|
||||
this.spring.register(BindAuthenticationConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class BindAuthenticationConfig extends BaseLdapServerConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
}
|
||||
// @formatter:on
|
||||
.andExpect(authenticated().withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
||||
}
|
||||
|
||||
// SEC-2472
|
||||
@@ -198,26 +128,13 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
this.spring.register(PasswordEncoderConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
|
||||
.andExpect(authenticated().withUsername("bcrypt").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class PasswordEncoderConfig extends BaseLdapServerConfig {
|
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.passwordEncoder(new BCryptPasswordEncoder())
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
}
|
||||
// @formatter:on
|
||||
.andExpect(authenticated().withUsername("bcrypt")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
||||
}
|
||||
|
||||
private LdapAuthenticationProvider ldapProvider() {
|
||||
return ((List<LdapAuthenticationProvider>) ReflectionTestUtils.getField(authenticationManager, "providers")).get(0);
|
||||
return ((List<LdapAuthenticationProvider>) ReflectionTestUtils.getField(this.authenticationManager,
|
||||
"providers")).get(0);
|
||||
}
|
||||
|
||||
private LdapAuthoritiesPopulator getAuthoritiesPopulator(LdapAuthenticationProvider provider) {
|
||||
@@ -228,23 +145,150 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
return (GrantedAuthoritiesMapper) ReflectionTestUtils.getField(provider, "authoritiesMapper");
|
||||
}
|
||||
|
||||
static int getPort() throws IOException {
|
||||
if (port == null) {
|
||||
ServerSocket socket = new ServerSocket(0);
|
||||
port = socket.getLocalPort();
|
||||
socket.close();
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig {
|
||||
static class DefaultLdapConfig extends BaseLdapProviderConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupRolesConfig extends BaseLdapProviderConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupRoleAttribute("group");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupSearchConfig extends BaseLdapProviderConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchFilter("ou=groupName");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchFilter("ou=groupName")
|
||||
.groupSearchSubtree(true);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class RolePrefixConfig extends BaseLdapProviderConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.rolePrefix("role_");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class BindAuthenticationConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class PasswordEncoderConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.passwordEncoder(new BCryptPasswordEncoder())
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
abstract static class BaseLdapServerConfig extends BaseLdapProviderConfig {
|
||||
|
||||
@Bean
|
||||
public ApacheDSContainer ldapServer() throws Exception {
|
||||
ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
||||
ApacheDSContainer ldapServer() throws Exception {
|
||||
ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org",
|
||||
"classpath:/test-server.ldif");
|
||||
apacheDSContainer.setPort(getPort());
|
||||
return apacheDSContainer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalAuthentication
|
||||
@Import(ObjectPostProcessorConfiguration.class)
|
||||
static abstract class BaseLdapProviderConfig extends WebSecurityConfigurerAdapter {
|
||||
abstract static class BaseLdapProviderConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public BaseLdapPathContextSource contextSource() throws Exception {
|
||||
BaseLdapPathContextSource contextSource() throws Exception {
|
||||
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
|
||||
"ldap://127.0.0.1:" + getPort() + "/dc=springframework,dc=org");
|
||||
contextSource.setUserDn("uid=admin,ou=system");
|
||||
@@ -254,22 +298,14 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception {
|
||||
AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception {
|
||||
configure(auth);
|
||||
return auth.build();
|
||||
}
|
||||
|
||||
abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception;
|
||||
@Override
|
||||
protected abstract void configure(AuthenticationManagerBuilder auth) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
static Integer port;
|
||||
|
||||
static int getPort() throws IOException {
|
||||
if (port == null) {
|
||||
ServerSocket socket = new ServerSocket(0);
|
||||
port = socket.getLocalPort();
|
||||
socket.close();
|
||||
}
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -27,13 +29,15 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
|
||||
public class LdapAuthenticationProviderConfigurerTests {
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@@ -41,7 +45,8 @@ public class LdapAuthenticationProviderConfigurerTests {
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void authenticationManagerSupportMultipleDefaultLdapContextsWithPortsDynamicallyAllocated() throws Exception {
|
||||
public void authenticationManagerSupportMultipleDefaultLdapContextsWithPortsDynamicallyAllocated()
|
||||
throws Exception {
|
||||
this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
@@ -52,39 +57,68 @@ public class LdapAuthenticationProviderConfigurerTests {
|
||||
public void authenticationManagerSupportMultipleLdapContextWithDefaultRolePrefix() throws Exception {
|
||||
this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bob")
|
||||
.password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||
.withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")));
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerSupportMultipleLdapContextWithCustomRolePrefix() throws Exception {
|
||||
this.spring.register(MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS"))));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bob")
|
||||
.password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||
.withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")));
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerWhenPortZeroThenAuthenticates() throws Exception {
|
||||
this.spring.register(LdapWithRandomPortConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bob")
|
||||
.password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||
.withUsername("bob");
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerWhenSearchSubtreeThenNestedGroupFound() throws Exception {
|
||||
this.spring.register(GroupSubtreeSearchConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("ben").password("benspassword"))
|
||||
.andExpect(authenticated().withUsername("ben").withAuthorities(
|
||||
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS")));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("ben")
|
||||
.password("benspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||
.withUsername("ben")
|
||||
.withAuthorities(
|
||||
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS"));
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
|
||||
// @formatter:off
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
@@ -95,14 +129,17 @@ public class LdapAuthenticationProviderConfigurerTests {
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
|
||||
// @formatter:off
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
@@ -115,14 +152,17 @@ public class LdapAuthenticationProviderConfigurerTests {
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.rolePrefix("RUOLO_");
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class LdapWithRandomPortConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
@@ -130,20 +170,26 @@ public class LdapAuthenticationProviderConfigurerTests {
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.contextSource()
|
||||
.port(0);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
|
||||
// @formatter:off
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.groupSearchSubtree(true)
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,13 @@
|
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.ldap.core.support.LdapContextSource;
|
||||
@@ -31,13 +36,11 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
|
||||
@@ -56,22 +59,35 @@ public class NamespaceLdapAuthenticationProviderTests {
|
||||
public void ldapAuthenticationProvider() throws Exception {
|
||||
this.spring.register(LdapAuthenticationProviderConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bob")
|
||||
.password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
||||
.withUsername("bob");
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ldapAuthenticationProviderCustom() throws Exception {
|
||||
this.spring.register(CustomLdapAuthenticationProviderConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS"))));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bob")
|
||||
.password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")));
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
// SEC-2490
|
||||
@Test
|
||||
public void ldapAuthenticationProviderCustomLdapAuthoritiesPopulator() throws Exception {
|
||||
LdapContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://blah.example.com:789/dc=springframework,dc=org");
|
||||
LdapContextSource contextSource = new DefaultSpringSecurityContextSource(
|
||||
"ldap://blah.example.com:789/dc=springframework,dc=org");
|
||||
CustomAuthoritiesPopulatorConfig.LAP = new DefaultLdapAuthoritiesPopulator(contextSource, null) {
|
||||
@Override
|
||||
protected Set<GrantedAuthority> getAdditionalRoles(DirContextOperations user, String username) {
|
||||
@@ -81,15 +97,27 @@ public class NamespaceLdapAuthenticationProviderTests {
|
||||
|
||||
this.spring.register(CustomAuthoritiesPopulatorConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA"))));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bob")
|
||||
.password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")));
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ldapAuthenticationProviderPasswordCompare() throws Exception {
|
||||
this.spring.register(PasswordCompareLdapConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
|
||||
.andExpect(authenticated().withUsername("bcrypt"));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin()
|
||||
.user("bcrypt")
|
||||
.password("password");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated().withUsername("bcrypt");
|
||||
// @formatter:on
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap;
|
||||
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
@@ -27,23 +28,28 @@ import org.springframework.security.ldap.userdetails.PersonContextMapper;
|
||||
*
|
||||
*/
|
||||
public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
|
||||
@EnableWebSecurity
|
||||
static class LdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
|
||||
// @formatter:off
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
.userDnPatterns("uid={0},ou=people"); // ldap-server@user-dn-pattern
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomLdapAuthenticationProviderConfig extends
|
||||
WebSecurityConfigurerAdapter {
|
||||
// @formatter:off
|
||||
static class CustomLdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupRoleAttribute("cn") // ldap-authentication-provider@group-role-attribute
|
||||
@@ -60,31 +66,36 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
.managerDn("uid=admin,ou=system") // ldap-server@manager-dn
|
||||
.managerPassword("secret") // ldap-server@manager-password
|
||||
.port(33399) // ldap-server@port
|
||||
.root("dc=springframework,dc=org") // ldap-server@root
|
||||
.root("dc=springframework,dc=org"); // ldap-server@root
|
||||
// .url("ldap://localhost:33389/dc-springframework,dc=org") this overrides root and port and is used for external
|
||||
;
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomAuthoritiesPopulatorConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
static LdapAuthoritiesPopulator LAP;
|
||||
|
||||
// @formatter:off
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.userSearchFilter("(uid={0})")
|
||||
.ldapAuthoritiesPopulator(LAP);
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter {
|
||||
// @formatter:off
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
@@ -92,7 +103,9 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
.passwordCompare()
|
||||
.passwordEncoder(new BCryptPasswordEncoder()) // ldap-authentication-provider/password-compare/password-encoder@ref
|
||||
.passwordAttribute("userPassword"); // ldap-authentication-provider/password-compare@password-attribute
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.rsocket;
|
||||
|
||||
import io.rsocket.ConnectionSetupPayload;
|
||||
@@ -26,15 +27,15 @@ public class HelloHandler implements SocketAcceptor {
|
||||
|
||||
@Override
|
||||
public Mono<RSocket> accept(ConnectionSetupPayload setup, RSocket sendingSocket) {
|
||||
return Mono.just(
|
||||
new RSocket() {
|
||||
@Override
|
||||
public Mono<Payload> requestResponse(Payload payload) {
|
||||
String data = payload.getDataUtf8();
|
||||
payload.release();
|
||||
System.out.println("Got " + data);
|
||||
return Mono.just(ByteBufPayload.create("Hello " + data));
|
||||
}
|
||||
});
|
||||
return Mono.just(new RSocket() {
|
||||
@Override
|
||||
public Mono<Payload> requestResponse(Payload payload) {
|
||||
String data = payload.getDataUtf8();
|
||||
payload.release();
|
||||
System.out.println("Got " + data);
|
||||
return Mono.just(ByteBufPayload.create("Hello " + data));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.rsocket.core.RSocketServer;
|
||||
import io.rsocket.exceptions.RejectedSetupException;
|
||||
import io.rsocket.frame.decoder.PayloadDecoder;
|
||||
import io.rsocket.transport.netty.server.CloseableChannel;
|
||||
import io.rsocket.transport.netty.server.TcpServerTransport;
|
||||
@@ -46,7 +47,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -54,6 +55,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringRunner.class)
|
||||
public class HelloRSocketITests {
|
||||
|
||||
@Autowired
|
||||
RSocketMessageHandler handler;
|
||||
|
||||
@@ -69,14 +71,16 @@ public class HelloRSocketITests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// @formatter:off
|
||||
this.server = RSocketServer.create()
|
||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.interceptors((registry) -> {
|
||||
registry.forSocketAcceptor(this.interceptor);
|
||||
})
|
||||
.interceptors((registry) ->
|
||||
registry.forSocketAcceptor(this.interceptor)
|
||||
)
|
||||
.acceptor(this.handler.responder())
|
||||
.bind(TcpServerTransport.create("localhost", 0))
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -88,38 +92,45 @@ public class HelloRSocketITests {
|
||||
|
||||
@Test
|
||||
public void retrieveMonoWhenSecureThenDenied() throws Exception {
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
assertThatCode(() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.isNotNull();
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(Exception.class).isThrownBy(
|
||||
() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.matches((ex) -> ex instanceof RejectedSetupException
|
||||
|| ex.getClass().toString().contains("ReactiveException"));
|
||||
// @formatter:on
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
// .isInstanceOf(RejectedSetupException.class);
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveMonoWhenAuthorizedThenGranted() throws Exception {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password");
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
@@ -129,37 +140,39 @@ public class HelloRSocketITests {
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ServerController controller() {
|
||||
ServerController controller() {
|
||||
return new ServerController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler handler = new RSocketMessageHandler();
|
||||
handler.setRSocketStrategies(rsocketStrategies());
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder()
|
||||
.encoder(new BasicAuthenticationEncoder())
|
||||
.build();
|
||||
RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder().encoder(new BasicAuthenticationEncoder()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MapReactiveUserDetailsService uds() {
|
||||
// @formatter:off
|
||||
UserDetails rob = User.withDefaultPasswordEncoder()
|
||||
.username("rob")
|
||||
.password("password")
|
||||
.roles("USER", "ADMIN")
|
||||
.build();
|
||||
// @formatter:on
|
||||
return new MapReactiveUserDetailsService(rob);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class ServerController {
|
||||
|
||||
private List<String> payloads = new ArrayList<>();
|
||||
|
||||
@MessageMapping("**")
|
||||
@@ -171,6 +184,7 @@ public class HelloRSocketITests {
|
||||
private void add(String p) {
|
||||
this.payloads.add(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.rsocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -21,6 +22,7 @@ import java.util.List;
|
||||
|
||||
import io.rsocket.core.RSocketServer;
|
||||
import io.rsocket.frame.decoder.PayloadDecoder;
|
||||
import io.rsocket.metadata.WellKnownMimeType;
|
||||
import io.rsocket.transport.netty.server.CloseableChannel;
|
||||
import io.rsocket.transport.netty.server.TcpServerTransport;
|
||||
import org.junit.After;
|
||||
@@ -51,11 +53,10 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static io.rsocket.metadata.WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -63,6 +64,7 @@ import static org.mockito.Mockito.when;
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringRunner.class)
|
||||
public class JwtITests {
|
||||
|
||||
@Autowired
|
||||
RSocketMessageHandler handler;
|
||||
|
||||
@@ -81,14 +83,16 @@ public class JwtITests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// @formatter:off
|
||||
this.server = RSocketServer.create()
|
||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.interceptors((registry) -> {
|
||||
registry.forSocketAcceptor(this.interceptor);
|
||||
})
|
||||
.acceptor(this.handler.responder())
|
||||
.bind(TcpServerTransport.create("localhost", 0))
|
||||
.block();
|
||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.interceptors((registry) ->
|
||||
registry.forSocketAcceptor(this.interceptor)
|
||||
)
|
||||
.acceptor(this.handler.responder())
|
||||
.bind(TcpServerTransport.create("localhost", 0))
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -100,88 +104,72 @@ public class JwtITests {
|
||||
|
||||
@Test
|
||||
public void routeWhenBearerThenAuthorized() {
|
||||
BearerTokenMetadata credentials =
|
||||
new BearerTokenMetadata("token");
|
||||
when(this.decoder.decode(any())).thenReturn(Mono.just(jwt()));
|
||||
BearerTokenMetadata credentials = new BearerTokenMetadata("token");
|
||||
given(this.decoder.decode(any())).willReturn(Mono.just(jwt()));
|
||||
// @formatter:off
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials.getToken(), BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
.setupMetadata(credentials.getToken(), BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenAuthenticationBearerThenAuthorized() {
|
||||
MimeType authenticationMimeType = MimeTypeUtils.parseMimeType(MESSAGE_RSOCKET_AUTHENTICATION.getString());
|
||||
|
||||
BearerTokenMetadata credentials =
|
||||
new BearerTokenMetadata("token");
|
||||
when(this.decoder.decode(any())).thenReturn(Mono.just(jwt()));
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, authenticationMimeType)
|
||||
MimeType authenticationMimeType = MimeTypeUtils
|
||||
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
|
||||
BearerTokenMetadata credentials = new BearerTokenMetadata("token");
|
||||
given(this.decoder.decode(any())).willReturn(Mono.just(jwt()));
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, authenticationMimeType)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.retrieveMono(String.class).block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
private Jwt jwt() {
|
||||
return TestJwts.jwt()
|
||||
.claim(IdTokenClaimNames.ISS, "https://issuer.example.com")
|
||||
.claim(IdTokenClaimNames.SUB, "rob")
|
||||
.claim(IdTokenClaimNames.AUD, Arrays.asList("client-id"))
|
||||
.build();
|
||||
return TestJwts.jwt().claim(IdTokenClaimNames.ISS, "https://issuer.example.com")
|
||||
.claim(IdTokenClaimNames.SUB, "rob").claim(IdTokenClaimNames.AUD, Arrays.asList("client-id")).build();
|
||||
}
|
||||
|
||||
private RSocketRequester.Builder requester() {
|
||||
return RSocketRequester.builder()
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies());
|
||||
return RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies());
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableRSocketSecurity
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ServerController controller() {
|
||||
ServerController controller() {
|
||||
return new ServerController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler handler = new RSocketMessageHandler();
|
||||
handler.setRSocketStrategies(rsocketStrategies());
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder()
|
||||
.encoder(new BearerTokenAuthenticationEncoder())
|
||||
.build();
|
||||
RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder().encoder(new BearerTokenAuthenticationEncoder()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||
rsocket
|
||||
.authorizePayload(authorize ->
|
||||
authorize
|
||||
.anyRequest().authenticated()
|
||||
.anyExchange().permitAll()
|
||||
)
|
||||
.jwt(Customizer.withDefaults());
|
||||
rsocket.authorizePayload((authorize) -> authorize.anyRequest().authenticated().anyExchange().permitAll())
|
||||
.jwt(Customizer.withDefaults());
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
@@ -189,16 +177,19 @@ public class JwtITests {
|
||||
ReactiveJwtDecoder jwtDecoder() {
|
||||
return mock(ReactiveJwtDecoder.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class ServerController {
|
||||
|
||||
private List<String> payloads = new ArrayList<>();
|
||||
|
||||
@MessageMapping("**")
|
||||
String connect(String payload) {
|
||||
return "Hi " + payload;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.rsocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -20,6 +21,7 @@ import java.util.List;
|
||||
|
||||
import io.rsocket.core.RSocketServer;
|
||||
import io.rsocket.exceptions.ApplicationErrorException;
|
||||
import io.rsocket.exceptions.RejectedSetupException;
|
||||
import io.rsocket.frame.decoder.PayloadDecoder;
|
||||
import io.rsocket.transport.netty.server.CloseableChannel;
|
||||
import io.rsocket.transport.netty.server.TcpServerTransport;
|
||||
@@ -48,7 +50,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -60,6 +62,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringRunner.class)
|
||||
public class RSocketMessageHandlerConnectionITests {
|
||||
|
||||
@Autowired
|
||||
RSocketMessageHandler handler;
|
||||
|
||||
@@ -75,14 +78,16 @@ public class RSocketMessageHandlerConnectionITests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// @formatter:off
|
||||
this.server = RSocketServer.create()
|
||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.interceptors((registry) -> {
|
||||
registry.forSocketAcceptor(this.interceptor);
|
||||
})
|
||||
.interceptors((registry) ->
|
||||
registry.forSocketAcceptor(this.interceptor)
|
||||
)
|
||||
.acceptor(this.handler.responder())
|
||||
.bind(TcpServerTransport.create("localhost", 0))
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -94,182 +99,179 @@ public class RSocketMessageHandlerConnectionITests {
|
||||
|
||||
@Test
|
||||
public void routeWhenAuthorized() {
|
||||
UsernamePasswordMetadata credentials =
|
||||
new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenNotAuthorized() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
assertThatCode(() -> this.requester.route("secure.admin.retrieve-mono")
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
assertThatExceptionOfType(ApplicationErrorException.class).isThrownBy(() -> this.requester
|
||||
.route("secure.admin.retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block())
|
||||
.isInstanceOf(ApplicationErrorException.class);
|
||||
.block()
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenStreamCredentialsAuthorized() {
|
||||
UsernamePasswordMetadata connectCredentials = new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.admin.retrieve-mono")
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"), UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"),
|
||||
UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenStreamCredentialsHaveAuthority() {
|
||||
UsernamePasswordMetadata connectCredentials = new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiUser = this.requester.route("secure.authority.retrieve-mono")
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"), UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("Felipe")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"),
|
||||
UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("Felipe")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiUser).isEqualTo("Hi Felipe");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWhenNotAuthenticated() {
|
||||
this.requester = requester()
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
// @formatter:off
|
||||
this.requester = requester().connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
assertThatCode(() -> this.requester.route("retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block())
|
||||
.isNotNull();
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.requester.route("retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.matches((ex) -> ex instanceof RejectedSetupException
|
||||
|| ex.getClass().toString().contains("ReactiveException"));
|
||||
// @formatter:on
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
// .isInstanceOf(RejectedSetupException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWhenNotAuthorized() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("evil", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
assertThatCode(() -> this.requester.route("retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block())
|
||||
.isNotNull();
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
// .isInstanceOf(RejectedSetupException.class);
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.requester.route("retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.matches((ex) -> ex instanceof RejectedSetupException
|
||||
|| ex.getClass().toString().contains("ReactiveException"));
|
||||
// @formatter:on
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionDenied() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
assertThatCode(() -> this.requester.route("prohibit")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block())
|
||||
.isInstanceOf(ApplicationErrorException.class);
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("prohibit")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWithAnyRole() {
|
||||
UsernamePasswordMetadata credentials =
|
||||
new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
String hiRob = this.requester.route("anyroute")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWithAnyAuthority() {
|
||||
UsernamePasswordMetadata credentials =
|
||||
new UsernamePasswordMetadata("admin", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("admin", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
String hiEbert = this.requester.route("management.users")
|
||||
.data("admin")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
// @formatter:on
|
||||
assertThat(hiEbert).isEqualTo("Hi admin");
|
||||
}
|
||||
|
||||
private RSocketRequester.Builder requester() {
|
||||
return RSocketRequester.builder()
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies());
|
||||
return RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies());
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableRSocketSecurity
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ServerController controller() {
|
||||
ServerController controller() {
|
||||
return new ServerController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler handler = new RSocketMessageHandler();
|
||||
handler.setRSocketStrategies(rsocketStrategies());
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder()
|
||||
.encoder(new BasicAuthenticationEncoder())
|
||||
.build();
|
||||
RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder().encoder(new BasicAuthenticationEncoder()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MapReactiveUserDetailsService uds() {
|
||||
// @formatter:off
|
||||
UserDetails admin = User.withDefaultPasswordEncoder()
|
||||
.username("admin")
|
||||
.password("password")
|
||||
@@ -280,41 +282,44 @@ public class RSocketMessageHandlerConnectionITests {
|
||||
.password("password")
|
||||
.roles("USER", "SETUP")
|
||||
.build();
|
||||
|
||||
UserDetails evil = User.withDefaultPasswordEncoder()
|
||||
.username("evil")
|
||||
.password("password")
|
||||
.roles("EVIL")
|
||||
.build();
|
||||
// @formatter:on
|
||||
return new MapReactiveUserDetailsService(admin, user, evil);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||
rsocket
|
||||
.authorizePayload(authorize ->
|
||||
authorize
|
||||
.setup().hasRole("SETUP")
|
||||
.route("secure.admin.*").hasRole("ADMIN")
|
||||
.route("secure.**").hasRole("USER")
|
||||
.route("secure.authority.*").hasAuthority("ROLE_USER")
|
||||
.route("management.*").hasAnyAuthority("ROLE_ADMIN")
|
||||
.route("prohibit").denyAll()
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:off
|
||||
rsocket.authorizePayload((authorize) -> authorize
|
||||
.setup().hasRole("SETUP")
|
||||
.route("secure.admin.*").hasRole("ADMIN")
|
||||
.route("secure.**").hasRole("USER")
|
||||
.route("secure.authority.*").hasAuthority("ROLE_USER")
|
||||
.route("management.*").hasAnyAuthority("ROLE_ADMIN")
|
||||
.route("prohibit").denyAll()
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:on
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class ServerController {
|
||||
|
||||
private List<String> payloads = new ArrayList<>();
|
||||
|
||||
@MessageMapping("**")
|
||||
String connect(String payload) {
|
||||
return "Hi " + payload;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -60,6 +60,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringRunner.class)
|
||||
public class RSocketMessageHandlerITests {
|
||||
|
||||
@Autowired
|
||||
RSocketMessageHandler handler;
|
||||
|
||||
@@ -75,20 +76,22 @@ public class RSocketMessageHandlerITests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// @formatter:off
|
||||
this.server = RSocketServer.create()
|
||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.interceptors((registry) -> {
|
||||
registry.forSocketAcceptor(this.interceptor);
|
||||
})
|
||||
.interceptors((registry) ->
|
||||
registry.forSocketAcceptor(this.interceptor)
|
||||
)
|
||||
.acceptor(this.handler.responder())
|
||||
.bind(TcpServerTransport.create("localhost", 0))
|
||||
.block();
|
||||
|
||||
this.requester = RSocketRequester.builder()
|
||||
// .rsocketFactory(factory -> factory.addRequesterPlugin(payloadInterceptor))
|
||||
// .rsocketFactory((factory) ->
|
||||
// factory.addRequesterPlugin(payloadInterceptor))
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -101,13 +104,15 @@ public class RSocketMessageHandlerITests {
|
||||
@Test
|
||||
public void retrieveMonoWhenSecureThenDenied() throws Exception {
|
||||
String data = "rob";
|
||||
assertThatCode(() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
).isInstanceOf(ApplicationErrorException.class)
|
||||
.hasMessageContaining("Access Denied");
|
||||
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class).isThrownBy(
|
||||
() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.withMessageContaining("Access Denied");
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@@ -115,14 +120,15 @@ public class RSocketMessageHandlerITests {
|
||||
public void retrieveMonoWhenAuthenticationFailedThenException() throws Exception {
|
||||
String data = "rob";
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("invalid", "password");
|
||||
assertThatCode(() -> this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
).isInstanceOf(ApplicationErrorException.class)
|
||||
.hasMessageContaining("Invalid Credentials");
|
||||
|
||||
)
|
||||
.withMessageContaining("Invalid Credentials");
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@@ -130,12 +136,13 @@ public class RSocketMessageHandlerITests {
|
||||
public void retrieveMonoWhenAuthorizedThenGranted() throws Exception {
|
||||
String data = "rob";
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password");
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
@@ -143,11 +150,12 @@ public class RSocketMessageHandlerITests {
|
||||
@Test
|
||||
public void retrieveMonoWhenPublicThenGranted() throws Exception {
|
||||
String data = "rob";
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
@@ -155,26 +163,29 @@ public class RSocketMessageHandlerITests {
|
||||
@Test
|
||||
public void retrieveFluxWhenDataFluxAndSecureThenDenied() throws Exception {
|
||||
Flux<String> data = Flux.just("a", "b", "c");
|
||||
assertThatCode(() -> this.requester.route("secure.retrieve-flux")
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-flux")
|
||||
.data(data, String.class)
|
||||
.retrieveFlux(String.class)
|
||||
.collectList()
|
||||
.block()
|
||||
).isInstanceOf(ApplicationErrorException.class)
|
||||
.hasMessageContaining("Access Denied");
|
||||
|
||||
)
|
||||
.withMessageContaining("Access Denied");
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveFluxWhenDataFluxAndPublicThenGranted() throws Exception {
|
||||
Flux<String> data = Flux.just("a", "b", "c");
|
||||
// @formatter:off
|
||||
List<String> hi = this.requester.route("retrieve-flux")
|
||||
.data(data, String.class)
|
||||
.retrieveFlux(String.class)
|
||||
.collectList()
|
||||
.block();
|
||||
|
||||
.data(data, String.class)
|
||||
.retrieveFlux(String.class)
|
||||
.collectList()
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hi).containsOnly("hello a", "hello b", "hello c");
|
||||
assertThat(this.controller.payloads).containsOnlyElementsOf(data.collectList().block());
|
||||
}
|
||||
@@ -182,35 +193,33 @@ public class RSocketMessageHandlerITests {
|
||||
@Test
|
||||
public void retrieveFluxWhenDataStringAndSecureThenDenied() throws Exception {
|
||||
String data = "a";
|
||||
assertThatCode(() -> this.requester.route("secure.hello")
|
||||
.data(data)
|
||||
.retrieveFlux(String.class)
|
||||
.collectList()
|
||||
.block()
|
||||
).isInstanceOf(ApplicationErrorException.class)
|
||||
.hasMessageContaining("Access Denied");
|
||||
|
||||
assertThatExceptionOfType(ApplicationErrorException.class).isThrownBy(
|
||||
() -> this.requester.route("secure.hello").data(data).retrieveFlux(String.class).collectList().block())
|
||||
.withMessageContaining("Access Denied");
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendWhenSecureThenDenied() throws Exception {
|
||||
String data = "hi";
|
||||
// @formatter:off
|
||||
this.requester.route("secure.send")
|
||||
.data(data)
|
||||
.send()
|
||||
.block();
|
||||
|
||||
.data(data)
|
||||
.send()
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendWhenPublicThenGranted() throws Exception {
|
||||
String data = "hi";
|
||||
// @formatter:off
|
||||
this.requester.route("send")
|
||||
.data(data)
|
||||
.send()
|
||||
.block();
|
||||
.data(data)
|
||||
.send()
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(this.controller.awaitPayloads()).containsOnly("hi");
|
||||
}
|
||||
|
||||
@@ -219,26 +228,25 @@ public class RSocketMessageHandlerITests {
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ServerController controller() {
|
||||
ServerController controller() {
|
||||
return new ServerController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler handler = new RSocketMessageHandler();
|
||||
handler.setRSocketStrategies(rsocketStrategies());
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder()
|
||||
.encoder(new BasicAuthenticationEncoder())
|
||||
.build();
|
||||
RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder().encoder(new BasicAuthenticationEncoder()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MapReactiveUserDetailsService uds() {
|
||||
// @formatter:off
|
||||
UserDetails rob = User.withDefaultPasswordEncoder()
|
||||
.username("rob")
|
||||
.password("password")
|
||||
@@ -249,45 +257,44 @@ public class RSocketMessageHandlerITests {
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
// @formatter:on
|
||||
return new MapReactiveUserDetailsService(rob, rossen);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||
rsocket
|
||||
.authorizePayload(authorize -> {
|
||||
authorize
|
||||
.route("secure.*").authenticated()
|
||||
.anyExchange().permitAll();
|
||||
})
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:off
|
||||
rsocket.authorizePayload(
|
||||
(authorize) -> authorize
|
||||
.route("secure.*").authenticated()
|
||||
.anyExchange().permitAll()
|
||||
)
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:on
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class ServerController {
|
||||
|
||||
private List<String> payloads = new ArrayList<>();
|
||||
|
||||
@MessageMapping({"secure.retrieve-mono", "retrieve-mono"})
|
||||
@MessageMapping({ "secure.retrieve-mono", "retrieve-mono" })
|
||||
String retrieveMono(String payload) {
|
||||
add(payload);
|
||||
return "Hi " + payload;
|
||||
}
|
||||
|
||||
@MessageMapping({"secure.retrieve-flux", "retrieve-flux"})
|
||||
@MessageMapping({ "secure.retrieve-flux", "retrieve-flux" })
|
||||
Flux<String> retrieveFlux(Flux<String> payload) {
|
||||
return payload.doOnNext(this::add)
|
||||
.map(p -> "hello " + p);
|
||||
return payload.doOnNext(this::add).map((p) -> "hello " + p);
|
||||
}
|
||||
|
||||
@MessageMapping({"secure.send", "send"})
|
||||
@MessageMapping({ "secure.send", "send" })
|
||||
Mono<Void> send(Mono<String> payload) {
|
||||
return payload
|
||||
.doOnNext(this::add)
|
||||
.then(Mono.fromRunnable(() -> {
|
||||
doNotifyAll();
|
||||
}));
|
||||
return payload.doOnNext(this::add).then(Mono.fromRunnable(() -> doNotifyAll()));
|
||||
}
|
||||
|
||||
private synchronized void doNotifyAll() {
|
||||
@@ -302,6 +309,7 @@ public class RSocketMessageHandlerITests {
|
||||
private void add(String p) {
|
||||
this.payloads.add(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import io.rsocket.core.RSocketServer;
|
||||
import io.rsocket.exceptions.ApplicationErrorException;
|
||||
import io.rsocket.frame.decoder.PayloadDecoder;
|
||||
import io.rsocket.metadata.WellKnownMimeType;
|
||||
import io.rsocket.transport.netty.server.CloseableChannel;
|
||||
import io.rsocket.transport.netty.server.TcpServerTransport;
|
||||
import org.junit.After;
|
||||
@@ -50,9 +51,8 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static io.rsocket.metadata.WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -60,6 +60,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringRunner.class)
|
||||
public class SimpleAuthenticationITests {
|
||||
|
||||
@Autowired
|
||||
RSocketMessageHandler handler;
|
||||
|
||||
@@ -75,14 +76,16 @@ public class SimpleAuthenticationITests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// @formatter:off
|
||||
this.server = RSocketServer.create()
|
||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.interceptors((registry) -> {
|
||||
registry.forSocketAcceptor(this.interceptor);
|
||||
})
|
||||
.interceptors((registry) ->
|
||||
registry.forSocketAcceptor(this.interceptor)
|
||||
)
|
||||
.acceptor(this.handler.responder())
|
||||
.bind(TcpServerTransport.create("localhost", 0))
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -94,38 +97,42 @@ public class SimpleAuthenticationITests {
|
||||
|
||||
@Test
|
||||
public void retrieveMonoWhenSecureThenDenied() throws Exception {
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
assertThatCode(() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data).retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.isInstanceOf(ApplicationErrorException.class);
|
||||
);
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveMonoWhenAuthorizedThenGranted() {
|
||||
MimeType authenticationMimeType = MimeTypeUtils.parseMimeType(MESSAGE_RSOCKET_AUTHENTICATION.getString());
|
||||
|
||||
MimeType authenticationMimeType = MimeTypeUtils
|
||||
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password");
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.setupMetadata(credentials, authenticationMimeType)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
.setupMetadata(credentials, authenticationMimeType)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, authenticationMimeType)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
|
||||
.metadata(credentials, authenticationMimeType)
|
||||
.data(data).retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
@@ -135,49 +142,46 @@ public class SimpleAuthenticationITests {
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ServerController controller() {
|
||||
ServerController controller() {
|
||||
return new ServerController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler messageHandler() {
|
||||
RSocketMessageHandler handler = new RSocketMessageHandler();
|
||||
handler.setRSocketStrategies(rsocketStrategies());
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder()
|
||||
.encoder(new SimpleAuthenticationEncoder())
|
||||
.build();
|
||||
RSocketStrategies rsocketStrategies() {
|
||||
return RSocketStrategies.builder().encoder(new SimpleAuthenticationEncoder()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||
rsocket
|
||||
.authorizePayload(authorize ->
|
||||
authorize
|
||||
.anyRequest().authenticated()
|
||||
.anyExchange().permitAll()
|
||||
)
|
||||
rsocket.authorizePayload((authorize) -> authorize.anyRequest().authenticated().anyExchange().permitAll())
|
||||
.simpleAuthentication(Customizer.withDefaults());
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MapReactiveUserDetailsService uds() {
|
||||
// @formatter:off
|
||||
UserDetails rob = User.withDefaultPasswordEncoder()
|
||||
.username("rob")
|
||||
.password("password")
|
||||
.roles("USER", "ADMIN")
|
||||
.build();
|
||||
// @formatter:on
|
||||
return new MapReactiveUserDetailsService(rob);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class ServerController {
|
||||
|
||||
private List<String> payloads = new ArrayList<>();
|
||||
|
||||
@MessageMapping("**")
|
||||
@@ -189,6 +193,7 @@ public class SimpleAuthenticationITests {
|
||||
private void add(String p) {
|
||||
this.payloads.add(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,84 +35,74 @@ import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class LdapProviderBeanDefinitionParserTests {
|
||||
|
||||
InMemoryXmlApplicationContext appCtx;
|
||||
|
||||
@After
|
||||
public void closeAppContext() {
|
||||
if (appCtx != null) {
|
||||
appCtx.close();
|
||||
appCtx = null;
|
||||
if (this.appCtx != null) {
|
||||
this.appCtx.close();
|
||||
this.appCtx = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleProviderAuthenticatesCorrectly() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider group-search-filter='member={0}' />"
|
||||
+ "</authentication-manager>"
|
||||
);
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>" + " <ldap-authentication-provider group-search-filter='member={0}' />"
|
||||
+ "</authentication-manager>");
|
||||
|
||||
AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
UserDetails ben = (UserDetails) auth.getPrincipal();
|
||||
assertThat(ben.getAuthorities()).hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleProvidersAreSupported() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider group-search-filter='member={0}' />"
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>" + " <ldap-authentication-provider group-search-filter='member={0}' />"
|
||||
+ " <ldap-authentication-provider group-search-filter='uniqueMember={0}' />"
|
||||
+ "</authentication-manager>"
|
||||
);
|
||||
+ "</authentication-manager>");
|
||||
|
||||
ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||
ProviderManager providerManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||
assertThat(providerManager.getProviders()).hasSize(2);
|
||||
assertThat(providerManager.getProviders())
|
||||
.extracting("authoritiesPopulator.groupSearchFilter")
|
||||
assertThat(providerManager.getProviders()).extracting("authoritiesPopulator.groupSearchFilter")
|
||||
.containsExactly("member={0}", "uniqueMember={0}");
|
||||
}
|
||||
|
||||
@Test(expected = ApplicationContextException.class)
|
||||
public void missingServerEltCausesConfigException() {
|
||||
new InMemoryXmlApplicationContext("<authentication-manager>"
|
||||
+ " <ldap-authentication-provider />"
|
||||
+ "</authentication-manager>"
|
||||
);
|
||||
new InMemoryXmlApplicationContext(
|
||||
"<authentication-manager>" + " <ldap-authentication-provider />" + "</authentication-manager>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsPasswordComparisonAuthentication() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>"
|
||||
+ " <password-compare />"
|
||||
+ " </ldap-authentication-provider>"
|
||||
+ "</authentication-manager>"
|
||||
);
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>" + " <ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>"
|
||||
+ " <password-compare />" + " </ldap-authentication-provider>" + "</authentication-manager>");
|
||||
|
||||
AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
|
||||
assertThat(auth).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>"
|
||||
+ " <password-compare password-attribute='uid'>"
|
||||
+ " <password-encoder ref='passwordEncoder' />"
|
||||
+ " </password-compare>"
|
||||
+ " </ldap-authentication-provider>"
|
||||
+ "</authentication-manager>"
|
||||
+ "<b:bean id='passwordEncoder' class='org.springframework.security.crypto.password.NoOpPasswordEncoder' factory-method='getInstance' />"
|
||||
);
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>" + " <ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>"
|
||||
+ " <password-compare password-attribute='uid'>" + " <password-encoder ref='passwordEncoder' />"
|
||||
+ " </password-compare>" + " </ldap-authentication-provider>" + "</authentication-manager>"
|
||||
+ "<b:bean id='passwordEncoder' class='org.springframework.security.crypto.password.NoOpPasswordEncoder' factory-method='getInstance' />");
|
||||
|
||||
AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class);
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"));
|
||||
|
||||
assertThat(auth).isNotNull();
|
||||
@@ -121,58 +111,52 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
// SEC-2472
|
||||
@Test
|
||||
public void supportsCryptoPasswordEncoder() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>"
|
||||
+ " <password-compare>"
|
||||
+ " <password-encoder ref='pe' />"
|
||||
+ " </password-compare>"
|
||||
+ " </ldap-authentication-provider>"
|
||||
+ "</authentication-manager>"
|
||||
+ "<b:bean id='pe' class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder' />"
|
||||
);
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>"
|
||||
+ "<authentication-manager>" + " <ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>"
|
||||
+ " <password-compare>" + " <password-encoder ref='pe' />" + " </password-compare>"
|
||||
+ " </ldap-authentication-provider>" + "</authentication-manager>"
|
||||
+ "<b:bean id='pe' class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder' />");
|
||||
|
||||
AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", "password"));
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", "password"));
|
||||
|
||||
assertThat(auth).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inetOrgContextMapperIsSupported() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider user-details-class='inetOrgPerson' />"
|
||||
+ "</authentication-manager>"
|
||||
);
|
||||
this.appCtx = new InMemoryXmlApplicationContext(
|
||||
"<ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org' port='0'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider user-details-class='inetOrgPerson' />"
|
||||
+ "</authentication-manager>");
|
||||
|
||||
ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||
ProviderManager providerManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||
assertThat(providerManager.getProviders()).hasSize(1);
|
||||
assertThat(providerManager.getProviders())
|
||||
.extracting("userDetailsContextMapper")
|
||||
.allSatisfy(contextMapper -> assertThat(contextMapper).isInstanceOf(InetOrgPersonContextMapper.class));
|
||||
assertThat(providerManager.getProviders()).extracting("userDetailsContextMapper").allSatisfy(
|
||||
(contextMapper) -> assertThat(contextMapper).isInstanceOf(InetOrgPersonContextMapper.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ldapAuthenticationProviderWorksWithPlaceholders() {
|
||||
System.setProperty("udp", "people");
|
||||
System.setProperty("gsf", "member");
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server />"
|
||||
+ "<authentication-manager>"
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server />" + "<authentication-manager>"
|
||||
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=${udp}' group-search-filter='${gsf}={0}' />"
|
||||
+ "</authentication-manager>"
|
||||
+ "<b:bean id='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' />"
|
||||
);
|
||||
+ "<b:bean id='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' />");
|
||||
|
||||
ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||
ProviderManager providerManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||
assertThat(providerManager.getProviders()).hasSize(1);
|
||||
|
||||
AuthenticationProvider authenticationProvider = providerManager.getProviders().get(0);
|
||||
assertThat(authenticationProvider)
|
||||
.extracting("authenticator.userDnFormat")
|
||||
.satisfies(messageFormats -> assertThat(messageFormats).isEqualTo(new MessageFormat[]{new MessageFormat("uid={0},ou=people")}));
|
||||
assertThat(authenticationProvider)
|
||||
.extracting("authoritiesPopulator.groupSearchFilter")
|
||||
.satisfies(searchFilter -> assertThat(searchFilter).isEqualTo("member={0}"));
|
||||
assertThat(authenticationProvider).extracting("authenticator.userDnFormat")
|
||||
.satisfies((messageFormats) -> assertThat(messageFormats)
|
||||
.isEqualTo(new MessageFormat[] { new MessageFormat("uid={0},ou=people") }));
|
||||
assertThat(authenticationProvider).extracting("authoritiesPopulator.groupSearchFilter")
|
||||
.satisfies((searchFilter) -> assertThat(searchFilter).isEqualTo("member={0}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -35,22 +36,22 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class LdapServerBeanDefinitionParserTests {
|
||||
|
||||
InMemoryXmlApplicationContext appCtx;
|
||||
|
||||
@After
|
||||
public void closeAppContext() {
|
||||
if (appCtx != null) {
|
||||
appCtx.close();
|
||||
appCtx = null;
|
||||
if (this.appCtx != null) {
|
||||
this.appCtx.close();
|
||||
this.appCtx = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void embeddedServerCreationContainsExpectedContextSourceAndData() {
|
||||
appCtx = new InMemoryXmlApplicationContext(
|
||||
"<ldap-server ldif='classpath:test-server.ldif' port='0'/>");
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='0'/>");
|
||||
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx
|
||||
.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
|
||||
// Check data is loaded
|
||||
@@ -62,17 +63,14 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception {
|
||||
int port = getDefaultPort();
|
||||
// Create second "server" with a url pointing at embedded one
|
||||
appCtx = new InMemoryXmlApplicationContext(
|
||||
"<ldap-server ldif='classpath:test-server.ldif' port='"
|
||||
+ port
|
||||
+ "'/>"
|
||||
+ "<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:"
|
||||
+ port + "/dc=springframework,dc=org' />");
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='" + port
|
||||
+ "'/>" + "<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:" + port
|
||||
+ "/dc=springframework,dc=org' />");
|
||||
|
||||
// Check the default context source is still there.
|
||||
appCtx.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
this.appCtx.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx
|
||||
.getBean("blah");
|
||||
|
||||
// Check data is loaded as before
|
||||
@@ -82,9 +80,9 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void loadingSpecificLdifFileIsSuccessful() {
|
||||
appCtx = new InMemoryXmlApplicationContext(
|
||||
this.appCtx = new InMemoryXmlApplicationContext(
|
||||
"<ldap-server ldif='classpath*:test-server2.xldif' root='dc=monkeymachine,dc=co,dc=uk' port='0'/>");
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx
|
||||
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx
|
||||
.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
|
||||
LdapTemplate template = new LdapTemplate(contextSource);
|
||||
@@ -93,8 +91,8 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void defaultLdifFileIsSuccessful() {
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server/>");
|
||||
ApacheDSContainer dsContainer = appCtx.getBean(ApacheDSContainer.class);
|
||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server/>");
|
||||
ApacheDSContainer dsContainer = this.appCtx.getBean(ApacheDSContainer.class);
|
||||
|
||||
assertThat(ReflectionTestUtils.getField(dsContainer, "ldifResources")).isEqualTo("classpath*:*.ldif");
|
||||
}
|
||||
@@ -104,4 +102,5 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
return server.getLocalPort();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.ldap;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -36,11 +37,6 @@ import org.springframework.security.ldap.userdetails.PersonContextMapper;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser.INET_ORG_PERSON_MAPPER_CLASS;
|
||||
import static org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser.LDAP_AUTHORITIES_POPULATOR_CLASS;
|
||||
import static org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS;
|
||||
import static org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser.LDAP_USER_MAPPER_CLASS;
|
||||
import static org.springframework.security.config.ldap.LdapUserServiceBeanDefinitionParser.PERSON_MAPPER_CLASS;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
@@ -48,36 +44,45 @@ import static org.springframework.security.config.ldap.LdapUserServiceBeanDefini
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
public class LdapUserServiceBeanDefinitionParserTests {
|
||||
|
||||
private InMemoryXmlApplicationContext appCtx;
|
||||
|
||||
@After
|
||||
public void closeAppContext() {
|
||||
if (appCtx != null) {
|
||||
appCtx.close();
|
||||
appCtx = null;
|
||||
if (this.appCtx != null) {
|
||||
this.appCtx.close();
|
||||
this.appCtx = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanClassNamesAreCorrect() {
|
||||
assertThat(FilterBasedLdapUserSearch.class.getName()).isEqualTo(LDAP_SEARCH_CLASS);
|
||||
assertThat(PersonContextMapper.class.getName()).isEqualTo(PERSON_MAPPER_CLASS);
|
||||
assertThat(InetOrgPersonContextMapper.class.getName()).isEqualTo(INET_ORG_PERSON_MAPPER_CLASS);
|
||||
assertThat(LdapUserDetailsMapper.class.getName()).isEqualTo(LDAP_USER_MAPPER_CLASS);
|
||||
assertThat(DefaultLdapAuthoritiesPopulator.class.getName()).isEqualTo(LDAP_AUTHORITIES_POPULATOR_CLASS);
|
||||
assertThat(new LdapUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class))).isEqualTo(LdapUserDetailsService.class.getName());
|
||||
assertThat(FilterBasedLdapUserSearch.class.getName())
|
||||
.isEqualTo(LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS);
|
||||
assertThat(PersonContextMapper.class.getName())
|
||||
.isEqualTo(LdapUserServiceBeanDefinitionParser.PERSON_MAPPER_CLASS);
|
||||
assertThat(InetOrgPersonContextMapper.class.getName())
|
||||
.isEqualTo(LdapUserServiceBeanDefinitionParser.INET_ORG_PERSON_MAPPER_CLASS);
|
||||
assertThat(LdapUserDetailsMapper.class.getName())
|
||||
.isEqualTo(LdapUserServiceBeanDefinitionParser.LDAP_USER_MAPPER_CLASS);
|
||||
assertThat(DefaultLdapAuthoritiesPopulator.class.getName())
|
||||
.isEqualTo(LdapUserServiceBeanDefinitionParser.LDAP_AUTHORITIES_POPULATOR_CLASS);
|
||||
assertThat(new LdapUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class)))
|
||||
.isEqualTo(LdapUserDetailsService.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minimalConfigurationIsParsedOk() {
|
||||
setContext("<ldap-user-service user-search-filter='(uid={0})' /><ldap-server ldif='classpath:test-server.ldif' url='ldap://127.0.0.1:343/dc=springframework,dc=org' />");
|
||||
setContext(
|
||||
"<ldap-user-service user-search-filter='(uid={0})' /><ldap-server ldif='classpath:test-server.ldif' url='ldap://127.0.0.1:343/dc=springframework,dc=org' />");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userServiceReturnsExpectedData() {
|
||||
setContext("<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-search-filter='member={0}' /><ldap-server ldif='classpath:test-server.ldif'/>");
|
||||
setContext(
|
||||
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-search-filter='member={0}' /><ldap-server ldif='classpath:test-server.ldif'/>");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
|
||||
@@ -87,12 +92,11 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void differentUserSearchBaseWorksAsExpected() {
|
||||
setContext("<ldap-user-service id='ldapUDS' "
|
||||
+ " user-search-base='ou=otherpeople' "
|
||||
setContext("<ldap-user-service id='ldapUDS' " + " user-search-base='ou=otherpeople' "
|
||||
+ " user-search-filter='(cn={0})' "
|
||||
+ " group-search-filter='member={0}' /><ldap-server ldif='classpath:test-server.ldif'/>");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails joe = uds.loadUserByUsername("Joe Smeth");
|
||||
|
||||
assertThat(joe.getUsername()).isEqualTo("Joe Smeth");
|
||||
@@ -100,27 +104,26 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void rolePrefixIsSupported() {
|
||||
setContext("<ldap-user-service id='ldapUDS' "
|
||||
+ " user-search-filter='(uid={0})' "
|
||||
setContext("<ldap-user-service id='ldapUDS' " + " user-search-filter='(uid={0})' "
|
||||
+ " group-search-filter='member={0}' role-prefix='PREFIX_'/>"
|
||||
+ "<ldap-user-service id='ldapUDSNoPrefix' "
|
||||
+ " user-search-filter='(uid={0})' "
|
||||
+ "<ldap-user-service id='ldapUDSNoPrefix' " + " user-search-filter='(uid={0})' "
|
||||
+ " group-search-filter='member={0}' role-prefix='none'/><ldap-server ldif='classpath:test-server.ldif'/>");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertThat(AuthorityUtils.authorityListToSet(ben.getAuthorities())).contains("PREFIX_DEVELOPERS");
|
||||
|
||||
uds = (UserDetailsService) appCtx.getBean("ldapUDSNoPrefix");
|
||||
uds = (UserDetailsService) this.appCtx.getBean("ldapUDSNoPrefix");
|
||||
ben = uds.loadUserByUsername("ben");
|
||||
assertThat(AuthorityUtils.authorityListToSet(ben.getAuthorities())).contains("DEVELOPERS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void differentGroupRoleAttributeWorksAsExpected() {
|
||||
setContext("<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-role-attribute='ou' group-search-filter='member={0}' /><ldap-server ldif='classpath:test-server.ldif'/>");
|
||||
setContext(
|
||||
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-role-attribute='ou' group-search-filter='member={0}' /><ldap-server ldif='classpath:test-server.ldif'/>");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
|
||||
@@ -131,18 +134,18 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
|
||||
@Test
|
||||
public void isSupportedByAuthenticationProviderElement() {
|
||||
setContext("<ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org' ldif='classpath:test-server.ldif'/>"
|
||||
+ "<authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <ldap-user-service user-search-filter='(uid={0})' />"
|
||||
+ " </authentication-provider>" + "</authentication-manager>");
|
||||
setContext(
|
||||
"<ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org' ldif='classpath:test-server.ldif'/>"
|
||||
+ "<authentication-manager>" + " <authentication-provider>"
|
||||
+ " <ldap-user-service user-search-filter='(uid={0})' />" + " </authentication-provider>"
|
||||
+ "</authentication-manager>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void personContextMapperIsSupported() {
|
||||
setContext("<ldap-server ldif='classpath:test-server.ldif'/>"
|
||||
+ "<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='person'/>");
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertThat(ben instanceof Person).isTrue();
|
||||
}
|
||||
@@ -151,7 +154,7 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
public void inetOrgContextMapperIsSupported() {
|
||||
setContext("<ldap-server id='someServer' ldif='classpath:test-server.ldif'/>"
|
||||
+ "<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='inetOrgPerson'/>");
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertThat(ben instanceof InetOrgPerson).isTrue();
|
||||
}
|
||||
@@ -160,15 +163,15 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
||||
public void externalContextMapperIsSupported() {
|
||||
setContext("<ldap-server id='someServer' ldif='classpath:test-server.ldif'/>"
|
||||
+ "<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-context-mapper-ref='mapper'/>"
|
||||
+ "<b:bean id='mapper' class='"
|
||||
+ InetOrgPersonContextMapper.class.getName() + "'/>");
|
||||
+ "<b:bean id='mapper' class='" + InetOrgPersonContextMapper.class.getName() + "'/>");
|
||||
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetailsService uds = (UserDetailsService) this.appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertThat(ben instanceof InetOrgPerson).isTrue();
|
||||
}
|
||||
|
||||
private void setContext(String context) {
|
||||
appCtx = new InMemoryXmlApplicationContext(context);
|
||||
this.appCtx = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user