13 changed files with 625 additions and 943 deletions
@ -1,220 +0,0 @@
@@ -1,220 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* 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.beans.factory.config.AutowireCapableBeanFactory |
||||
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Bean |
||||
import org.springframework.context.annotation.Configuration |
||||
import org.springframework.context.annotation.Import |
||||
import org.springframework.ldap.core.ContextSource; |
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource; |
||||
import org.springframework.security.authentication.AuthenticationManager |
||||
import org.springframework.security.authentication.AuthenticationProvider |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken |
||||
import org.springframework.security.config.annotation.BaseSpringSpec |
||||
import org.springframework.security.config.annotation.SecurityBuilder; |
||||
import org.springframework.security.config.annotation.authentication.AuthenticationManagerBuilder |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder |
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication |
||||
import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor |
||||
import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests |
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration |
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
||||
import org.springframework.security.crypto.password.PasswordEncoder |
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource; |
||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; |
||||
import org.springframework.security.ldap.server.ApacheDSContainer; |
||||
import org.springframework.test.util.ReflectionTestUtils; |
||||
|
||||
/** |
||||
* |
||||
* @author Rob Winch |
||||
* |
||||
*/ |
||||
class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSpec { |
||||
def "default configuration"() { |
||||
when: |
||||
loadConfig(DefaultLdapConfig) |
||||
LdapAuthenticationProvider provider = ldapProvider() |
||||
then: |
||||
provider.authoritiesPopulator.groupRoleAttribute == "cn" |
||||
provider.authoritiesPopulator.groupSearchBase == "" |
||||
provider.authoritiesPopulator.groupSearchFilter == "(uniqueMember={0})" |
||||
ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "ROLE_" |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
static class DefaultLdapConfig extends BaseLdapProviderConfig { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.contextSource(contextSource()) |
||||
.userDnPatterns("uid={0},ou=people") |
||||
} |
||||
} |
||||
|
||||
def "group roles custom"() { |
||||
when: |
||||
loadConfig(GroupRolesConfig) |
||||
LdapAuthenticationProvider provider = ldapProvider() |
||||
then: |
||||
provider.authoritiesPopulator.groupRoleAttribute == "group" |
||||
} |
||||
|
||||
@Configuration |
||||
static class GroupRolesConfig extends BaseLdapProviderConfig { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.contextSource(contextSource()) |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.groupRoleAttribute("group") |
||||
} |
||||
} |
||||
|
||||
def "group search custom"() { |
||||
when: |
||||
loadConfig(GroupSearchConfig) |
||||
LdapAuthenticationProvider provider = ldapProvider() |
||||
then: |
||||
provider.authoritiesPopulator.groupSearchFilter == "ou=groupName" |
||||
} |
||||
|
||||
@Configuration |
||||
static class GroupSearchConfig extends BaseLdapProviderConfig { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.contextSource(contextSource()) |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.groupSearchFilter("ou=groupName"); |
||||
} |
||||
} |
||||
|
||||
def "role prefix custom"() { |
||||
when: |
||||
loadConfig(RolePrefixConfig) |
||||
LdapAuthenticationProvider provider = ldapProvider() |
||||
then: |
||||
ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "role_" |
||||
} |
||||
|
||||
@Configuration |
||||
static class RolePrefixConfig extends BaseLdapProviderConfig { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.contextSource(contextSource()) |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.rolePrefix("role_") |
||||
} |
||||
} |
||||
|
||||
def "bind authentication"() { |
||||
when: |
||||
loadConfig(BindAuthenticationConfig) |
||||
AuthenticationManager auth = context.getBean(AuthenticationManager) |
||||
then: |
||||
auth |
||||
auth.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"] |
||||
} |
||||
|
||||
@Configuration |
||||
static class BindAuthenticationConfig extends BaseLdapServerConfig { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.contextSource(contextSource()) |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people"); |
||||
} |
||||
} |
||||
|
||||
def "SEC-2472: Can use crypto PasswordEncoder"() { |
||||
setup: |
||||
loadConfig(PasswordEncoderConfig) |
||||
when: |
||||
AuthenticationManager auth = context.getBean(AuthenticationManager) |
||||
then: |
||||
auth.authenticate(new UsernamePasswordAuthenticationToken("bcrypt","password")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"] |
||||
} |
||||
|
||||
@Configuration |
||||
static class PasswordEncoderConfig extends BaseLdapServerConfig { |
||||
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"); |
||||
} |
||||
} |
||||
|
||||
def ldapProvider() { |
||||
context.getBean(AuthenticationManager).providers[0] |
||||
} |
||||
|
||||
@Configuration |
||||
static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig { |
||||
@Bean |
||||
public ApacheDSContainer ldapServer() throws Exception { |
||||
ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif"); |
||||
apacheDSContainer.setPort(getPort()); |
||||
return apacheDSContainer; |
||||
} |
||||
} |
||||
|
||||
@Configuration |
||||
@EnableGlobalAuthentication |
||||
@Import(ObjectPostProcessorConfiguration) |
||||
static abstract class BaseLdapProviderConfig { |
||||
|
||||
@Bean |
||||
public BaseLdapPathContextSource contextSource() throws Exception { |
||||
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource( |
||||
"ldap://127.0.0.1:"+ getPort() + "/dc=springframework,dc=org") |
||||
contextSource.userDn = "uid=admin,ou=system" |
||||
contextSource.password = "secret" |
||||
contextSource.afterPropertiesSet() |
||||
return contextSource; |
||||
} |
||||
|
||||
@Bean |
||||
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) { |
||||
configure(auth) |
||||
auth.build() |
||||
} |
||||
|
||||
abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception |
||||
} |
||||
|
||||
static Integer port; |
||||
|
||||
static int getPort() { |
||||
if(port == null) { |
||||
ServerSocket socket = new ServerSocket(0) |
||||
port = socket.localPort |
||||
socket.close() |
||||
} |
||||
port |
||||
} |
||||
} |
||||
@ -1,90 +0,0 @@
@@ -1,90 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* 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.authentication.UsernamePasswordAuthenticationToken |
||||
import org.springframework.security.config.annotation.BaseSpringSpec |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter |
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority |
||||
|
||||
/** |
||||
* |
||||
* @author Rob Winch |
||||
* @author Eddú Meléndez |
||||
* |
||||
*/ |
||||
class LdapAuthenticationProviderConfigurerTests extends BaseSpringSpec { |
||||
|
||||
def "authentication-manager support multiple default ldap contexts (ports dynamically allocated)"() { |
||||
when: |
||||
loadConfig(MultiLdapAuthenticationProvidersConfig) |
||||
then: |
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")) |
||||
} |
||||
|
||||
def "authentication-manager support multiple ldap context with default role prefix" () { |
||||
when: |
||||
loadConfig(MultiLdapAuthenticationProvidersConfig) |
||||
then: |
||||
def authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob", "bobspassword")) |
||||
authenticate.authorities.contains(new SimpleGrantedAuthority("ROLE_DEVELOPERS")) |
||||
} |
||||
|
||||
def "authentication-manager support multiple ldap context with custom role prefix"() { |
||||
when: |
||||
loadConfig(MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig) |
||||
then: |
||||
def authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob", "bobspassword")) |
||||
authenticate.authorities.contains(new SimpleGrantedAuthority("ROL_DEVELOPERS")) |
||||
} |
||||
|
||||
@EnableWebSecurity |
||||
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.and() |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
} |
||||
} |
||||
|
||||
@EnableWebSecurity |
||||
static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends |
||||
WebSecurityConfigurerAdapter { |
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.rolePrefix("ROL_") |
||||
.and() |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.rolePrefix("RUOLO_") |
||||
} |
||||
} |
||||
} |
||||
@ -1,80 +0,0 @@
@@ -1,80 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.config.annotation.authentication.ldap |
||||
|
||||
import static org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.* |
||||
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource |
||||
import org.springframework.security.authentication.AuthenticationManager |
||||
import org.springframework.security.authentication.AuthenticationProvider |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken |
||||
import org.springframework.security.config.annotation.BaseSpringSpec |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.LdapAuthenticationProviderConfig; |
||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; |
||||
import org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator; |
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; |
||||
import org.springframework.security.ldap.userdetails.PersonContextMapper; |
||||
import org.springframework.test.util.ReflectionTestUtils; |
||||
|
||||
/** |
||||
* |
||||
* @author Rob Winch |
||||
* |
||||
*/ |
||||
class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec { |
||||
def "ldap-authentication-provider"() { |
||||
when: |
||||
loadConfig(LdapAuthenticationProviderConfig) |
||||
then: |
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")) |
||||
} |
||||
|
||||
def "ldap-authentication-provider custom"() { |
||||
when: |
||||
loadConfig(CustomLdapAuthenticationProviderConfig) |
||||
LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider) |
||||
then: |
||||
provider.authoritiesPopulator.groupRoleAttribute == "cn" |
||||
provider.authoritiesPopulator.groupSearchBase == "ou=groups" |
||||
provider.authoritiesPopulator.groupSearchFilter == "(member={0})" |
||||
ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "PREFIX_" |
||||
provider.userDetailsContextMapper instanceof PersonContextMapper |
||||
provider.authenticator.getUserDns("user") == ["uid=user,ou=people"] |
||||
provider.authenticator.userSearch.searchBase == "ou=users" |
||||
provider.authenticator.userSearch.searchFilter == "(uid={0})" |
||||
} |
||||
|
||||
def "SEC-2490: ldap-authentication-provider custom LdapAuthoritiesPopulator"() { |
||||
setup: |
||||
LdapAuthoritiesPopulator LAP = Mock() |
||||
CustomAuthoritiesPopulatorConfig.LAP = LAP |
||||
when: |
||||
loadConfig(CustomAuthoritiesPopulatorConfig) |
||||
LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider) |
||||
then: |
||||
provider.authoritiesPopulator == LAP |
||||
} |
||||
|
||||
def "ldap-authentication-provider password compare"() { |
||||
when: |
||||
loadConfig(PasswordCompareLdapConfig) |
||||
LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider) |
||||
then: |
||||
provider.authenticator instanceof PasswordComparisonAuthenticator |
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")) |
||||
} |
||||
} |
||||
@ -1,164 +0,0 @@
@@ -1,164 +0,0 @@
|
||||
package org.springframework.security.config.ldap |
||||
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder |
||||
|
||||
import static org.mockito.Mockito.* |
||||
|
||||
import java.text.MessageFormat |
||||
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer |
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
||||
import org.springframework.security.crypto.password.PasswordEncoder |
||||
import org.springframework.security.config.AbstractXmlConfigTests |
||||
import org.springframework.security.config.BeanIds |
||||
import org.springframework.security.util.FieldUtils |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken |
||||
import org.springframework.context.ApplicationContextException |
||||
import org.springframework.security.core.AuthenticationException |
||||
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper |
||||
|
||||
/** |
||||
* @author Luke Taylor |
||||
*/ |
||||
class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests { |
||||
|
||||
// SEC-1182 |
||||
def multipleProvidersAreSupported() { |
||||
xml.'ldap-server'(url: 'ldap://blah:389/dc=blah') |
||||
xml.'authentication-manager'() { |
||||
'ldap-authentication-provider'('group-search-filter': 'member={0}') |
||||
'ldap-authentication-provider'('group-search-filter': 'uniqueMember={0}') |
||||
} |
||||
|
||||
createAppContext('') |
||||
|
||||
def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers |
||||
|
||||
expect: |
||||
|
||||
providers.size() == 2 |
||||
providers[0].authoritiesPopulator.groupSearchFilter == "member={0}" |
||||
providers[1].authoritiesPopulator.groupSearchFilter == "uniqueMember={0}" |
||||
} |
||||
|
||||
|
||||
def simpleProviderAuthenticatesCorrectly() { |
||||
xml.'ldap-server'(ldif:'test-server.ldif') |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'('group-search-filter':'member={0}') |
||||
} |
||||
|
||||
createAppContext('') |
||||
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) |
||||
|
||||
when: |
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")) |
||||
def ben = auth.principal; |
||||
|
||||
then: |
||||
ben.authorities.size() == 3 |
||||
} |
||||
|
||||
def missingServerEltCausesConfigException() { |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'() |
||||
} |
||||
|
||||
when: |
||||
createAppContext('') |
||||
|
||||
then: |
||||
thrown(ApplicationContextException) |
||||
} |
||||
|
||||
def supportsPasswordComparisonAuthentication() { |
||||
xml.'ldap-server'(ldif:'test-server.ldif') |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') |
||||
'password-compare' |
||||
} |
||||
createAppContext('') |
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) |
||||
|
||||
when: |
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")) |
||||
|
||||
then: |
||||
auth != null |
||||
notThrown(AuthenticationException) |
||||
} |
||||
|
||||
def supportsPasswordComparisonAuthenticationWithPasswordEncoder() { |
||||
xml.'ldap-server'(ldif:'test-server.ldif') |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') { |
||||
'password-compare'('password-attribute': 'uid') { |
||||
'password-encoder'(ref: 'passwordEncoder') |
||||
} |
||||
} |
||||
} |
||||
xml.'b:bean'(id: 'passwordEncoder', 'class' : NoOpPasswordEncoder.name, 'factory-method': 'getInstance') |
||||
|
||||
createAppContext('') |
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) |
||||
|
||||
when: |
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben")) |
||||
|
||||
then: |
||||
auth != null |
||||
notThrown(AuthenticationException) |
||||
} |
||||
|
||||
def 'SEC-2472: Supports Crypto PasswordEncoder'() { |
||||
setup: |
||||
xml.'ldap-server'(ldif:'test-server.ldif') |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') { |
||||
'password-compare'() { |
||||
'password-encoder'(ref: 'pe') |
||||
} |
||||
} |
||||
} |
||||
xml.'b:bean'(id:'pe','class':BCryptPasswordEncoder.class.name) |
||||
|
||||
createAppContext('') |
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) |
||||
|
||||
when: |
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password')) |
||||
|
||||
then: |
||||
auth != null |
||||
} |
||||
|
||||
def inetOrgContextMapperIsSupported() { |
||||
xml.'ldap-server'(url: 'ldap://127.0.0.1:343/dc=springframework,dc=org') |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'('user-details-class' :'inetOrgPerson') |
||||
} |
||||
createAppContext('') |
||||
|
||||
expect: |
||||
appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0].userDetailsContextMapper instanceof InetOrgPersonContextMapper |
||||
} |
||||
|
||||
def ldapAuthenticationProviderWorksWithPlaceholders() { |
||||
System.setProperty('udp','people') |
||||
System.setProperty('gsf','member') |
||||
|
||||
xml.'ldap-server'() |
||||
xml.'authentication-manager'{ |
||||
'ldap-authentication-provider'('user-dn-pattern':'uid={0},ou=${udp}','group-search-filter':'${gsf}={0}') |
||||
} |
||||
bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class) |
||||
|
||||
createAppContext('') |
||||
def provider = this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0] |
||||
|
||||
expect: |
||||
[new MessageFormat("uid={0},ou=people")] == FieldUtils.getFieldValue(provider,"authenticator.userDnFormat") |
||||
"member={0}" == FieldUtils.getFieldValue(provider, "authoritiesPopulator.groupSearchFilter") |
||||
} |
||||
} |
||||
@ -0,0 +1,250 @@
@@ -0,0 +1,250 @@
|
||||
/* |
||||
* Copyright 2002-2019 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap; |
||||
|
||||
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; |
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource; |
||||
import org.springframework.security.authentication.AuthenticationManager; |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication; |
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
||||
import org.springframework.security.config.test.SpringTestRule; |
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; |
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource; |
||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; |
||||
import org.springframework.security.ldap.server.ApacheDSContainer; |
||||
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 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 { |
||||
@Rule |
||||
public final SpringTestRule spring = new SpringTestRule(); |
||||
|
||||
@Autowired |
||||
private MockMvc mockMvc; |
||||
|
||||
@Autowired |
||||
private AuthenticationManager authenticationManager; |
||||
|
||||
@Test |
||||
public void defaultConfiguration() { |
||||
this.spring.register(DefaultLdapConfig.class).autowire(); |
||||
LdapAuthenticationProvider provider = ldapProvider(); |
||||
|
||||
LdapAuthoritiesPopulator authoritiesPopulator = getAuthoritiesPopulator(provider); |
||||
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupRoleAttribute", "cn"); |
||||
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchBase", ""); |
||||
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchFilter", "(uniqueMember={0})"); |
||||
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
|
||||
} |
||||
|
||||
@Test |
||||
public void groupSearchCustom() { |
||||
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
|
||||
} |
||||
|
||||
@Test |
||||
public void rolePrefixCustom() { |
||||
this.spring.register(RolePrefixConfig.class).autowire(); |
||||
LdapAuthenticationProvider provider = ldapProvider(); |
||||
|
||||
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
|
||||
} |
||||
|
||||
// SEC-2472
|
||||
@Test |
||||
public void canUseCryptoPasswordEncoder() throws Exception { |
||||
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
|
||||
} |
||||
|
||||
private LdapAuthenticationProvider ldapProvider() { |
||||
return ((List<LdapAuthenticationProvider>) ReflectionTestUtils.getField(authenticationManager, "providers")).get(0); |
||||
} |
||||
|
||||
private LdapAuthoritiesPopulator getAuthoritiesPopulator(LdapAuthenticationProvider provider) { |
||||
return (LdapAuthoritiesPopulator) ReflectionTestUtils.getField(provider, "authoritiesPopulator"); |
||||
} |
||||
|
||||
private GrantedAuthoritiesMapper getAuthoritiesMapper(LdapAuthenticationProvider provider) { |
||||
return (GrantedAuthoritiesMapper) ReflectionTestUtils.getField(provider, "authoritiesMapper"); |
||||
} |
||||
|
||||
@EnableWebSecurity |
||||
static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig { |
||||
@Bean |
||||
public 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 { |
||||
|
||||
@Bean |
||||
public BaseLdapPathContextSource contextSource() throws Exception { |
||||
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource( |
||||
"ldap://127.0.0.1:" + getPort() + "/dc=springframework,dc=org"); |
||||
contextSource.setUserDn("uid=admin,ou=system"); |
||||
contextSource.setPassword("secret"); |
||||
contextSource.afterPropertiesSet(); |
||||
return contextSource; |
||||
} |
||||
|
||||
@Bean |
||||
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception { |
||||
configure(auth); |
||||
return auth.build(); |
||||
} |
||||
|
||||
abstract protected 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; |
||||
} |
||||
} |
||||
@ -0,0 +1,101 @@
@@ -0,0 +1,101 @@
|
||||
/* |
||||
* Copyright 2002-2019 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap; |
||||
|
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
||||
import org.springframework.security.config.test.SpringTestRule; |
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
||||
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(); |
||||
|
||||
@Autowired |
||||
private MockMvc mockMvc; |
||||
|
||||
@Test |
||||
public void authenticationManagerSupportMultipleDefaultLdapContextsWithPortsDynamicallyAllocated() throws Exception { |
||||
this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire(); |
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) |
||||
.andExpect(authenticated().withUsername("bob")); |
||||
} |
||||
|
||||
@Test |
||||
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")))); |
||||
} |
||||
|
||||
@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")))); |
||||
} |
||||
|
||||
@EnableWebSecurity |
||||
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { |
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.and() |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people"); |
||||
} |
||||
// @formatter:on
|
||||
} |
||||
|
||||
@EnableWebSecurity |
||||
static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { |
||||
// @formatter:off
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.rolePrefix("ROL_") |
||||
.and() |
||||
.ldapAuthentication() |
||||
.groupSearchBase("ou=groups") |
||||
.groupSearchFilter("(member={0})") |
||||
.userDnPatterns("uid={0},ou=people") |
||||
.rolePrefix("RUOLO_"); |
||||
} |
||||
// @formatter:on
|
||||
} |
||||
} |
||||
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
/* |
||||
* Copyright 2002-2019 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.config.annotation.authentication.ldap; |
||||
|
||||
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; |
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.CustomAuthoritiesPopulatorConfig; |
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.CustomLdapAuthenticationProviderConfig; |
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.LdapAuthenticationProviderConfig; |
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.PasswordCompareLdapConfig; |
||||
import org.springframework.security.config.test.SpringTestRule; |
||||
import org.springframework.security.core.GrantedAuthority; |
||||
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.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; |
||||
|
||||
public class NamespaceLdapAuthenticationProviderTests { |
||||
|
||||
@Rule |
||||
public final SpringTestRule spring = new SpringTestRule(); |
||||
|
||||
@Autowired |
||||
private MockMvc mockMvc; |
||||
|
||||
@Autowired |
||||
private FilterChainProxy filterChainProxy; |
||||
|
||||
@Test |
||||
public void ldapAuthenticationProvider() throws Exception { |
||||
this.spring.register(LdapAuthenticationProviderConfig.class).autowire(); |
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) |
||||
.andExpect(authenticated().withUsername("bob")); |
||||
} |
||||
|
||||
@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")))); |
||||
} |
||||
|
||||
// SEC-2490
|
||||
@Test |
||||
public void ldapAuthenticationProviderCustomLdapAuthoritiesPopulator() throws Exception { |
||||
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) { |
||||
return new HashSet<>(AuthorityUtils.createAuthorityList("ROLE_EXTRA")); |
||||
} |
||||
}; |
||||
|
||||
this.spring.register(CustomAuthoritiesPopulatorConfig.class).autowire(); |
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) |
||||
.andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")))); |
||||
} |
||||
|
||||
@Test |
||||
public void ldapAuthenticationProviderPasswordCompare() throws Exception { |
||||
this.spring.register(PasswordCompareLdapConfig.class).autowire(); |
||||
|
||||
this.mockMvc.perform(formLogin().user("bcrypt").password("password")) |
||||
.andExpect(authenticated().withUsername("bcrypt")); |
||||
} |
||||
} |
||||
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
/* |
||||
* Copyright 2002-2019 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.config.ldap; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Test; |
||||
import org.springframework.context.ApplicationContextException; |
||||
import org.springframework.security.authentication.AuthenticationManager; |
||||
import org.springframework.security.authentication.AuthenticationProvider; |
||||
import org.springframework.security.authentication.ProviderManager; |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
||||
import org.springframework.security.config.BeanIds; |
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper; |
||||
|
||||
import java.text.MessageFormat; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class LdapProviderBeanDefinitionParserTests { |
||||
InMemoryXmlApplicationContext appCtx; |
||||
|
||||
@After |
||||
public void closeAppContext() { |
||||
if (appCtx != null) { |
||||
appCtx.close(); |
||||
appCtx = null; |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void simpleProviderAuthenticatesCorrectly() { |
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif'/>" |
||||
+ "<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")); |
||||
UserDetails ben = (UserDetails) auth.getPrincipal(); |
||||
assertThat(ben.getAuthorities()).hasSize(3); |
||||
} |
||||
|
||||
@Test |
||||
public void multipleProvidersAreSupported() { |
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif'/>" |
||||
+ "<authentication-manager>" |
||||
+ " <ldap-authentication-provider group-search-filter='member={0}' />" |
||||
+ " <ldap-authentication-provider group-search-filter='uniqueMember={0}' />" |
||||
+ "</authentication-manager>" |
||||
); |
||||
|
||||
ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); |
||||
assertThat(providerManager.getProviders()).hasSize(2); |
||||
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>" |
||||
); |
||||
} |
||||
|
||||
@Test |
||||
public void supportsPasswordComparisonAuthentication() { |
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif'/>" |
||||
+ "<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")); |
||||
|
||||
assertThat(auth).isNotNull(); |
||||
} |
||||
|
||||
@Test |
||||
public void supportsPasswordComparisonAuthenticationWithPasswordEncoder() { |
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif'/>" |
||||
+ "<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); |
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben")); |
||||
|
||||
assertThat(auth).isNotNull(); |
||||
} |
||||
|
||||
// SEC-2472
|
||||
@Test |
||||
public void supportsCryptoPasswordEncoder() { |
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif'/>" |
||||
+ "<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")); |
||||
|
||||
assertThat(auth).isNotNull(); |
||||
} |
||||
|
||||
@Test |
||||
public void inetOrgContextMapperIsSupported() { |
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org'/>" |
||||
+ "<authentication-manager>" |
||||
+ " <ldap-authentication-provider user-details-class='inetOrgPerson' />" |
||||
+ "</authentication-manager>" |
||||
); |
||||
|
||||
ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); |
||||
assertThat(providerManager.getProviders()).hasSize(1); |
||||
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>" |
||||
+ " <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' />" |
||||
); |
||||
|
||||
ProviderManager providerManager = 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}")); |
||||
} |
||||
} |
||||
@ -1,106 +0,0 @@
@@ -1,106 +0,0 @@
|
||||
package org.springframework.security.config |
||||
|
||||
import groovy.xml.MarkupBuilder |
||||
import org.mockito.Mockito |
||||
import org.springframework.context.ApplicationListener |
||||
import org.springframework.context.support.AbstractRefreshableApplicationContext |
||||
import org.springframework.mock.web.MockServletContext |
||||
import org.springframework.security.CollectingAppListener |
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext |
||||
import org.springframework.security.config.util.InMemoryXmlWebApplicationContext |
||||
import org.springframework.security.core.context.SecurityContextHolder |
||||
import spock.lang.Specification |
||||
|
||||
import javax.servlet.ServletContext |
||||
|
||||
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML |
||||
/** |
||||
* |
||||
* @author Luke Taylor |
||||
*/ |
||||
abstract class AbstractXmlConfigTests extends Specification { |
||||
AbstractRefreshableApplicationContext appContext; |
||||
Writer writer; |
||||
MarkupBuilder xml; |
||||
ApplicationListener appListener; |
||||
|
||||
def setup() { |
||||
writer = new StringWriter() |
||||
xml = new MarkupBuilder(writer) |
||||
appListener = new CollectingAppListener() |
||||
} |
||||
|
||||
def cleanup() { |
||||
if (appContext != null) { |
||||
appContext.close(); |
||||
appContext = null; |
||||
} |
||||
SecurityContextHolder.clearContext(); |
||||
} |
||||
|
||||
def mockBean(Class clazz, String id = clazz.simpleName) { |
||||
xml.'b:bean'(id: id, 'class': Mockito.class.name, 'factory-method':'mock') { |
||||
'b:constructor-arg'(value : clazz.name) |
||||
'b:constructor-arg'(value : id) |
||||
} |
||||
} |
||||
|
||||
def bean(String name, Class clazz) { |
||||
xml.'b:bean'(id: name, 'class': clazz.name) |
||||
} |
||||
|
||||
def bean(String name, String clazz) { |
||||
xml.'b:bean'(id: name, 'class': clazz) |
||||
} |
||||
|
||||
def bean(String name, String clazz, List constructorArgs) { |
||||
xml.'b:bean'(id: name, 'class': clazz) { |
||||
constructorArgs.each { val -> |
||||
'b:constructor-arg'(value: val) |
||||
} |
||||
} |
||||
} |
||||
|
||||
def bean(String name, String clazz, Map properties, Map refs) { |
||||
xml.'b:bean'(id: name, 'class': clazz) { |
||||
properties.each {key, val -> |
||||
'b:property'(name: key, value: val) |
||||
} |
||||
refs.each {key, val -> |
||||
'b:property'(name: key, ref: val) |
||||
} |
||||
} |
||||
} |
||||
|
||||
def createAppContext() { |
||||
createAppContext(AUTH_PROVIDER_XML) |
||||
} |
||||
|
||||
def createAppContext(String extraXml) { |
||||
appContext = new InMemoryXmlApplicationContext(writer.toString() + extraXml); |
||||
appContext.addApplicationListener(appListener); |
||||
} |
||||
|
||||
def createWebAppContext() { |
||||
createWebAppContext(AUTH_PROVIDER_XML); |
||||
} |
||||
|
||||
def createWebAppContext(ServletContext servletContext) { |
||||
createWebAppContext(AUTH_PROVIDER_XML, servletContext); |
||||
} |
||||
|
||||
def createWebAppContext(String extraXml) { |
||||
createWebAppContext(extraXml, null); |
||||
} |
||||
|
||||
def createWebAppContext(String extraXml, ServletContext servletContext) { |
||||
appContext = new InMemoryXmlWebApplicationContext(writer.toString() + extraXml); |
||||
appContext.addApplicationListener(appListener); |
||||
if (servletContext != null) { |
||||
appContext.setServletContext(servletContext); |
||||
} else { |
||||
appContext.setServletContext(new MockServletContext()); |
||||
} |
||||
appContext.refresh(); |
||||
} |
||||
} |
||||
@ -1,25 +0,0 @@
@@ -1,25 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.config.annotation; |
||||
|
||||
/** |
||||
* Exists for mocking purposes to ensure that the Type information is found. |
||||
* |
||||
* @author Rob Winch |
||||
*/ |
||||
public interface AnyObjectPostProcessor extends ObjectPostProcessor<Object> { |
||||
|
||||
} |
||||
@ -1,174 +0,0 @@
@@ -1,174 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.security.config.annotation; |
||||
|
||||
import javax.servlet.Filter |
||||
|
||||
import spock.lang.AutoCleanup |
||||
import spock.lang.Specification |
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException |
||||
import org.springframework.context.ConfigurableApplicationContext |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext |
||||
import org.springframework.mock.web.MockFilterChain |
||||
import org.springframework.mock.web.MockHttpServletRequest |
||||
import org.springframework.mock.web.MockHttpServletResponse |
||||
import org.springframework.mock.web.MockServletContext |
||||
import org.springframework.security.authentication.AuthenticationManager |
||||
import org.springframework.security.authentication.AuthenticationProvider |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder |
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration |
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration |
||||
import org.springframework.security.core.Authentication |
||||
import org.springframework.security.core.authority.AuthorityUtils |
||||
import org.springframework.security.core.context.SecurityContextHolder |
||||
import org.springframework.security.core.context.SecurityContextImpl |
||||
import org.springframework.security.web.FilterChainProxy |
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor |
||||
import org.springframework.security.web.context.HttpRequestResponseHolder |
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository |
||||
import org.springframework.security.web.csrf.CsrfToken |
||||
import org.springframework.security.web.csrf.DefaultCsrfToken |
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository |
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext |
||||
|
||||
/** |
||||
* |
||||
* @author Rob Winch |
||||
*/ |
||||
abstract class BaseSpringSpec extends Specification { |
||||
boolean allowCircularReferences = false |
||||
@AutoCleanup |
||||
ConfigurableApplicationContext context |
||||
@AutoCleanup |
||||
ConfigurableApplicationContext oppContext |
||||
|
||||
MockHttpServletRequest request |
||||
MockHttpServletResponse response |
||||
MockFilterChain chain |
||||
CsrfToken csrfToken |
||||
AuthenticationManagerBuilder authenticationBldr |
||||
|
||||
def setup() { |
||||
authenticationBldr = createAuthenticationManagerBuilder() |
||||
setupWeb(null) |
||||
} |
||||
|
||||
def setupWeb(httpSession = null) { |
||||
request = new MockHttpServletRequest(method:"GET") |
||||
if(httpSession) { |
||||
request.session = httpSession |
||||
} |
||||
response = new MockHttpServletResponse() |
||||
chain = new MockFilterChain() |
||||
setupCsrf() |
||||
} |
||||
|
||||
def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN",req=request,resp=response) { |
||||
csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue) |
||||
new HttpSessionCsrfTokenRepository().saveToken(csrfToken, req, resp) |
||||
req.setParameter(csrfToken.parameterName, csrfToken.token) |
||||
} |
||||
|
||||
def cleanup() { |
||||
SecurityContextHolder.clearContext() |
||||
} |
||||
|
||||
def loadConfig(Class<?>... configs) { |
||||
context = new AnnotationConfigWebApplicationContext() |
||||
context.setAllowCircularReferences(allowCircularReferences) |
||||
context.register(configs) |
||||
context.setServletContext(new MockServletContext()) |
||||
context.refresh() |
||||
context |
||||
} |
||||
|
||||
def findFilter(Class<?> filter, int index = 0) { |
||||
filterChain(index).filters.find { filter.isAssignableFrom(it.class)} |
||||
} |
||||
|
||||
def filterChain(int index=0) { |
||||
filterChains()[index] |
||||
} |
||||
|
||||
def filterChains() { |
||||
context.getBean(FilterChainProxy).filterChains |
||||
} |
||||
|
||||
Filter getSpringSecurityFilterChain() { |
||||
context.getBean("springSecurityFilterChain",Filter.class) |
||||
} |
||||
|
||||
def getResponseHeaders() { |
||||
def headers = [:] |
||||
response.headerNames.each { name -> |
||||
headers.put(name, response.getHeaderValues(name).join(',')) |
||||
} |
||||
return headers |
||||
} |
||||
|
||||
AuthenticationManager authenticationManager() { |
||||
context.getBean(AuthenticationManager) |
||||
} |
||||
|
||||
AuthenticationManager getAuthenticationManager() { |
||||
try { |
||||
authenticationManager().delegateBuilder.getObject() |
||||
} catch(NoSuchBeanDefinitionException e) { |
||||
} catch(MissingPropertyException e) {} |
||||
findFilter(FilterSecurityInterceptor).authenticationManager |
||||
} |
||||
|
||||
List<AuthenticationProvider> authenticationProviders() { |
||||
List<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>() |
||||
AuthenticationManager authenticationManager = getAuthenticationManager() |
||||
while(authenticationManager?.providers) { |
||||
providers.addAll(authenticationManager.providers) |
||||
authenticationManager = authenticationManager.parent |
||||
} |
||||
providers |
||||
} |
||||
|
||||
AuthenticationProvider findAuthenticationProvider(Class<?> provider) { |
||||
authenticationProviders().find { provider.isAssignableFrom(it.class) } |
||||
} |
||||
|
||||
def getCurrentAuthentication() { |
||||
new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response)).authentication |
||||
} |
||||
|
||||
def login(String username="user", String role="ROLE_USER") { |
||||
login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))) |
||||
} |
||||
|
||||
def login(Authentication auth) { |
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository() |
||||
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response) |
||||
repo.loadContext(requestResponseHolder) |
||||
repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response) |
||||
} |
||||
|
||||
def createAuthenticationManagerBuilder() { |
||||
oppContext = new AnnotationConfigApplicationContext(ObjectPostProcessorConfiguration, AuthenticationConfiguration) |
||||
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor) |
||||
auth.inMemoryAuthentication().and() |
||||
} |
||||
|
||||
def getObjectPostProcessor() { |
||||
oppContext.getBean(ObjectPostProcessor) |
||||
} |
||||
} |
||||
@ -1,82 +0,0 @@
@@ -1,82 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2012 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
*/ |
||||
package org.springframework.security.config.http |
||||
|
||||
import javax.servlet.Filter |
||||
import org.springframework.mock.web.MockFilterChain |
||||
import org.springframework.mock.web.MockHttpServletRequest |
||||
import org.springframework.mock.web.MockHttpServletResponse |
||||
import org.springframework.security.config.AbstractXmlConfigTests |
||||
import org.springframework.security.config.BeanIds |
||||
import org.springframework.security.web.FilterInvocation |
||||
|
||||
import javax.servlet.http.HttpServletRequest |
||||
|
||||
/** |
||||
* |
||||
* @author Rob Winch |
||||
* |
||||
*/ |
||||
abstract class AbstractHttpConfigTests extends AbstractXmlConfigTests { |
||||
final int AUTO_CONFIG_FILTERS = 15; |
||||
|
||||
def httpAutoConfig(Closure c) { |
||||
xml.http(['auto-config': 'true', 'use-expressions':false], c) |
||||
} |
||||
|
||||
def httpAutoConfig(String matcher, Closure c) { |
||||
xml.http(['auto-config': 'true', 'use-expressions':false, 'request-matcher': matcher], c) |
||||
} |
||||
|
||||
def interceptUrl(String path, String authz) { |
||||
xml.'intercept-url'(pattern: path, access: authz) |
||||
} |
||||
|
||||
def interceptUrl(String path, String httpMethod, String authz) { |
||||
xml.'intercept-url'(pattern: path, method: httpMethod, access: authz) |
||||
} |
||||
|
||||
Filter getFilter(Class type) { |
||||
List filters = getFilters("/any"); |
||||
|
||||
for (f in filters) { |
||||
if (f.class.isAssignableFrom(type)) { |
||||
return f; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
List getFilters(String url) { |
||||
springSecurityFilterChain.getFilters(url) |
||||
} |
||||
|
||||
Filter getSpringSecurityFilterChain() { |
||||
appContext.getBean(BeanIds.FILTER_CHAIN_PROXY) |
||||
} |
||||
|
||||
FilterInvocation createFilterinvocation(String path, String method) { |
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); |
||||
request.setMethod(method); |
||||
request.setRequestURI(null); |
||||
request.setServletPath(path); |
||||
|
||||
return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain()); |
||||
} |
||||
|
||||
def basicLogin(HttpServletRequest request, String username="user",String password="password") { |
||||
def credentials = username + ":" + password |
||||
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64()) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue