1
0
mirror of synced 2026-05-22 21:33:16 +00:00

SEC-2915: More Tabs -> Spaces

This commit is contained in:
Rob Winch
2015-04-17 11:34:34 -05:00
parent 5fa5630bc3
commit 4fdfb8caba
154 changed files with 9917 additions and 9917 deletions
@@ -9,94 +9,94 @@
-->
<beans>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<constructor-arg>
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</property>
<property name="cacheName" value="aclCache"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
</constructor-arg>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_USER"/>
</bean>
</list>
</constructor-arg>
</bean>
</constructor-arg>
<bean id="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<constructor-arg>
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</property>
<property name="cacheName" value="aclCache"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
</constructor-arg>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_USER"/>
</bean>
</list>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</bean>
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
</constructor-arg>
</bean>
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
</constructor-arg>
</bean>
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMINISTRATOR"/>
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMINISTRATOR"/>
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMINISTRATOR"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMINISTRATOR"/>
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMINISTRATOR"/>
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="ROLE_ADMINISTRATOR"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="lookupStrategy"/>
<constructor-arg ref="aclCache"/>
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="lookupStrategy"/>
<constructor-arg ref="aclCache"/>
<!-- Uncomment to use PostgreSQL
<property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))"/>
<property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))"/>
<property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))"/>
<property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))"/>
-->
</bean>
</bean>
<!-- PostgreSQL DataSource configuration
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/acltest"/>
<property name="username" value="acltest"/>
<property name="password" value="acltest"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/acltest"/>
<property name="username" value="acltest"/>
<property name="password" value="acltest"/>
</bean>
-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:acltest"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:acltest"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="serviceProperties2"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example2.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="serviceProperties2"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example2.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
<constructor-arg ref="serviceProperties"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
<constructor-arg ref="serviceProperties"/>
</bean>
</beans>
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
</beans>
@@ -47,174 +47,174 @@ import org.springframework.test.util.ReflectionTestUtils;
*
*/
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_"
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")
}
}
@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"
}
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")
}
}
@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"
}
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");
}
}
@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_"
}
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_")
}
}
@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"]
}
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");
}
}
@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"]
}
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");
}
}
@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]
}
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
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 {
@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 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()
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) {
configure(auth)
auth.build()
}
abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception
}
abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception
}
static Integer port;
static Integer port;
static int getPort() {
if(port == null) {
ServerSocket socket = new ServerSocket(0)
port = socket.localPort
socket.close()
}
port
}
static int getPort() {
if(port == null) {
ServerSocket socket = new ServerSocket(0)
port = socket.localPort
socket.close()
}
port
}
}
@@ -37,24 +37,24 @@ import static org.springframework.security.config.annotation.authentication.ldap
*/
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 default ldap contexts (ports dynamically allocated)"() {
when:
loadConfig(MultiLdapAuthenticationProvidersConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
}
@EnableWebSecurity
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.groupSearchBase("ou=groups")
.userDnPatterns("uid={0},ou=people")
.and()
.ldapAuthentication()
.groupSearchBase("ou=groups")
.userDnPatterns("uid={0},ou=people")
}
}
@EnableWebSecurity
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.groupSearchBase("ou=groups")
.userDnPatterns("uid={0},ou=people")
.and()
.ldapAuthentication()
.groupSearchBase("ou=groups")
.userDnPatterns("uid={0},ou=people")
}
}
}
@@ -36,45 +36,45 @@ import org.springframework.test.util.ReflectionTestUtils;
*
*/
class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec {
def "ldap-authentication-provider"() {
when:
loadConfig(LdapAuthenticationProviderConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
}
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 "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 "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"))
}
def "ldap-authentication-provider password compare"() {
when:
loadConfig(PasswordCompareLdapConfig)
LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
then:
provider.authenticator instanceof PasswordComparisonAuthenticator
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
}
}
@@ -21,161 +21,161 @@ import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper
*/
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}')
}
// 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('')
createAppContext('')
def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers
def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers
expect:
expect:
providers.size() == 2
providers[0].authoritiesPopulator.groupSearchFilter == "member={0}"
providers[1].authoritiesPopulator.groupSearchFilter == "uniqueMember={0}"
}
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}')
}
def simpleProviderAuthenticatesCorrectly() {
xml.'ldap-server'(ldif:'test-server.ldif')
xml.'authentication-manager'{
'ldap-authentication-provider'('group-search-filter':'member={0}')
}
createAppContext('')
createAppContext('')
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
def ben = auth.principal;
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
def ben = auth.principal;
then:
ben.authorities.size() == 3
}
then:
ben.authorities.size() == 3
}
def missingServerEltCausesConfigException() {
xml.'authentication-manager'{
'ldap-authentication-provider'()
}
def missingServerEltCausesConfigException() {
xml.'authentication-manager'{
'ldap-authentication-provider'()
}
when:
createAppContext('')
when:
createAppContext('')
then:
thrown(ApplicationContextException)
}
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)
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"))
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
then:
auth != null
notThrown(AuthenticationException)
}
then:
auth != null
notThrown(AuthenticationException)
}
def supportsPasswordComparisonAuthenticationWithHashAttribute() {
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', hash: 'plaintext')
}
}
createAppContext('')
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
def supportsPasswordComparisonAuthenticationWithHashAttribute() {
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', hash: 'plaintext')
}
}
createAppContext('')
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
then:
auth != null
notThrown(AuthenticationException)
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'(hash: 'plaintext')
}
}
}
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'(hash: 'plaintext')
}
}
}
createAppContext('')
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
createAppContext('')
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
then:
auth != null
notThrown(AuthenticationException)
}
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)
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)
createAppContext('')
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password'))
when:
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password'))
then:
auth != null
}
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('')
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
}
expect:
appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0].userDetailsContextMapper instanceof InetOrgPersonContextMapper
}
def ldapAuthenticationProviderWorksWithPlaceholders() {
System.setProperty('udp','people')
System.setProperty('gsf','member')
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)
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]
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")
}
expect:
[new MessageFormat("uid={0},ou=people")] == FieldUtils.getFieldValue(provider,"authenticator.userDnFormat")
"member={0}" == FieldUtils.getFieldValue(provider, "authoritiesPopulator.groupSearchFilter")
}
}
@@ -44,127 +44,127 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
*
*/
class AuthenticationManagerBuilderTests extends BaseSpringSpec {
def "add(AuthenticationProvider) does not perform registration"() {
setup:
ObjectPostProcessor opp = Mock()
AuthenticationProvider provider = Mock()
AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(objectPostProcessor).objectPostProcessor(opp)
when: "Adding an AuthenticationProvider"
builder.authenticationProvider(provider)
builder.build()
then: "AuthenticationProvider is not passed into LifecycleManager (it should be managed externally)"
0 * opp._(_ as AuthenticationProvider)
}
def "add(AuthenticationProvider) does not perform registration"() {
setup:
ObjectPostProcessor opp = Mock()
AuthenticationProvider provider = Mock()
AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(objectPostProcessor).objectPostProcessor(opp)
when: "Adding an AuthenticationProvider"
builder.authenticationProvider(provider)
builder.build()
then: "AuthenticationProvider is not passed into LifecycleManager (it should be managed externally)"
0 * opp._(_ as AuthenticationProvider)
}
// https://github.com/SpringSource/spring-security-javaconfig/issues/132
def "#132 Custom AuthenticationEventPublisher with Web configure(AuthenticationManagerBuilder)"() {
setup:
AuthenticationEventPublisher aep = Mock()
when:
AuthenticationManager am = new AuthenticationManagerBuilder(objectPostProcessor)
.authenticationEventPublisher(aep)
.inMemoryAuthentication()
.and()
.build()
then:
am.eventPublisher == aep
}
// https://github.com/SpringSource/spring-security-javaconfig/issues/132
def "#132 Custom AuthenticationEventPublisher with Web configure(AuthenticationManagerBuilder)"() {
setup:
AuthenticationEventPublisher aep = Mock()
when:
AuthenticationManager am = new AuthenticationManagerBuilder(objectPostProcessor)
.authenticationEventPublisher(aep)
.inMemoryAuthentication()
.and()
.build()
then:
am.eventPublisher == aep
}
def "authentication-manager support multiple DaoAuthenticationProvider's"() {
setup:
loadConfig(MultiAuthenticationProvidersConfig)
when:
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.name == "user"
auth.authorities*.authority == ['ROLE_USER']
when:
auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("admin","password"))
then:
auth.name == "admin"
auth.authorities*.authority.sort() == ['ROLE_ADMIN','ROLE_USER']
}
def "authentication-manager support multiple DaoAuthenticationProvider's"() {
setup:
loadConfig(MultiAuthenticationProvidersConfig)
when:
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.name == "user"
auth.authorities*.authority == ['ROLE_USER']
when:
auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("admin","password"))
then:
auth.name == "admin"
auth.authorities*.authority.sort() == ['ROLE_ADMIN','ROLE_USER']
}
@EnableWebSecurity
static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.and()
.inMemoryAuthentication()
.withUser("admin").password("password").roles("USER","ADMIN")
}
}
@EnableWebSecurity
static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.and()
.inMemoryAuthentication()
.withUser("admin").password("password").roles("USER","ADMIN")
}
}
def "isConfigured with AuthenticationProvider"() {
setup:
ObjectPostProcessor opp = Mock()
AuthenticationProvider provider = Mock()
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
when:
auth
.authenticationProvider(provider)
then:
auth.isConfigured()
}
def "isConfigured with AuthenticationProvider"() {
setup:
ObjectPostProcessor opp = Mock()
AuthenticationProvider provider = Mock()
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
when:
auth
.authenticationProvider(provider)
then:
auth.isConfigured()
}
def "isConfigured with parent"() {
setup:
ObjectPostProcessor opp = Mock()
AuthenticationManager parent = Mock()
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
when:
auth
.parentAuthenticationManager(parent)
then:
auth.isConfigured()
}
def "isConfigured with parent"() {
setup:
ObjectPostProcessor opp = Mock()
AuthenticationManager parent = Mock()
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
when:
auth
.parentAuthenticationManager(parent)
then:
auth.isConfigured()
}
def "isConfigured not configured"() {
setup:
ObjectPostProcessor opp = Mock()
when:
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
then:
auth.isConfigured() == false
}
def "isConfigured not configured"() {
setup:
ObjectPostProcessor opp = Mock()
when:
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
then:
auth.isConfigured() == false
}
def "user from properties"() {
setup:
loadConfig(UserFromPropertiesConfig)
AuthenticationManager manager = context.getBean(AuthenticationConfiguration).authenticationManager
when:
manager.authenticate(new UsernamePasswordAuthenticationToken("joe","joespassword"))
then:
noExceptionThrown()
}
def "user from properties"() {
setup:
loadConfig(UserFromPropertiesConfig)
AuthenticationManager manager = context.getBean(AuthenticationConfiguration).authenticationManager
when:
manager.authenticate(new UsernamePasswordAuthenticationToken("joe","joespassword"))
then:
noExceptionThrown()
}
@Configuration
@EnableGlobalAuthentication
@Import(ObjectPostProcessorConfiguration.class)
static class UserFromPropertiesConfig {
@Configuration
@EnableGlobalAuthentication
@Import(ObjectPostProcessorConfiguration.class)
static class UserFromPropertiesConfig {
@Value("classpath:org/springframework/security/config/users.properties")
Resource users;
@Value("classpath:org/springframework/security/config/users.properties")
Resource users;
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(authenticationProvider()));
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(authenticationProvider()));
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService())
return provider;
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService())
return provider;
}
@Bean
public UserDetailsService userDetailsService() {
Properties properties = new Properties();
properties.load(users.getInputStream());
return new InMemoryUserDetailsManager(properties);
}
}
@Bean
public UserDetailsService userDetailsService() {
Properties properties = new Properties();
properties.load(users.getInputStream());
return new InMemoryUserDetailsManager(properties);
}
}
}
@@ -34,11 +34,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
*/
@Configuration
class BaseAuthenticationConfig {
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN").and()
}
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN").and()
}
}
@@ -32,80 +32,80 @@ import org.springframework.security.core.Authentication
*
*/
class NamespaceAuthenticationManagerTests extends BaseSpringSpec {
def "authentication-manager@erase-credentials=true (default)"() {
when:
loadConfig(EraseCredentialsTrueDefaultConfig)
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.principal.password == null
auth.credentials == null
when: "authenticate the same user"
auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then: "successfully authenticate again"
noExceptionThrown()
}
def "authentication-manager@erase-credentials=true (default)"() {
when:
loadConfig(EraseCredentialsTrueDefaultConfig)
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.principal.password == null
auth.credentials == null
when: "authenticate the same user"
auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then: "successfully authenticate again"
noExceptionThrown()
}
@EnableWebSecurity
static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@EnableWebSecurity
static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
def "authentication-manager@erase-credentials=false"() {
when:
loadConfig(EraseCredentialsFalseConfig)
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.credentials == "password"
auth.principal.password == "password"
}
def "authentication-manager@erase-credentials=false"() {
when:
loadConfig(EraseCredentialsFalseConfig)
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.credentials == "password"
auth.principal.password == "password"
}
@EnableWebSecurity
static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.eraseCredentials(false)
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@EnableWebSecurity
static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.eraseCredentials(false)
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
def "SEC-2533: global authentication-manager@erase-credentials=false"() {
when:
loadConfig(GlobalEraseCredentialsFalseConfig)
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.credentials == "password"
auth.principal.password == "password"
}
def "SEC-2533: global authentication-manager@erase-credentials=false"() {
when:
loadConfig(GlobalEraseCredentialsFalseConfig)
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
auth.credentials == "password"
auth.principal.password == "password"
}
@EnableWebSecurity
static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.eraseCredentials(false)
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@EnableWebSecurity
static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.eraseCredentials(false)
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
}
@@ -31,51 +31,51 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
*
*/
class NamespaceAuthenticationProviderTests extends BaseSpringSpec {
def "authentication-provider@ref"() {
when:
loadConfig(AuthenticationProviderRefConfig)
then:
authenticationProviders()[1] == AuthenticationProviderRefConfig.expected
}
def "authentication-provider@ref"() {
when:
loadConfig(AuthenticationProviderRefConfig)
then:
authenticationProviders()[1] == AuthenticationProviderRefConfig.expected
}
@EnableWebSecurity
static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter {
static DaoAuthenticationProvider expected = new DaoAuthenticationProvider()
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(expected)
}
@EnableWebSecurity
static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter {
static DaoAuthenticationProvider expected = new DaoAuthenticationProvider()
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(expected)
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
def "authentication-provider@user-service-ref"() {
when:
loadConfig(UserServiceRefConfig)
then:
findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService == UserServiceRefConfig.expected
}
def "authentication-provider@user-service-ref"() {
when:
loadConfig(UserServiceRefConfig)
then:
findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService == UserServiceRefConfig.expected
}
@EnableWebSecurity
static class UserServiceRefConfig extends WebSecurityConfigurerAdapter {
static InMemoryUserDetailsManager expected = new InMemoryUserDetailsManager([] as Collection)
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(expected)
}
@EnableWebSecurity
static class UserServiceRefConfig extends WebSecurityConfigurerAdapter {
static InMemoryUserDetailsManager expected = new InMemoryUserDetailsManager([] as Collection)
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(expected)
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
}
@@ -41,145 +41,145 @@ import org.springframework.security.provisioning.JdbcUserDetailsManager
*
*/
class NamespaceJdbcUserServiceTests extends BaseSpringSpec {
def "jdbc-user-service"() {
when:
loadConfig(DataSourceConfig,JdbcUserServiceConfig)
then:
findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService instanceof JdbcUserDetailsManager
}
def "jdbc-user-service"() {
when:
loadConfig(DataSourceConfig,JdbcUserServiceConfig)
then:
findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService instanceof JdbcUserDetailsManager
}
@EnableWebSecurity
static class JdbcUserServiceConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@EnableWebSecurity
static class JdbcUserServiceConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource) // jdbc-user-service@data-source-ref
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource) // jdbc-user-service@data-source-ref
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
def "jdbc-user-service in memory testing sample"() {
when:
loadConfig(DataSourceConfig,JdbcUserServiceInMemorySampleConfig)
then:
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
auth.authorities.collect {it.authority} == ['ROLE_USER']
auth.name == "user"
}
def "jdbc-user-service in memory testing sample"() {
when:
loadConfig(DataSourceConfig,JdbcUserServiceInMemorySampleConfig)
then:
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
auth.authorities.collect {it.authority} == ['ROLE_USER']
auth.name == "user"
}
@EnableWebSecurity
static class JdbcUserServiceInMemorySampleConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@EnableWebSecurity
static class JdbcUserServiceInMemorySampleConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
// imports the default schema (will fail if already exists)
.withDefaultSchema()
// adds this user automatically (will fail if already exists)
.withUser("user")
.password("password")
.roles("USER")
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
// imports the default schema (will fail if already exists)
.withDefaultSchema()
// adds this user automatically (will fail if already exists)
.withUser("user")
.password("password")
.roles("USER")
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
@Configuration
static class DataSourceConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
@Configuration
static class DataSourceConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
def "jdbc-user-service custom"() {
when:
loadConfig(CustomDataSourceConfig,CustomJdbcUserServiceSampleConfig)
then:
findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService.userCache instanceof CustomUserCache
when:
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
then:
auth.authorities.collect {it.authority}.sort() == ['ROLE_DBA','ROLE_USER']
auth.name == 'user'
}
def "jdbc-user-service custom"() {
when:
loadConfig(CustomDataSourceConfig,CustomJdbcUserServiceSampleConfig)
then:
findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService.userCache instanceof CustomUserCache
when:
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
then:
auth.authorities.collect {it.authority}.sort() == ['ROLE_DBA','ROLE_USER']
auth.name == 'user'
}
@EnableWebSecurity
static class CustomJdbcUserServiceSampleConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@EnableWebSecurity
static class CustomJdbcUserServiceSampleConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
// jdbc-user-service@dataSource
.dataSource(dataSource)
// jdbc-user-service@cache-ref
.userCache(new CustomUserCache())
// jdbc-user-service@users-byusername-query
.usersByUsernameQuery("select principal,credentials,true from users where principal = ?")
// jdbc-user-service@authorities-by-username-query
.authoritiesByUsernameQuery("select principal,role from roles where principal = ?")
// jdbc-user-service@group-authorities-by-username-query
.groupAuthoritiesByUsername(JdbcUserDetailsManager.DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY)
// jdbc-user-service@role-prefix
.rolePrefix("ROLE_")
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
// jdbc-user-service@dataSource
.dataSource(dataSource)
// jdbc-user-service@cache-ref
.userCache(new CustomUserCache())
// jdbc-user-service@users-byusername-query
.usersByUsernameQuery("select principal,credentials,true from users where principal = ?")
// jdbc-user-service@authorities-by-username-query
.authoritiesByUsernameQuery("select principal,role from roles where principal = ?")
// jdbc-user-service@group-authorities-by-username-query
.groupAuthoritiesByUsername(JdbcUserDetailsManager.DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY)
// jdbc-user-service@role-prefix
.rolePrefix("ROLE_")
}
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
// Only necessary to have access to verify the AuthenticationManager
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
static class CustomUserCache implements UserCache {
static class CustomUserCache implements UserCache {
@Override
public UserDetails getUserFromCache(String username) {
return null;
}
@Override
public UserDetails getUserFromCache(String username) {
return null;
}
@Override
public void putUserInCache(UserDetails user) {
}
@Override
public void putUserInCache(UserDetails user) {
}
@Override
public void removeUserFromCache(String username) {
}
}
}
@Override
public void removeUserFromCache(String username) {
}
}
}
@Configuration
static class CustomDataSourceConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
// simulate that the DB already has the schema loaded and users in it
.addScript("CustomJdbcUserServiceSampleConfig.sql")
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
@Configuration
static class CustomDataSourceConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
// simulate that the DB already has the schema loaded and users in it
.addScript("CustomJdbcUserServiceSampleConfig.sql")
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
}
@@ -43,78 +43,78 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
*
*/
class NamespacePasswordEncoderTests extends BaseSpringSpec {
def "password-encoder@ref with in memory"() {
when:
loadConfig(PasswordEncoderWithInMemoryConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
def "password-encoder@ref with in memory"() {
when:
loadConfig(PasswordEncoderWithInMemoryConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
@EnableWebSecurity
static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
@EnableWebSecurity
static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
auth
.inMemoryAuthentication()
.withUser("user").password(encoder.encode("password")).roles("USER").and()
.passwordEncoder(encoder)
}
}
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
auth
.inMemoryAuthentication()
.withUser("user").password(encoder.encode("password")).roles("USER").and()
.passwordEncoder(encoder)
}
}
def "password-encoder@ref with jdbc"() {
when:
loadConfig(PasswordEncoderWithJdbcConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
def "password-encoder@ref with jdbc"() {
when:
loadConfig(PasswordEncoderWithJdbcConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
@EnableWebSecurity
static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
@EnableWebSecurity
static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
auth
.jdbcAuthentication()
.withDefaultSchema()
.dataSource(dataSource())
.withUser("user").password(encoder.encode("password")).roles("USER").and()
.passwordEncoder(encoder)
}
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
auth
.jdbcAuthentication()
.withDefaultSchema()
.dataSource(dataSource())
.withUser("user").password(encoder.encode("password")).roles("USER").and()
.passwordEncoder(encoder)
}
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
def "password-encoder@ref with userdetailsservice"() {
when:
loadConfig(PasswordEncoderWithUserDetailsServiceConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
def "password-encoder@ref with userdetailsservice"() {
when:
loadConfig(PasswordEncoderWithUserDetailsServiceConfig)
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
@EnableWebSecurity
static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
@EnableWebSecurity
static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
User user = new User("user",encoder.encode("password"), AuthorityUtils.createAuthorityList("ROLE_USER"))
InMemoryUserDetailsManager uds = new InMemoryUserDetailsManager([user])
auth
.userDetailsService(uds)
.passwordEncoder(encoder)
}
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
User user = new User("user",encoder.encode("password"), AuthorityUtils.createAuthorityList("ROLE_USER"))
InMemoryUserDetailsManager uds = new InMemoryUserDetailsManager([user])
auth
.userDetailsService(uds)
.passwordEncoder(encoder)
}
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
}
}
@@ -44,18 +44,18 @@ import org.springframework.test.util.ReflectionTestUtils;
*
*/
class PasswordEncoderConfigurerTests extends BaseSpringSpec {
def "password-encoder@ref with No AuthenticationManager Bean"() {
when:
loadConfig(PasswordEncoderNoAuthManagerLoadsConfig)
then:
noExceptionThrown()
}
def "password-encoder@ref with No AuthenticationManager Bean"() {
when:
loadConfig(PasswordEncoderNoAuthManagerLoadsConfig)
then:
noExceptionThrown()
}
def "password-encoder@ref with AuthenticationManagerBuilder"() {
when:
loadConfig(PasswordEncoderConfig)
AuthenticationManager authMgr = authenticationManager()
then:
authMgr.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
def "password-encoder@ref with AuthenticationManagerBuilder"() {
when:
loadConfig(PasswordEncoderConfig)
AuthenticationManager authMgr = authenticationManager()
then:
authMgr.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
}
}
@@ -50,320 +50,320 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
class AuthenticationConfigurationTests extends BaseSpringSpec {
def "Ordering Autowired on EnableGlobalMethodSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityAutowiredConfigAndServicesConfig)
then:
context.getBean(Service).run()
}
def "Ordering Autowired on EnableGlobalMethodSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityAutowiredConfigAndServicesConfig)
then:
context.getBean(Service).run()
}
@Configuration
@Import([GlobalMethodSecurityAutowiredConfig,ServicesConfig])
static class GlobalMethodSecurityAutowiredConfigAndServicesConfig {}
@Configuration
@Import([GlobalMethodSecurityAutowiredConfig,ServicesConfig])
static class GlobalMethodSecurityAutowiredConfigAndServicesConfig {}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityAutowiredConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityAutowiredConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
def "Ordering Autowired on EnableWebSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityConfigAndServicesConfig)
then:
context.getBean(Service).run()
}
def "Ordering Autowired on EnableWebSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityConfigAndServicesConfig)
then:
context.getBean(Service).run()
}
@Configuration
@Import([GlobalMethodSecurityConfig,WebSecurityConfig,ServicesConfig])
static class GlobalMethodSecurityConfigAndServicesConfig {}
@Configuration
@Import([GlobalMethodSecurityConfig,WebSecurityConfig,ServicesConfig])
static class GlobalMethodSecurityConfigAndServicesConfig {}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityConfig {}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityConfig {}
@EnableWebSecurity
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
@EnableWebSecurity
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
//
//
def "Ordering Autowired on EnableWebMvcSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityMvcSecurityAndServicesConfig)
then:
context.getBean(Service).run()
}
def "Ordering Autowired on EnableWebMvcSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityMvcSecurityAndServicesConfig)
then:
context.getBean(Service).run()
}
@Configuration
@Import([GlobalMethodSecurityConfig,WebMvcSecurityConfig,ServicesConfig])
static class GlobalMethodSecurityMvcSecurityAndServicesConfig {}
@Configuration
@Import([GlobalMethodSecurityConfig,WebMvcSecurityConfig,ServicesConfig])
static class GlobalMethodSecurityMvcSecurityAndServicesConfig {}
@EnableWebSecurity
static class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
@EnableWebSecurity
static class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
//
//
def "no authentication getAuthenticationManager falls back to null"() {
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
then:
context.getBean(AuthenticationConfiguration).authenticationManager == null
}
def "no authentication getAuthenticationManager falls back to null"() {
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
then:
context.getBean(AuthenticationConfiguration).authenticationManager == null
}
def "QuiesentGlobalAuthenticationConfiguererAdapter falls back to null"() {
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,QuiesentGlobalAuthenticationConfiguererAdapter)
then:
context.getBean(AuthenticationConfiguration).authenticationManager == null
}
def "QuiesentGlobalAuthenticationConfiguererAdapter falls back to null"() {
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,QuiesentGlobalAuthenticationConfiguererAdapter)
then:
context.getBean(AuthenticationConfiguration).authenticationManager == null
}
@Configuration
static class QuiesentGlobalAuthenticationConfiguererAdapter extends GlobalAuthenticationConfigurerAdapter {}
@Configuration
static class QuiesentGlobalAuthenticationConfiguererAdapter extends GlobalAuthenticationConfigurerAdapter {}
//
//
def "GlobalAuthenticationConfiguererAdapterImpl configures authentication successfully"() {
setup:
def token = new UsernamePasswordAuthenticationToken("user", "password")
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,GlobalAuthenticationConfiguererAdapterImpl)
then:
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token)?.name == "user"
}
def "GlobalAuthenticationConfiguererAdapterImpl configures authentication successfully"() {
setup:
def token = new UsernamePasswordAuthenticationToken("user", "password")
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,GlobalAuthenticationConfiguererAdapterImpl)
then:
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token)?.name == "user"
}
@Configuration
static class GlobalAuthenticationConfiguererAdapterImpl extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
@Configuration
static class GlobalAuthenticationConfiguererAdapterImpl extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
}
}
//
//
def "AuthenticationManagerBean configures authentication successfully"() {
setup:
def token = new UsernamePasswordAuthenticationToken("user", "password")
def auth = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
AuthenticationManagerBeanConfig.AM = Mock(AuthenticationManager)
1 * AuthenticationManagerBeanConfig.AM.authenticate(token) >> auth
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,AuthenticationManagerBeanConfig)
then:
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token).name == auth.name
}
def "AuthenticationManagerBean configures authentication successfully"() {
setup:
def token = new UsernamePasswordAuthenticationToken("user", "password")
def auth = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
AuthenticationManagerBeanConfig.AM = Mock(AuthenticationManager)
1 * AuthenticationManagerBeanConfig.AM.authenticate(token) >> auth
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,AuthenticationManagerBeanConfig)
then:
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token).name == auth.name
}
@Configuration
static class AuthenticationManagerBeanConfig {
static AuthenticationManager AM
@Bean
public AuthenticationManager authenticationManager() {
AM
}
}
@Configuration
static class AuthenticationManagerBeanConfig {
static AuthenticationManager AM
@Bean
public AuthenticationManager authenticationManager() {
AM
}
}
//
//
@Configuration
static class ServicesConfig {
@Bean
public Service service() {
return new ServiceImpl()
}
}
@Configuration
static class ServicesConfig {
@Bean
public Service service() {
return new ServiceImpl()
}
}
static interface Service {
public void run();
}
static interface Service {
public void run();
}
static class ServiceImpl implements Service {
@Secured("ROLE_USER")
public void run() {}
}
static class ServiceImpl implements Service {
@Secured("ROLE_USER")
public void run() {}
}
//
//
def "GlobalAuthenticationConfigurerAdapter are ordered"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()])
when:
config.getAuthenticationManager()
then:
DefaultOrderGlobalAuthenticationConfigurerAdapter.inits == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
DefaultOrderGlobalAuthenticationConfigurerAdapter.configs == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
def "GlobalAuthenticationConfigurerAdapter are ordered"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()])
when:
config.getAuthenticationManager()
then:
DefaultOrderGlobalAuthenticationConfigurerAdapter.inits == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
DefaultOrderGlobalAuthenticationConfigurerAdapter.configs == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
}
}
static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
static List inits = []
static List configs = []
static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
static List inits = []
static List configs = []
public void init(AuthenticationManagerBuilder auth) throws Exception {
inits.add(getClass())
}
public void init(AuthenticationManagerBuilder auth) throws Exception {
inits.add(getClass())
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
configs.add(getClass())
}
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
configs.add(getClass())
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
@Order(Ordered.LOWEST_PRECEDENCE)
static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
@Order(Ordered.HIGHEST_PRECEDENCE)
static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
@Order(Ordered.HIGHEST_PRECEDENCE)
static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
//
//
def "Spring Boot not triggered when already configured"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()])
AuthenticationManager authenticationManager = config.authenticationManager
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
noExceptionThrown()
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
then:
thrown(AuthenticationException)
}
def "Spring Boot not triggered when already configured"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()])
AuthenticationManager authenticationManager = config.authenticationManager
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
noExceptionThrown()
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
then:
thrown(AuthenticationException)
}
def "Spring Boot is triggered when not already configured"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new BootGlobalAuthenticationConfigurerAdapter()])
AuthenticationManager authenticationManager = config.authenticationManager
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
then:
noExceptionThrown()
}
def "Spring Boot is triggered when not already configured"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new BootGlobalAuthenticationConfigurerAdapter()])
AuthenticationManager authenticationManager = config.authenticationManager
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
then:
noExceptionThrown()
}
static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter())
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter())
}
}
static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if(auth.isConfigured()) {
return;
}
static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if(auth.isConfigured()) {
return;
}
User user = new User("boot","password", AuthorityUtils.createAuthorityList("ROLE_USER"))
User user = new User("boot","password", AuthorityUtils.createAuthorityList("ROLE_USER"))
List<User> users = Arrays.asList(user);
InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
List<User> users = Arrays.asList(user);
InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
provider.userDetailsService = inMemory
DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
provider.userDetailsService = inMemory
auth.authenticationProvider(provider)
}
}
auth.authenticationProvider(provider)
}
}
def "SEC-2531: AuthenticationConfiguration#lazyBean should use BeanClassLoader on ProxyFactoryBean"() {
setup:
ObjectPostProcessor opp = Mock()
Sec2531Config. opp = opp
loadConfig(Sec2531Config)
when:
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.getAuthenticationManager()
then:
1 * opp.postProcess(_ as ProxyFactoryBean) >> { args ->
args[0]
}
}
def "SEC-2531: AuthenticationConfiguration#lazyBean should use BeanClassLoader on ProxyFactoryBean"() {
setup:
ObjectPostProcessor opp = Mock()
Sec2531Config. opp = opp
loadConfig(Sec2531Config)
when:
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.getAuthenticationManager()
then:
1 * opp.postProcess(_ as ProxyFactoryBean) >> { args ->
args[0]
}
}
@Configuration
@Import(AuthenticationConfiguration)
static class Sec2531Config {
static ObjectPostProcessor opp
@Configuration
@Import(AuthenticationConfiguration)
static class Sec2531Config {
static ObjectPostProcessor opp
@Bean
public ObjectPostProcessor objectPostProcessor() {
opp
}
@Bean
public ObjectPostProcessor objectPostProcessor() {
opp
}
@Bean
public AuthenticationManager manager() {
null
}
}
@Bean
public AuthenticationManager manager() {
null
}
}
def "SEC-2822: Cannot Force Authentication already built"() {
setup:
loadConfig(Sec2822WebSecurity,Sec2822UseAuth,Sec2822Config)
when:
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.getAuthenticationManager()
then:
noExceptionThrown()
}
def "SEC-2822: Cannot Force Authentication already built"() {
setup:
loadConfig(Sec2822WebSecurity,Sec2822UseAuth,Sec2822Config)
when:
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.getAuthenticationManager()
then:
noExceptionThrown()
}
@Configuration
@Import(AuthenticationConfiguration)
static class Sec2822Config {}
@Configuration
@Import(AuthenticationConfiguration)
static class Sec2822Config {}
@Configuration
@EnableWebSecurity
static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
}
}
@Configuration
@EnableWebSecurity
static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
}
}
@Configuration
static class Sec2822UseAuth {
@Autowired
public void useAuthenticationManager(AuthenticationConfiguration auth) {
auth.authenticationManager
}
@Configuration
static class Sec2822UseAuth {
@Autowired
public void useAuthenticationManager(AuthenticationConfiguration auth) {
auth.authenticationManager
}
// Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
// must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
@Bean
public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
new BootGlobalAuthenticationConfigurerAdapter()
}
// Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
// must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
@Bean
public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
new BootGlobalAuthenticationConfigurerAdapter()
}
static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
}
static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
}
}
@@ -42,100 +42,100 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
*/
class AutowireBeanFactoryObjectPostProcessorTests extends BaseSpringSpec {
def "Verify All Aware methods are invoked"() {
setup:
ApplicationContextAware contextAware = Mock(ApplicationContextAware)
ApplicationEventPublisherAware publisher = Mock(ApplicationEventPublisherAware)
BeanClassLoaderAware classloader = Mock(BeanClassLoaderAware)
BeanFactoryAware beanFactory = Mock(BeanFactoryAware)
EnvironmentAware environment = Mock(EnvironmentAware)
MessageSourceAware messageSource = Mock(MessageSourceAware)
ServletConfigAware servletConfig = Mock(ServletConfigAware)
ServletContextAware servletContext = Mock(ServletContextAware)
DisposableBean disposable = Mock(DisposableBean)
def "Verify All Aware methods are invoked"() {
setup:
ApplicationContextAware contextAware = Mock(ApplicationContextAware)
ApplicationEventPublisherAware publisher = Mock(ApplicationEventPublisherAware)
BeanClassLoaderAware classloader = Mock(BeanClassLoaderAware)
BeanFactoryAware beanFactory = Mock(BeanFactoryAware)
EnvironmentAware environment = Mock(EnvironmentAware)
MessageSourceAware messageSource = Mock(MessageSourceAware)
ServletConfigAware servletConfig = Mock(ServletConfigAware)
ServletContextAware servletContext = Mock(ServletContextAware)
DisposableBean disposable = Mock(DisposableBean)
context = new AnnotationConfigWebApplicationContext([servletConfig:new MockServletConfig(),servletContext:new MockServletContext()])
context.register(Config)
context.refresh()
context.start()
context = new AnnotationConfigWebApplicationContext([servletConfig:new MockServletConfig(),servletContext:new MockServletContext()])
context.register(Config)
context.refresh()
context.start()
ObjectPostProcessor opp = context.getBean(ObjectPostProcessor)
when:
opp.postProcess(contextAware)
then:
1 * contextAware.setApplicationContext(!null)
ObjectPostProcessor opp = context.getBean(ObjectPostProcessor)
when:
opp.postProcess(contextAware)
then:
1 * contextAware.setApplicationContext(!null)
when:
opp.postProcess(publisher)
then:
1 * publisher.setApplicationEventPublisher(!null)
when:
opp.postProcess(publisher)
then:
1 * publisher.setApplicationEventPublisher(!null)
when:
opp.postProcess(classloader)
then:
1 * classloader.setBeanClassLoader(!null)
when:
opp.postProcess(classloader)
then:
1 * classloader.setBeanClassLoader(!null)
when:
opp.postProcess(beanFactory)
then:
1 * beanFactory.setBeanFactory(!null)
when:
opp.postProcess(beanFactory)
then:
1 * beanFactory.setBeanFactory(!null)
when:
opp.postProcess(environment)
then:
1 * environment.setEnvironment(!null)
when:
opp.postProcess(environment)
then:
1 * environment.setEnvironment(!null)
when:
opp.postProcess(messageSource)
then:
1 * messageSource.setMessageSource(!null)
when:
opp.postProcess(messageSource)
then:
1 * messageSource.setMessageSource(!null)
when:
opp.postProcess(servletConfig)
then:
1 * servletConfig.setServletConfig(!null)
when:
opp.postProcess(servletConfig)
then:
1 * servletConfig.setServletConfig(!null)
when:
opp.postProcess(servletContext)
then:
1 * servletContext.setServletContext(!null)
when:
opp.postProcess(servletContext)
then:
1 * servletContext.setServletContext(!null)
when:
opp.postProcess(disposable)
context.close()
context = null
then:
1 * disposable.destroy()
}
when:
opp.postProcess(disposable)
context.close()
context = null
then:
1 * disposable.destroy()
}
@Configuration
static class Config {
@Bean
public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
}
}
@Configuration
static class Config {
@Bean
public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
}
}
def "SEC-2382: AutowireBeanFactoryObjectPostProcessor works with BeanNameAutoProxyCreator"() {
when:
// must load with XML for BeanPostProcessors to work
context = new ClassPathXmlApplicationContext("AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml", getClass());
then:
noExceptionThrown()
and: "make sure autoproxying was actually enabled"
context.getBean(MyAdvisedBean).doStuff() == "null"
}
def "SEC-2382: AutowireBeanFactoryObjectPostProcessor works with BeanNameAutoProxyCreator"() {
when:
// must load with XML for BeanPostProcessors to work
context = new ClassPathXmlApplicationContext("AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml", getClass());
then:
noExceptionThrown()
and: "make sure autoproxying was actually enabled"
context.getBean(MyAdvisedBean).doStuff() == "null"
}
@Configuration
static class WithBanNameAutoProxyCreatorConfig {
@Bean
public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
return new AutowireBeanFactoryObjectPostProcessor(beanFactory)
}
@Configuration
static class WithBanNameAutoProxyCreatorConfig {
@Bean
public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
return new AutowireBeanFactoryObjectPostProcessor(beanFactory)
}
@Autowired
public void configure(ObjectPostProcessor<Object> p) {
p.postProcess(new Object())
}
}
@Autowired
public void configure(ObjectPostProcessor<Object> p) {
p.postProcess(new Object())
}
}
}
@@ -53,348 +53,348 @@ import org.springframework.security.core.context.SecurityContextHolder
* @author Rob Winch
*/
public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
def "messages set when using GlobalMethodSecurityConfiguration"() {
when:
loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
then:
authenticationManager.messages.messageSource instanceof ApplicationContext
}
def "messages set when using GlobalMethodSecurityConfiguration"() {
when:
loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
then:
authenticationManager.messages.messageSource instanceof ApplicationContext
}
def "AuthenticationEventPublisher is registered GlobalMethodSecurityConfiguration"() {
when:
loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
then:
authenticationManager.eventPublisher instanceof DefaultAuthenticationEventPublisher
when:
Authentication auth = new UsernamePasswordAuthenticationToken("user",null,AuthorityUtils.createAuthorityList("ROLE_USER"))
authenticationManager.eventPublisher.publishAuthenticationSuccess(auth)
then:
InMemoryAuthWithGlobalMethodSecurityConfig.EVENT.authentication == auth
}
def "AuthenticationEventPublisher is registered GlobalMethodSecurityConfiguration"() {
when:
loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
then:
authenticationManager.eventPublisher instanceof DefaultAuthenticationEventPublisher
when:
Authentication auth = new UsernamePasswordAuthenticationToken("user",null,AuthorityUtils.createAuthorityList("ROLE_USER"))
authenticationManager.eventPublisher.publishAuthenticationSuccess(auth)
then:
InMemoryAuthWithGlobalMethodSecurityConfig.EVENT.authentication == auth
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration implements ApplicationListener<AuthenticationSuccessEvent> {
static AuthenticationSuccessEvent EVENT
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration implements ApplicationListener<AuthenticationSuccessEvent> {
static AuthenticationSuccessEvent EVENT
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent e) {
EVENT = e
}
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent e) {
EVENT = e
}
}
AuthenticationManager getAuthenticationManager() {
context.getBean(MethodInterceptor).authenticationManager
}
AuthenticationManager getAuthenticationManager() {
context.getBean(MethodInterceptor).authenticationManager
}
def "AuthenticationTrustResolver autowires"() {
setup:
CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(CustomTrustResolverConfig)
def preAdviceVoter = context.getBean(MethodInterceptor).accessDecisionManager.decisionVoters.find { it instanceof PreInvocationAuthorizationAdviceVoter}
then:
preAdviceVoter.preAdvice.expressionHandler.trustResolver == CustomTrustResolverConfig.TR
}
def "AuthenticationTrustResolver autowires"() {
setup:
CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(CustomTrustResolverConfig)
def preAdviceVoter = context.getBean(MethodInterceptor).accessDecisionManager.decisionVoters.find { it instanceof PreInvocationAuthorizationAdviceVoter}
then:
preAdviceVoter.preAdvice.expressionHandler.trustResolver == CustomTrustResolverConfig.TR
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration {
static AuthenticationTrustResolver TR
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration {
static AuthenticationTrustResolver TR
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public AuthenticationTrustResolver tr() {
return TR
}
}
@Bean
public AuthenticationTrustResolver tr() {
return TR
}
}
def "SEC-2301: DefaultWebSecurityExpressionHandler has BeanResolver set"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(ExpressionHandlerHasBeanResolverSetConfig)
def service = context.getBean(ServiceImpl)
when: "service with bean reference on PreAuthorize invoked"
service.message()
then: "properly throws AccessDeniedException"
thrown(AccessDeniedException)
when: "service with bean reference on PreAuthorize invoked"
context.getBean(CustomAuthzService).grantAccess = true
service.message()
then: "grants access too"
noExceptionThrown()
}
def "SEC-2301: DefaultWebSecurityExpressionHandler has BeanResolver set"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(ExpressionHandlerHasBeanResolverSetConfig)
def service = context.getBean(ServiceImpl)
when: "service with bean reference on PreAuthorize invoked"
service.message()
then: "properly throws AccessDeniedException"
thrown(AccessDeniedException)
when: "service with bean reference on PreAuthorize invoked"
context.getBean(CustomAuthzService).grantAccess = true
service.message()
then: "grants access too"
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
static class ExpressionHandlerHasBeanResolverSetConfig extends GlobalMethodSecurityConfiguration {
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
static class ExpressionHandlerHasBeanResolverSetConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public ServiceImpl service() {
return new ServiceImpl()
}
@Bean
public ServiceImpl service() {
return new ServiceImpl()
}
@Bean
public CustomAuthzService authz() {
return new CustomAuthzService()
}
}
@Bean
public CustomAuthzService authz() {
return new CustomAuthzService()
}
}
static class ServiceImpl {
@PreAuthorize("@authz.authorize()")
public String message() {
null
}
}
static class ServiceImpl {
@PreAuthorize("@authz.authorize()")
public String message() {
null
}
}
static class CustomAuthzService {
boolean grantAccess
static class CustomAuthzService {
boolean grantAccess
public boolean authorize() {
grantAccess
}
}
public boolean authorize() {
grantAccess
}
}
def "Method Security supports annotations on interface parameter names"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(MethodSecurityServiceConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when: "service with annotated argument"
service.postAnnotation('deny')
then: "properly throws AccessDeniedException"
thrown(AccessDeniedException)
when: "service with annotated argument"
service.postAnnotation('grant')
then: "properly throws AccessDeniedException"
noExceptionThrown()
}
def "Method Security supports annotations on interface parameter names"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(MethodSecurityServiceConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when: "service with annotated argument"
service.postAnnotation('deny')
then: "properly throws AccessDeniedException"
thrown(AccessDeniedException)
when: "service with annotated argument"
service.postAnnotation('grant')
then: "properly throws AccessDeniedException"
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class MethodSecurityServiceConfig extends GlobalMethodSecurityConfiguration {
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class MethodSecurityServiceConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "GlobalMethodSecurityConfiguration autowires PermissionEvaluator"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
PermissionEvaluator evaluator = Mock()
AutowirePermissionEvaluatorConfig.PE = evaluator
loadConfig(AutowirePermissionEvaluatorConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.hasPermission("something")
then:
1 * evaluator.hasPermission(_, "something", "read") >> true
when:
service.hasPermission("something")
then:
1 * evaluator.hasPermission(_, "something", "read") >> false
thrown(AccessDeniedException)
}
def "GlobalMethodSecurityConfiguration autowires PermissionEvaluator"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
PermissionEvaluator evaluator = Mock()
AutowirePermissionEvaluatorConfig.PE = evaluator
loadConfig(AutowirePermissionEvaluatorConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.hasPermission("something")
then:
1 * evaluator.hasPermission(_, "something", "read") >> true
when:
service.hasPermission("something")
then:
1 * evaluator.hasPermission(_, "something", "read") >> false
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
static PermissionEvaluator PE
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
static PermissionEvaluator PE
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public PermissionEvaluator pe() {
PE
}
@Bean
public PermissionEvaluator pe() {
PE
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "GlobalMethodSecurityConfiguration does not failw with multiple PermissionEvaluator"() {
when:
loadConfig(MultiPermissionEvaluatorConfig)
then:
noExceptionThrown()
}
def "GlobalMethodSecurityConfiguration does not failw with multiple PermissionEvaluator"() {
when:
loadConfig(MultiPermissionEvaluatorConfig)
then:
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
static PermissionEvaluator PE
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
static PermissionEvaluator PE
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public PermissionEvaluator pe() {
PE
}
@Bean
public PermissionEvaluator pe() {
PE
}
@Bean
public PermissionEvaluator pe2() {
PE
}
@Bean
public PermissionEvaluator pe2() {
PE
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "SEC-2425: EnableGlobalMethodSecurity works on superclass"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(ParentConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
def "SEC-2425: EnableGlobalMethodSecurity works on superclass"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(ParentConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
static class ChildConfig extends ParentConfig {}
static class ChildConfig extends ParentConfig {}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class ParentConfig {
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class ParentConfig {
@Autowired
protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Autowired
protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "SEC-2479: Support AuthenticationManager in parent"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(Sec2479ParentConfig)
def child = new AnnotationConfigApplicationContext()
child.register(Sec2479ChildConfig)
child.parent = context
child.refresh()
MethodSecurityService service = child.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
cleanup:
child?.close()
}
def "SEC-2479: Support AuthenticationManager in parent"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(Sec2479ParentConfig)
def child = new AnnotationConfigApplicationContext()
child.register(Sec2479ChildConfig)
child.parent = context
child.refresh()
MethodSecurityService service = child.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
cleanup:
child?.close()
}
@Configuration
static class Sec2479ParentConfig {
static AuthenticationManager AM
@Configuration
static class Sec2479ParentConfig {
static AuthenticationManager AM
@Bean
public AuthenticationManager am() {
AM
}
}
@Bean
public AuthenticationManager am() {
AM
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2479ChildConfig {
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2479ChildConfig {
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "SEC-2815: @EnableGlobalMethodSecurity does not trigger eager initialization of Beans in GlobalAuthenticationConfigurer"() {
setup:
Sec2815Config.dataSource = Mock(DataSource)
when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
loadConfig(Sec2815Config)
then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
context.getBean(MockBeanPostProcessor).beforeInit['dataSource']
context.getBean(MockBeanPostProcessor).afterInit['dataSource']
}
def "SEC-2815: @EnableGlobalMethodSecurity does not trigger eager initialization of Beans in GlobalAuthenticationConfigurer"() {
setup:
Sec2815Config.dataSource = Mock(DataSource)
when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
loadConfig(Sec2815Config)
then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
context.getBean(MockBeanPostProcessor).beforeInit['dataSource']
context.getBean(MockBeanPostProcessor).afterInit['dataSource']
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2815Config {
static DataSource dataSource;
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2815Config {
static DataSource dataSource;
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
@Bean
public MockBeanPostProcessor mockBeanPostProcessor() {
new MockBeanPostProcessor()
}
@Bean
public MockBeanPostProcessor mockBeanPostProcessor() {
new MockBeanPostProcessor()
}
@Bean
public DataSource dataSource() {
dataSource
}
@Bean
public DataSource dataSource() {
dataSource
}
@Configuration
static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
@Autowired
DataSource dataSource
@Configuration
static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
@Autowired
DataSource dataSource
@Override
void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
}
}
}
@Override
void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
}
}
}
static class MockBeanPostProcessor implements BeanPostProcessor {
Map<String,Object> beforeInit = new HashMap<String,Object>()
Map<String,Object> afterInit = new HashMap<String,Object>()
static class MockBeanPostProcessor implements BeanPostProcessor {
Map<String,Object> beforeInit = new HashMap<String,Object>()
Map<String,Object> afterInit = new HashMap<String,Object>()
@Override
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
beforeInit[beanName] = bean
bean
}
@Override
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
beforeInit[beanName] = bean
bean
}
@Override
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
afterInit[beanName] = bean
bean
}
}
@Override
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
afterInit[beanName] = bean
bean
}
}
}
@@ -30,33 +30,33 @@ import org.springframework.security.core.Authentication
* @author Rob Winch
*/
public interface MethodSecurityService {
@PreAuthorize("denyAll")
public String preAuthorize();
@PreAuthorize("denyAll")
public String preAuthorize();
@Secured("ROLE_ADMIN")
public String secured();
@Secured("ROLE_ADMIN")
public String secured();
@Secured("ROLE_USER")
public String securedUser();
@Secured("ROLE_USER")
public String securedUser();
@DenyAll
public String jsr250();
@DenyAll
public String jsr250();
@PermitAll
public String jsr250PermitAll();
@PermitAll
public String jsr250PermitAll();
@Secured(["ROLE_USER","RUN_AS_SUPER"])
public Authentication runAs();
@Secured(["ROLE_USER","RUN_AS_SUPER"])
public Authentication runAs();
@PreAuthorize("permitAll")
public String preAuthorizePermitAll();
@PreAuthorize("permitAll")
public String preAuthorizePermitAll();
@PreAuthorize("hasPermission(#object,'read')")
public String hasPermission(String object);
@PreAuthorize("hasPermission(#object,'read')")
public String hasPermission(String object);
@PostAuthorize("hasPermission(#object,'read')")
public String postHasPermission(String object);
@PostAuthorize("hasPermission(#object,'read')")
public String postHasPermission(String object);
@PostAuthorize("#o?.contains('grant')")
public String postAnnotation(@P("o") String object);
@PostAuthorize("#o?.contains('grant')")
public String postAnnotation(@P("o") String object);
}
@@ -25,53 +25,53 @@ import org.springframework.security.core.context.SecurityContextHolder
*/
public class MethodSecurityServiceImpl implements MethodSecurityService {
@Override
public String preAuthorize() {
return null;
}
@Override
public String preAuthorize() {
return null;
}
@Override
public String secured() {
return null;
}
@Override
public String secured() {
return null;
}
@Override
public String securedUser() {
return null;
}
@Override
public String securedUser() {
return null;
}
@Override
public String jsr250() {
return null;
}
@Override
public String jsr250() {
return null;
}
@Override
public String jsr250PermitAll() {
return null;
}
@Override
public String jsr250PermitAll() {
return null;
}
@Override
public Authentication runAs() {
return SecurityContextHolder.getContext().getAuthentication();
}
@Override
public Authentication runAs() {
return SecurityContextHolder.getContext().getAuthentication();
}
@Override
public String preAuthorizePermitAll() {
return null;
}
@Override
public String preAuthorizePermitAll() {
return null;
}
@Override
public String hasPermission(String object) {
return null;
}
@Override
public String hasPermission(String object) {
return null;
}
@Override
public String postHasPermission(String object) {
return null;
}
@Override
public String postHasPermission(String object) {
return null;
}
@Override
public String postAnnotation(String object) {
return null;
}
@Override
public String postAnnotation(String object) {
return null;
}
}
@@ -40,53 +40,53 @@ import org.springframework.security.core.context.SecurityContextHolder
* @author Rob Winch
*/
public class NamespaceGlobalMethodSecurityExpressionHandlerTests extends BaseSpringSpec {
def setup() {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
}
def setup() {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
}
def "global-method-security/expression-handler @PreAuthorize"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.hasPermission("granted")
then:
noExceptionThrown()
when:
service.hasPermission("denied")
then:
thrown(AccessDeniedException)
}
def "global-method-security/expression-handler @PreAuthorize"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.hasPermission("granted")
then:
noExceptionThrown()
when:
service.hasPermission("denied")
then:
thrown(AccessDeniedException)
}
def "global-method-security/expression-handler @PostAuthorize"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.postHasPermission("granted")
then:
noExceptionThrown()
when:
service.postHasPermission("denied")
then:
thrown(AccessDeniedException)
}
def "global-method-security/expression-handler @PostAuthorize"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.postHasPermission("granted")
then:
noExceptionThrown()
when:
service.postHasPermission("denied")
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler()
expressionHandler.permissionEvaluator = new PermissionEvaluator() {
boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
"granted" == targetDomainObject
}
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
throw new UnsupportedOperationException()
}
}
return expressionHandler
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler()
expressionHandler.permissionEvaluator = new PermissionEvaluator() {
boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
"granted" == targetDomainObject
}
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
throw new UnsupportedOperationException()
}
}
return expressionHandler
}
}
}
@@ -57,387 +57,387 @@ import org.springframework.security.core.context.SecurityContextHolder
* @author Rob Winch
*/
public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
def setup() {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
}
def setup() {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
}
// --- access-decision-manager-ref ---
// --- access-decision-manager-ref ---
def "custom AccessDecisionManager can be used"() {
setup: "Create an instance with an AccessDecisionManager that always denies access"
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
when:
service.secured()
then:
thrown(AccessDeniedException)
}
def "custom AccessDecisionManager can be used"() {
setup: "Create an instance with an AccessDecisionManager that always denies access"
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
when:
service.secured()
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
return new DenyAllAccessDecisionManager()
}
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AccessDecisionManager accessDecisionManager() {
return new DenyAllAccessDecisionManager()
}
public static class DenyAllAccessDecisionManager implements AccessDecisionManager {
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
throw new AccessDeniedException("Always Denied")
}
public boolean supports(ConfigAttribute attribute) {
return true
}
public boolean supports(Class<?> clazz) {
return true
}
}
}
public static class DenyAllAccessDecisionManager implements AccessDecisionManager {
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
throw new AccessDeniedException("Always Denied")
}
public boolean supports(ConfigAttribute attribute) {
return true
}
public boolean supports(Class<?> clazz) {
return true
}
}
}
// --- authentication-manager-ref ---
// --- authentication-manager-ref ---
def "custom AuthenticationManager can be used"() {
when:
context = new AnnotationConfigApplicationContext(CustomAuthenticationConfig)
MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
then:
thrown(UnsupportedOperationException)
}
def "custom AuthenticationManager can be used"() {
when:
context = new AnnotationConfigApplicationContext(CustomAuthenticationConfig)
MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
then:
thrown(UnsupportedOperationException)
}
@EnableGlobalMethodSecurity
public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AuthenticationManager authenticationManager() {
return new AuthenticationManager() {
Authentication authenticate(Authentication authentication) {
throw new UnsupportedOperationException()
}
}
}
}
@EnableGlobalMethodSecurity
public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AuthenticationManager authenticationManager() {
return new AuthenticationManager() {
Authentication authenticate(Authentication authentication) {
throw new UnsupportedOperationException()
}
}
}
}
// --- jsr250-annotations ---
// --- jsr250-annotations ---
def "enable jsr250"() {
when:
context = new AnnotationConfigApplicationContext(Jsr250Config)
MethodSecurityService service = context.getBean(MethodSecurityService)
then: "@Secured and @PreAuthorize are ignored"
service.secured() == null
service.preAuthorize() == null
def "enable jsr250"() {
when:
context = new AnnotationConfigApplicationContext(Jsr250Config)
MethodSecurityService service = context.getBean(MethodSecurityService)
then: "@Secured and @PreAuthorize are ignored"
service.secured() == null
service.preAuthorize() == null
when: "@DenyAll method invoked"
service.jsr250()
then: "access is denied"
thrown(AccessDeniedException)
when: "@PermitAll method invoked"
String jsr250PermitAll = service.jsr250PermitAll()
then: "access is allowed"
jsr250PermitAll == null
}
when: "@DenyAll method invoked"
service.jsr250()
then: "access is denied"
thrown(AccessDeniedException)
when: "@PermitAll method invoked"
String jsr250PermitAll = service.jsr250PermitAll()
then: "access is allowed"
jsr250PermitAll == null
}
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@Configuration
public static class Jsr250Config extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@Configuration
public static class Jsr250Config extends BaseMethodConfig {
}
// --- metadata-source-ref ---
// --- metadata-source-ref ---
def "custom MethodSecurityMetadataSource can be used with higher priority than other sources"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomMethodSecurityMetadataSourceConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
when:
service.secured()
then:
thrown(AccessDeniedException)
when:
service.jsr250()
then:
thrown(AccessDeniedException)
}
def "custom MethodSecurityMetadataSource can be used with higher priority than other sources"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomMethodSecurityMetadataSourceConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
when:
service.secured()
then:
thrown(AccessDeniedException)
when:
service.jsr250()
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity
public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
return new AbstractMethodSecurityMetadataSource() {
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
// require ROLE_NOBODY for any method on MethodSecurityService class
return MethodSecurityService.isAssignableFrom(targetClass) ? [new SecurityConfig("ROLE_NOBODY")] : []
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null
}
}
}
}
@EnableGlobalMethodSecurity
public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
return new AbstractMethodSecurityMetadataSource() {
public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
// require ROLE_NOBODY for any method on MethodSecurityService class
return MethodSecurityService.isAssignableFrom(targetClass) ? [new SecurityConfig("ROLE_NOBODY")] : []
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null
}
}
}
}
// --- mode ---
// --- mode ---
def "aspectj mode works"() {
when:
context = new AnnotationConfigApplicationContext(AspectJModeConfig)
then:
context.getBean(AnnotationSecurityAspect)
context.getBean(AspectJMethodSecurityInterceptor)
}
def "aspectj mode works"() {
when:
context = new AnnotationConfigApplicationContext(AspectJModeConfig)
then:
context.getBean(AnnotationSecurityAspect)
context.getBean(AspectJMethodSecurityInterceptor)
}
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, proxyTargetClass = true)
public static class AspectJModeConfig extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, proxyTargetClass = true)
public static class AspectJModeConfig extends BaseMethodConfig {
}
def "aspectj mode works extending GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,AspectJModeExtendsGMSCConfig)
then:
context.getBean(AnnotationSecurityAspect)
context.getBean(AspectJMethodSecurityInterceptor)
}
def "aspectj mode works extending GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,AspectJModeExtendsGMSCConfig)
then:
context.getBean(AnnotationSecurityAspect)
context.getBean(AspectJMethodSecurityInterceptor)
}
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ)
public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
}
@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ)
public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
}
// --- order ---
// --- order ---
def order() {
when:
context = new AnnotationConfigApplicationContext(CustomOrderConfig)
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
then:
advisor.order == 135
}
def order() {
when:
context = new AnnotationConfigApplicationContext(CustomOrderConfig)
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
then:
advisor.order == 135
}
@EnableGlobalMethodSecurity(order = 135)
public static class CustomOrderConfig extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity(order = 135)
public static class CustomOrderConfig extends BaseMethodConfig {
}
def "order is defaulted to Ordered.LOWEST_PRECEDENCE when using @EnableGlobalMethodSecurity"() {
when:
context = new AnnotationConfigApplicationContext(DefaultOrderConfig)
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
then:
advisor.order == Ordered.LOWEST_PRECEDENCE
}
def "order is defaulted to Ordered.LOWEST_PRECEDENCE when using @EnableGlobalMethodSecurity"() {
when:
context = new AnnotationConfigApplicationContext(DefaultOrderConfig)
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
then:
advisor.order == Ordered.LOWEST_PRECEDENCE
}
@EnableGlobalMethodSecurity
public static class DefaultOrderConfig extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity
public static class DefaultOrderConfig extends BaseMethodConfig {
}
def "order is defaulted to Ordered.LOWEST_PRECEDENCE when extending GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,DefaultOrderExtendsMethodSecurityConfig)
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
then:
advisor.order == Ordered.LOWEST_PRECEDENCE
}
def "order is defaulted to Ordered.LOWEST_PRECEDENCE when extending GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,DefaultOrderExtendsMethodSecurityConfig)
MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
then:
advisor.order == Ordered.LOWEST_PRECEDENCE
}
@EnableGlobalMethodSecurity
public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
@EnableGlobalMethodSecurity
public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
// --- pre-post-annotations ---
// --- pre-post-annotations ---
def preAuthorize() {
when:
context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
def preAuthorize() {
when:
context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class PreAuthorizeConfig extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class PreAuthorizeConfig extends BaseMethodConfig {
}
def "prePostEnabled extends GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,PreAuthorizeExtendsGMSCConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
def "prePostEnabled extends GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,PreAuthorizeExtendsGMSCConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
}
// --- proxy-target-class ---
// --- proxy-target-class ---
def "proxying classes works"() {
when:
context = new AnnotationConfigApplicationContext(ProxyTargetClass)
MethodSecurityServiceImpl service = context.getBean(MethodSecurityServiceImpl)
then:
noExceptionThrown()
}
def "proxying classes works"() {
when:
context = new AnnotationConfigApplicationContext(ProxyTargetClass)
MethodSecurityServiceImpl service = context.getBean(MethodSecurityServiceImpl)
then:
noExceptionThrown()
}
@EnableGlobalMethodSecurity(proxyTargetClass = true)
@Configuration
public static class ProxyTargetClass extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity(proxyTargetClass = true)
@Configuration
public static class ProxyTargetClass extends BaseMethodConfig {
}
def "proxying interfaces works"() {
when:
context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then: "we get an instance of the interface"
noExceptionThrown()
when: "try to cast to the class"
MethodSecurityServiceImpl serviceImpl = service
then: "we get a class cast exception"
thrown(ClassCastException)
}
def "proxying interfaces works"() {
when:
context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then: "we get an instance of the interface"
noExceptionThrown()
when: "try to cast to the class"
MethodSecurityServiceImpl serviceImpl = service
then: "we get a class cast exception"
thrown(ClassCastException)
}
// --- run-as-manager-ref ---
// --- run-as-manager-ref ---
def "custom RunAsManager"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomRunAsManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.runAs().authorities.find { it.authority == "ROLE_RUN_AS_SUPER"}
}
def "custom RunAsManager"() {
when:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomRunAsManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.runAs().authorities.find { it.authority == "ROLE_RUN_AS_SUPER"}
}
@EnableGlobalMethodSecurity(securedEnabled = true)
public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected RunAsManager runAsManager() {
RunAsManagerImpl runAsManager = new RunAsManagerImpl()
runAsManager.setKey("some key")
return runAsManager
}
}
@EnableGlobalMethodSecurity(securedEnabled = true)
public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected RunAsManager runAsManager() {
RunAsManagerImpl runAsManager = new RunAsManagerImpl()
runAsManager.setKey("some key")
return runAsManager
}
}
// --- secured-annotation ---
// --- secured-annotation ---
def "secured enabled"() {
setup:
context = new AnnotationConfigApplicationContext(SecuredConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.secured()
then:
thrown(AccessDeniedException)
and: "service with ROLE_USER allowed"
service.securedUser() == null
and:
service.preAuthorize() == null
service.jsr250() == null
}
def "secured enabled"() {
setup:
context = new AnnotationConfigApplicationContext(SecuredConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.secured()
then:
thrown(AccessDeniedException)
and: "service with ROLE_USER allowed"
service.securedUser() == null
and:
service.preAuthorize() == null
service.jsr250() == null
}
@EnableGlobalMethodSecurity(securedEnabled = true)
@Configuration
public static class SecuredConfig extends BaseMethodConfig {
}
@EnableGlobalMethodSecurity(securedEnabled = true)
@Configuration
public static class SecuredConfig extends BaseMethodConfig {
}
// --- after-invocation-provider
// --- after-invocation-provider
def "custom AfterInvocationManager"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAfterInvocationManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorizePermitAll()
then:
AccessDeniedException e = thrown()
e.message == "custom AfterInvocationManager"
}
def "custom AfterInvocationManager"() {
setup:
context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAfterInvocationManagerConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorizePermitAll()
then:
AccessDeniedException e = thrown()
e.message == "custom AfterInvocationManager"
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AfterInvocationManager afterInvocationManager() {
return new AfterInvocationManagerStub()
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AfterInvocationManager afterInvocationManager() {
return new AfterInvocationManagerStub()
}
public static class AfterInvocationManagerStub implements AfterInvocationManager {
Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes,
Object returnedObject) throws AccessDeniedException {
throw new AccessDeniedException("custom AfterInvocationManager")
}
public static class AfterInvocationManagerStub implements AfterInvocationManager {
Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes,
Object returnedObject) throws AccessDeniedException {
throw new AccessDeniedException("custom AfterInvocationManager")
}
boolean supports(ConfigAttribute attribute) {
return true
}
boolean supports(Class<?> clazz) {
return true
}
}
}
boolean supports(ConfigAttribute attribute) {
return true
}
boolean supports(Class<?> clazz) {
return true
}
}
}
// --- misc ---
// --- misc ---
def "good error message when no Enable annotation"() {
when:
context = new AnnotationConfigApplicationContext(ExtendsNoEnableAnntotationConfig)
MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
then:
BeanCreationException e = thrown()
e.message.contains(EnableGlobalMethodSecurity.class.getName() + " is required")
}
def "good error message when no Enable annotation"() {
when:
context = new AnnotationConfigApplicationContext(ExtendsNoEnableAnntotationConfig)
MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
then:
BeanCreationException e = thrown()
e.message.contains(EnableGlobalMethodSecurity.class.getName() + " is required")
}
@Configuration
public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AuthenticationManager authenticationManager() {
return new AuthenticationManager() {
Authentication authenticate(Authentication authentication) {
throw new UnsupportedOperationException()
}
}
}
}
@Configuration
public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration {
@Override
protected AuthenticationManager authenticationManager() {
return new AuthenticationManager() {
Authentication authenticate(Authentication authentication) {
throw new UnsupportedOperationException()
}
}
}
}
def "import subclass of GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(ImportSubclassGMSCConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
def "import subclass of GlobalMethodSecurityConfiguration"() {
when:
context = new AnnotationConfigApplicationContext(ImportSubclassGMSCConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
@Configuration
@Import(PreAuthorizeExtendsGMSCConfig)
public static class ImportSubclassGMSCConfig extends BaseMethodConfig {
}
@Configuration
@Import(PreAuthorizeExtendsGMSCConfig)
public static class ImportSubclassGMSCConfig extends BaseMethodConfig {
}
@Configuration
public static class BaseMethodConfig extends BaseAuthenticationConfig {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
}
@Configuration
public static class BaseMethodConfig extends BaseAuthenticationConfig {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
}
}
@@ -39,87 +39,87 @@ import org.springframework.security.core.context.SecurityContextHolder
*
*/
public class SampleEnableGlobalMethodSecurityTests extends BaseSpringSpec {
def setup() {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
}
def setup() {
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
}
def preAuthorize() {
when:
loadConfig(SampleWebSecurityConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
def preAuthorize() {
when:
loadConfig(SampleWebSecurityConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.secured() == null
service.jsr250() == null
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled=true)
public static class SampleWebSecurityConfig {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
@EnableGlobalMethodSecurity(prePostEnabled=true)
public static class SampleWebSecurityConfig {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
def 'custom permission handler'() {
when:
loadConfig(CustomPermissionEvaluatorWebSecurityConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.hasPermission("allowed") == null
def 'custom permission handler'() {
when:
loadConfig(CustomPermissionEvaluatorWebSecurityConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
then:
service.hasPermission("allowed") == null
when:
service.hasPermission("denied") == null
then:
thrown(AccessDeniedException)
}
when:
service.hasPermission("denied") == null
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled=true)
public static class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
@EnableGlobalMethodSecurity(prePostEnabled=true)
public static class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration {
@Bean
public MethodSecurityService methodSecurityService() {
return new MethodSecurityServiceImpl()
}
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
return expressionHandler;
}
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
return expressionHandler;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
static class CustomPermissionEvaluator implements PermissionEvaluator {
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return !"denied".equals(targetDomainObject);
}
static class CustomPermissionEvaluator implements PermissionEvaluator {
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return !"denied".equals(targetDomainObject);
}
public boolean hasPermission(Authentication authentication,
Serializable targetId, String targetType, Object permission) {
return !"denied".equals(targetId);
}
public boolean hasPermission(Authentication authentication,
Serializable targetId, String targetType, Object permission) {
return !"denied".equals(targetId);
}
}
}
}
@@ -29,69 +29,69 @@ import spock.lang.Specification
*/
class UserDetailsManagerConfigurerTests extends Specification {
def "all attributes supported"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.roles("USER")
.disabled(true)
.accountExpired(true)
.accountLocked(true)
.credentialsExpired(true)
.build()
then:
userDetails.username == 'user'
userDetails.password == 'password'
userDetails.authorities.collect { it.authority } == ["ROLE_USER"]
!userDetails.accountNonExpired
!userDetails.accountNonLocked
!userDetails.credentialsNonExpired
!userDetails.enabled
}
def "all attributes supported"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.roles("USER")
.disabled(true)
.accountExpired(true)
.accountLocked(true)
.credentialsExpired(true)
.build()
then:
userDetails.username == 'user'
userDetails.password == 'password'
userDetails.authorities.collect { it.authority } == ["ROLE_USER"]
!userDetails.accountNonExpired
!userDetails.accountNonLocked
!userDetails.credentialsNonExpired
!userDetails.enabled
}
def "authorities(GrantedAuthorities...) works"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.authorities(authority)
.build()
then:
userDetails.authorities == [authority] as Set
}
def "authorities(GrantedAuthorities...) works"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.authorities(authority)
.build()
then:
userDetails.authorities == [authority] as Set
}
def "authorities(String...) works"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
String authority = "ROLE_USER"
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.authorities(authority)
.build()
then:
userDetails.authorities.collect { it.authority } == [authority]
}
def "authorities(String...) works"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
String authority = "ROLE_USER"
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.authorities(authority)
.build()
then:
userDetails.authorities.collect { it.authority } == [authority]
}
def "authorities(List) works"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.authorities([authority])
.build()
then:
userDetails.authorities == [authority] as Set
}
def "authorities(List) works"() {
setup:
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
when:
UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
.withUser("user")
.password("password")
.authorities([authority])
.build()
then:
userDetails.authorities == [authority] as Set
}
}
@@ -30,144 +30,144 @@ import spock.lang.Specification
*/
class AbstractConfiguredSecurityBuilderTests extends BaseSpringSpec {
ConcreteAbstractConfiguredBuilder builder
ConcreteAbstractConfiguredBuilder builder
def setup() {
builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor)
}
def setup() {
builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor)
}
def "Null ObjectPostProcessor rejected"() {
when:
new ConcreteAbstractConfiguredBuilder(null)
then:
thrown(IllegalArgumentException)
when:
builder.objectPostProcessor(null);
then:
thrown(IllegalArgumentException)
}
def "Null ObjectPostProcessor rejected"() {
when:
new ConcreteAbstractConfiguredBuilder(null)
then:
thrown(IllegalArgumentException)
when:
builder.objectPostProcessor(null);
then:
thrown(IllegalArgumentException)
}
def "apply null is rejected"() {
when:
builder.apply(null)
then:
thrown(IllegalArgumentException)
}
def "apply null is rejected"() {
when:
builder.apply(null)
then:
thrown(IllegalArgumentException)
}
def "Duplicate configurer is removed"() {
when:
builder.apply(new ConcreteConfigurer())
builder.apply(new ConcreteConfigurer())
then:
ReflectionTestUtils.getField(builder,"configurers").size() == 1
}
def "Duplicate configurer is removed"() {
when:
builder.apply(new ConcreteConfigurer())
builder.apply(new ConcreteConfigurer())
then:
ReflectionTestUtils.getField(builder,"configurers").size() == 1
}
def "build twice fails"() {
setup:
builder.build()
when:
builder.build()
then:
thrown(IllegalStateException)
}
def "build twice fails"() {
setup:
builder.build()
when:
builder.build()
then:
thrown(IllegalStateException)
}
def "getObject before build fails"() {
when:
builder.getObject()
then:
thrown(IllegalStateException)
}
def "getObject before build fails"() {
when:
builder.getObject()
then:
thrown(IllegalStateException)
}
def "Configurer.init can apply another configurer"() {
setup:
DelegateConfigurer.CONF = Mock(SecurityConfigurerAdapter)
when:
builder.apply(new DelegateConfigurer())
builder.build()
then:
1 * DelegateConfigurer.CONF.init(builder)
1 * DelegateConfigurer.CONF.configure(builder)
}
def "Configurer.init can apply another configurer"() {
setup:
DelegateConfigurer.CONF = Mock(SecurityConfigurerAdapter)
when:
builder.apply(new DelegateConfigurer())
builder.build()
then:
1 * DelegateConfigurer.CONF.init(builder)
1 * DelegateConfigurer.CONF.configure(builder)
}
def "getConfigurer with multi fails"() {
setup:
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(new DelegateConfigurer())
builder.apply(new DelegateConfigurer())
when:
builder.getConfigurer(DelegateConfigurer)
then: "Fail due to trying to obtain a single DelegateConfigurer and multiple are provided"
thrown(IllegalStateException)
}
def "getConfigurer with multi fails"() {
setup:
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(new DelegateConfigurer())
builder.apply(new DelegateConfigurer())
when:
builder.getConfigurer(DelegateConfigurer)
then: "Fail due to trying to obtain a single DelegateConfigurer and multiple are provided"
thrown(IllegalStateException)
}
def "removeConfigurer with multi fails"() {
setup:
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(new DelegateConfigurer())
builder.apply(new DelegateConfigurer())
when:
builder.removeConfigurer(DelegateConfigurer)
then: "Fail due to trying to remove and obtain a single DelegateConfigurer and multiple are provided"
thrown(IllegalStateException)
}
def "removeConfigurer with multi fails"() {
setup:
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(new DelegateConfigurer())
builder.apply(new DelegateConfigurer())
when:
builder.removeConfigurer(DelegateConfigurer)
then: "Fail due to trying to remove and obtain a single DelegateConfigurer and multiple are provided"
thrown(IllegalStateException)
}
def "removeConfigurers with multi"() {
setup:
DelegateConfigurer c1 = new DelegateConfigurer()
DelegateConfigurer c2 = new DelegateConfigurer()
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(c1)
builder.apply(c2)
when:
def result = builder.removeConfigurers(DelegateConfigurer)
then:
result.size() == 2
result.contains(c1)
result.contains(c2)
builder.getConfigurers(DelegateConfigurer).empty
}
def "removeConfigurers with multi"() {
setup:
DelegateConfigurer c1 = new DelegateConfigurer()
DelegateConfigurer c2 = new DelegateConfigurer()
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(c1)
builder.apply(c2)
when:
def result = builder.removeConfigurers(DelegateConfigurer)
then:
result.size() == 2
result.contains(c1)
result.contains(c2)
builder.getConfigurers(DelegateConfigurer).empty
}
def "getConfigurers with multi"() {
setup:
DelegateConfigurer c1 = new DelegateConfigurer()
DelegateConfigurer c2 = new DelegateConfigurer()
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(c1)
builder.apply(c2)
when:
def result = builder.getConfigurers(DelegateConfigurer)
then:
result.size() == 2
result.contains(c1)
result.contains(c2)
builder.getConfigurers(DelegateConfigurer).size() == 2
}
def "getConfigurers with multi"() {
setup:
DelegateConfigurer c1 = new DelegateConfigurer()
DelegateConfigurer c2 = new DelegateConfigurer()
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
builder.apply(c1)
builder.apply(c2)
when:
def result = builder.getConfigurers(DelegateConfigurer)
then:
result.size() == 2
result.contains(c1)
result.contains(c2)
builder.getConfigurers(DelegateConfigurer).size() == 2
}
private static class DelegateConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> {
private static SecurityConfigurer<Object, ConcreteAbstractConfiguredBuilder> CONF;
private static class DelegateConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> {
private static SecurityConfigurer<Object, ConcreteAbstractConfiguredBuilder> CONF;
@Override
public void init(ConcreteAbstractConfiguredBuilder builder)
throws Exception {
builder.apply(CONF);
}
}
@Override
public void init(ConcreteAbstractConfiguredBuilder builder)
throws Exception {
builder.apply(CONF);
}
}
private static class ConcreteConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> { }
private static class ConcreteConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> { }
private class ConcreteAbstractConfiguredBuilder extends AbstractConfiguredSecurityBuilder<Object, ConcreteAbstractConfiguredBuilder> {
private class ConcreteAbstractConfiguredBuilder extends AbstractConfiguredSecurityBuilder<Object, ConcreteAbstractConfiguredBuilder> {
public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
super(objectPostProcessor);
}
public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
super(objectPostProcessor);
}
public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor, boolean allowMulti) {
super(objectPostProcessor,allowMulti);
}
public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor, boolean allowMulti) {
super(objectPostProcessor,allowMulti);
}
public Object performBuild() throws Exception {
return "success";
}
}
public Object performBuild() throws Exception {
return "success";
}
}
}
@@ -34,286 +34,286 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
*
*/
public class SampleWebSecurityConfigurerAdapterTests extends BaseSpringSpec {
def "README HelloWorld Sample works"() {
setup: "Sample Config is loaded"
loadConfig(HelloWorldWebSecurityConfigurerAdapter)
when:
request.addHeader("Accept", "text/html")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.addHeader("Accept", "text/html")
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
def "README HelloWorld Sample works"() {
setup: "Sample Config is loaded"
loadConfig(HelloWorldWebSecurityConfigurerAdapter)
when:
request.addHeader("Accept", "text/html")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.addHeader("Accept", "text/html")
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
/**
* <code>
* <http>
* <intercept-url pattern="/resources/**" access="permitAll"/>
* <intercept-url pattern="/**" access="authenticated"/>
* <logout
* logout-success-url="/login?logout"
* logout-url="/logout"
* <form-login
* authentication-failure-url="/login?error"
* login-page="/login" <!-- Except Spring Security renders the login page -->
* login-processing-url="/login" <!-- but only POST -->
* password-parameter="password"
* username-parameter="username"
* />
* </http>
* <authentication-manager>
* <authentication-provider>
* <user-service>
* <user username="user" password="password" authorities="ROLE_USER"/>
* </user-service>
* </authentication-provider>
* </authentication-manager>
* </code>
* @author Rob Winch
*/
@EnableWebSecurity
public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
/**
* <code>
* <http>
* <intercept-url pattern="/resources/**" access="permitAll"/>
* <intercept-url pattern="/**" access="authenticated"/>
* <logout
* logout-success-url="/login?logout"
* logout-url="/logout"
* <form-login
* authentication-failure-url="/login?error"
* login-page="/login" <!-- Except Spring Security renders the login page -->
* login-processing-url="/login" <!-- but only POST -->
* password-parameter="password"
* username-parameter="username"
* />
* </http>
* <authentication-manager>
* <authentication-provider>
* <user-service>
* <user username="user" password="password" authorities="ROLE_USER"/>
* </user-service>
* </authentication-provider>
* </authentication-manager>
* </code>
* @author Rob Winch
*/
@EnableWebSecurity
public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
def "README Sample works"() {
setup: "Sample Config is loaded"
loadConfig(SampleWebSecurityConfigurerAdapter)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
def "README Sample works"() {
setup: "Sample Config is loaded"
loadConfig(SampleWebSecurityConfigurerAdapter)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
/**
* <code>
* <http security="none" pattern="/resources/**"/>
* <http>
* <intercept-url pattern="/logout" access="permitAll"/>
* <intercept-url pattern="/login" access="permitAll"/>
* <intercept-url pattern="/signup" access="permitAll"/>
* <intercept-url pattern="/about" access="permitAll"/>
* <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
* <logout
* logout-success-url="/login?logout"
* logout-url="/logout"
* <form-login
* authentication-failure-url="/login?error"
* login-page="/login"
* login-processing-url="/login" <!-- but only POST -->
* password-parameter="password"
* username-parameter="username"
* />
* </http>
* <authentication-manager>
* <authentication-provider>
* <user-service>
* <user username="user" password="password" authorities="ROLE_USER"/>
* <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
* </user-service>
* </authentication-provider>
* </authentication-manager>
* </code>
* @author Rob Winch
*/
@EnableWebSecurity
public static class SampleWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
/**
* <code>
* <http security="none" pattern="/resources/**"/>
* <http>
* <intercept-url pattern="/logout" access="permitAll"/>
* <intercept-url pattern="/login" access="permitAll"/>
* <intercept-url pattern="/signup" access="permitAll"/>
* <intercept-url pattern="/about" access="permitAll"/>
* <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
* <logout
* logout-success-url="/login?logout"
* logout-url="/logout"
* <form-login
* authentication-failure-url="/login?error"
* login-page="/login"
* login-processing-url="/login" <!-- but only POST -->
* password-parameter="password"
* username-parameter="username"
* />
* </http>
* <authentication-manager>
* <authentication-provider>
* <user-service>
* <user username="user" password="password" authorities="ROLE_USER"/>
* <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
* </user-service>
* </authentication-provider>
* </authentication-manager>
* </code>
* @author Rob Winch
*/
@EnableWebSecurity
public static class SampleWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
// set permitAll for all URLs associated with Form Login
.permitAll();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
// set permitAll for all URLs associated with Form Login
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
}
def "README Multi http Sample works"() {
setup:
loadConfig(SampleMultiHttpSecurityConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
def "README Multi http Sample works"() {
setup:
loadConfig(SampleMultiHttpSecurityConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
when: "request protected API URL"
super.setup()
request.servletPath = "/api/admin/test"
springSecurityFilterChain.doFilter(request,response,chain)
then: "get 401"
response.getStatus() == HttpServletResponse.SC_UNAUTHORIZED
when: "request protected API URL"
super.setup()
request.servletPath = "/api/admin/test"
springSecurityFilterChain.doFilter(request,response,chain)
then: "get 401"
response.getStatus() == HttpServletResponse.SC_UNAUTHORIZED
when: "request API for admins with user"
super.setup()
request.servletPath = "/api/admin/test"
request.addHeader("Authorization", "Basic " + "user:password".bytes.encodeBase64().toString())
springSecurityFilterChain.doFilter(request,response,chain)
then: "get 403"
response.getStatus() == HttpServletResponse.SC_FORBIDDEN
when: "request API for admins with user"
super.setup()
request.servletPath = "/api/admin/test"
request.addHeader("Authorization", "Basic " + "user:password".bytes.encodeBase64().toString())
springSecurityFilterChain.doFilter(request,response,chain)
then: "get 403"
response.getStatus() == HttpServletResponse.SC_FORBIDDEN
when: "request API for admins with admin"
super.setup()
request.servletPath = "/api/admin/test"
request.addHeader("Authorization", "Basic " + "admin:password".bytes.encodeBase64().toString())
springSecurityFilterChain.doFilter(request,response,chain)
then: "get 200"
response.getStatus() == HttpServletResponse.SC_OK
}
when: "request API for admins with admin"
super.setup()
request.servletPath = "/api/admin/test"
request.addHeader("Authorization", "Basic " + "admin:password".bytes.encodeBase64().toString())
springSecurityFilterChain.doFilter(request,response,chain)
then: "get 200"
response.getStatus() == HttpServletResponse.SC_OK
}
/**
* <code>
* <http security="none" pattern="/resources/**"/>
* <http pattern="/api/**">
* <intercept-url pattern="/api/admin/**" access="hasRole('ROLE_ADMIN')"/>
* <intercept-url pattern="/api/**" access="hasRole('ROLE_USER')"/>
* <http-basic />
* </http>
* <http>
* <intercept-url pattern="/logout" access="permitAll"/>
* <intercept-url pattern="/login" access="permitAll"/>
* <intercept-url pattern="/signup" access="permitAll"/>
* <intercept-url pattern="/about" access="permitAll"/>
* <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
* <logout
* logout-success-url="/login?logout"
* logout-url="/logout"
* <form-login
* authentication-failure-url="/login?error"
* login-page="/login"
* login-processing-url="/login" <!-- but only POST -->
* password-parameter="password"
* username-parameter="username"
* />
* </http>
* <authentication-manager>
* <authentication-provider>
* <user-service>
* <user username="user" password="password" authorities="ROLE_USER"/>
* <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
* </user-service>
* </authentication-provider>
* </authentication-manager>
* </code>
* @author Rob Winch
*/
@EnableWebSecurity
public static class SampleMultiHttpSecurityConfig {
@Autowired
protected void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
/**
* <code>
* <http security="none" pattern="/resources/**"/>
* <http pattern="/api/**">
* <intercept-url pattern="/api/admin/**" access="hasRole('ROLE_ADMIN')"/>
* <intercept-url pattern="/api/**" access="hasRole('ROLE_USER')"/>
* <http-basic />
* </http>
* <http>
* <intercept-url pattern="/logout" access="permitAll"/>
* <intercept-url pattern="/login" access="permitAll"/>
* <intercept-url pattern="/signup" access="permitAll"/>
* <intercept-url pattern="/about" access="permitAll"/>
* <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
* <logout
* logout-success-url="/login?logout"
* logout-url="/logout"
* <form-login
* authentication-failure-url="/login?error"
* login-page="/login"
* login-processing-url="/login" <!-- but only POST -->
* password-parameter="password"
* username-parameter="username"
* />
* </http>
* <authentication-manager>
* <authentication-provider>
* <user-service>
* <user username="user" password="password" authorities="ROLE_USER"/>
* <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
* </user-service>
* </authentication-provider>
* </authentication-manager>
* </code>
* @author Rob Winch
*/
@EnableWebSecurity
public static class SampleMultiHttpSecurityConfig {
@Autowired
protected void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").hasRole("USER")
.and()
.httpBasic();
}
}
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").hasRole("USER")
.and()
.httpBasic();
}
}
@Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup","/about").permitAll()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
}
}
@@ -56,240 +56,240 @@ import org.springframework.web.filter.OncePerRequestFilter
*/
class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
def "MessageSources populated on AuthenticationProviders"() {
when:
loadConfig(MessageSourcesPopulatedConfig)
List<AuthenticationProvider> providers = authenticationProviders()
then:
providers*.messages*.messageSource == [context,context,context,context]
}
def "MessageSources populated on AuthenticationProviders"() {
when:
loadConfig(MessageSourcesPopulatedConfig)
List<AuthenticationProvider> providers = authenticationProviders()
then:
providers*.messages*.messageSource == [context,context,context,context]
}
def "messages set when using WebSecurityConfigurerAdapter"() {
when:
loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
then:
authenticationManager.messages.messageSource instanceof ApplicationContext
}
def "messages set when using WebSecurityConfigurerAdapter"() {
when:
loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
then:
authenticationManager.messages.messageSource instanceof ApplicationContext
}
def "headers are populated by default"() {
setup: "load config that overrides http and accepts defaults"
loadConfig(HeadersArePopulatedByDefaultConfig)
request.secure = true
when: "invoke the springSecurityFilterChain"
springSecurityFilterChain.doFilter(request, response, chain)
then: "the default headers are added"
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'DENY',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Pragma':'no-cache',
'Expires' : '0',
'X-XSS-Protection' : '1; mode=block']
}
def "headers are populated by default"() {
setup: "load config that overrides http and accepts defaults"
loadConfig(HeadersArePopulatedByDefaultConfig)
request.secure = true
when: "invoke the springSecurityFilterChain"
springSecurityFilterChain.doFilter(request, response, chain)
then: "the default headers are added"
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'DENY',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Pragma':'no-cache',
'Expires' : '0',
'X-XSS-Protection' : '1; mode=block']
}
@EnableWebSecurity
static class HeadersArePopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HeadersArePopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(HttpSecurity http) throws Exception {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
}
}
def "webasync populated by default"() {
when: "load config that overrides http and accepts defaults"
loadConfig(WebAsyncPopulatedByDefaultConfig)
then: "WebAsyncManagerIntegrationFilter is populated"
findFilter(WebAsyncManagerIntegrationFilter)
}
def "webasync populated by default"() {
when: "load config that overrides http and accepts defaults"
loadConfig(WebAsyncPopulatedByDefaultConfig)
then: "WebAsyncManagerIntegrationFilter is populated"
findFilter(WebAsyncManagerIntegrationFilter)
}
@EnableWebSecurity
static class WebAsyncPopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class WebAsyncPopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(HttpSecurity http) throws Exception {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
}
}
def "AuthenticationEventPublisher is registered for Web configure(AuthenticationManagerBuilder auth)"() {
when:
loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
then:
authenticationManager.parent.eventPublisher instanceof DefaultAuthenticationEventPublisher
when:
Authentication token = new UsernamePasswordAuthenticationToken("user","password")
authenticationManager.authenticate(token)
then: "We only receive the AuthenticationSuccessEvent once"
InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS.size() == 1
InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS[0].authentication.name == token.principal
}
def "AuthenticationEventPublisher is registered for Web configure(AuthenticationManagerBuilder auth)"() {
when:
loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
then:
authenticationManager.parent.eventPublisher instanceof DefaultAuthenticationEventPublisher
when:
Authentication token = new UsernamePasswordAuthenticationToken("user","password")
authenticationManager.authenticate(token)
then: "We only receive the AuthenticationSuccessEvent once"
InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS.size() == 1
InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS[0].authentication.name == token.principal
}
@EnableWebSecurity
static class InMemoryAuthWithWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter implements ApplicationListener<AuthenticationSuccessEvent> {
static List<AuthenticationSuccessEvent> EVENTS = []
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
@EnableWebSecurity
static class InMemoryAuthWithWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter implements ApplicationListener<AuthenticationSuccessEvent> {
static List<AuthenticationSuccessEvent> EVENTS = []
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent e) {
EVENTS.add(e)
}
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent e) {
EVENTS.add(e)
}
}
def "Override ContentNegotiationStrategy with @Bean"() {
setup:
OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
when:
loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
then:
context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
}
def "Override ContentNegotiationStrategy with @Bean"() {
setup:
OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
when:
loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
then:
context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
}
@EnableWebSecurity
static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
static ContentNegotiationStrategy CNS
@EnableWebSecurity
static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
static ContentNegotiationStrategy CNS
@Bean
public ContentNegotiationStrategy cns() {
return CNS
}
}
@Bean
public ContentNegotiationStrategy cns() {
return CNS
}
}
def "ContentNegotiationStrategy shareObject defaults to Header with no @Bean"() {
when:
loadConfig(ContentNegotiationStrategyDefaultSharedObjectConfig)
then:
context.getBean(ContentNegotiationStrategyDefaultSharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy).class == HeaderContentNegotiationStrategy
}
def "ContentNegotiationStrategy shareObject defaults to Header with no @Bean"() {
when:
loadConfig(ContentNegotiationStrategyDefaultSharedObjectConfig)
then:
context.getBean(ContentNegotiationStrategyDefaultSharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy).class == HeaderContentNegotiationStrategy
}
@EnableWebSecurity
static class ContentNegotiationStrategyDefaultSharedObjectConfig extends WebSecurityConfigurerAdapter {}
@EnableWebSecurity
static class ContentNegotiationStrategyDefaultSharedObjectConfig extends WebSecurityConfigurerAdapter {}
def "UserDetailsService lazy"() {
setup:
loadConfig(RequiresUserDetailsServiceConfig,UserDetailsServiceConfig)
when:
findFilter(MyFilter).userDetailsService.loadUserByUsername("user")
then:
noExceptionThrown()
when:
findFilter(MyFilter).userDetailsService.loadUserByUsername("admin")
then:
thrown(UsernameNotFoundException)
}
def "UserDetailsService lazy"() {
setup:
loadConfig(RequiresUserDetailsServiceConfig,UserDetailsServiceConfig)
when:
findFilter(MyFilter).userDetailsService.loadUserByUsername("user")
then:
noExceptionThrown()
when:
findFilter(MyFilter).userDetailsService.loadUserByUsername("admin")
then:
thrown(UsernameNotFoundException)
}
@Configuration
static class RequiresUserDetailsServiceConfig {
@Bean
public MyFilter myFilter(UserDetailsService uds) {
return new MyFilter(uds)
}
}
@Configuration
static class RequiresUserDetailsServiceConfig {
@Bean
public MyFilter myFilter(UserDetailsService uds) {
return new MyFilter(uds)
}
}
@EnableWebSecurity
static class UserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilter myFilter;
@EnableWebSecurity
static class UserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilter myFilter;
@Bean
@Override
public UserDetailsService userDetailsServiceBean() {
return super.userDetailsServiceBean()
}
@Bean
@Override
public UserDetailsService userDetailsServiceBean() {
return super.userDetailsServiceBean()
}
@Override
public void configure(HttpSecurity http) {
http
.addFilterBefore(myFilter,UsernamePasswordAuthenticationFilter)
}
@Override
public void configure(HttpSecurity http) {
http
.addFilterBefore(myFilter,UsernamePasswordAuthenticationFilter)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object"() {
when:
loadConfig(ApplicationContextSharedObjectConfig)
then:
context.getBean(ApplicationContextSharedObjectConfig).http.getSharedObject(ApplicationContext) == context
}
def "SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object"() {
when:
loadConfig(ApplicationContextSharedObjectConfig)
then:
context.getBean(ApplicationContextSharedObjectConfig).http.getSharedObject(ApplicationContext) == context
}
@EnableWebSecurity
static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter {
}
}
static class MyFilter extends OncePerRequestFilter {
private UserDetailsService userDetailsService
public MyFilter(UserDetailsService uds) {
assert uds != null
this.userDetailsService = uds
}
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
chain.doFilter(request,response)
}
}
static class MyFilter extends OncePerRequestFilter {
private UserDetailsService userDetailsService
public MyFilter(UserDetailsService uds) {
assert uds != null
this.userDetailsService = uds
}
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
chain.doFilter(request,response)
}
}
def "AuthenticationTrustResolver populated as defaultObject"() {
setup:
CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(CustomTrustResolverConfig)
then:
context.getBean(CustomTrustResolverConfig).http.getSharedObject(AuthenticationTrustResolver) == CustomTrustResolverConfig.TR
}
def "AuthenticationTrustResolver populated as defaultObject"() {
setup:
CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(CustomTrustResolverConfig)
then:
context.getBean(CustomTrustResolverConfig).http.getSharedObject(AuthenticationTrustResolver) == CustomTrustResolverConfig.TR
}
@EnableWebSecurity
static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter {
static AuthenticationTrustResolver TR
@EnableWebSecurity
static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter {
static AuthenticationTrustResolver TR
@Bean
public AuthenticationTrustResolver tr() {
return TR
}
}
@Bean
public AuthenticationTrustResolver tr() {
return TR
}
}
def "WebSecurityConfigurerAdapter has Ordered between 0 and lowest priority"() {
when:
def lowestConfig = new LowestPriorityWebSecurityConfig()
def defaultConfig = new DefaultOrderWebSecurityConfig()
def compare = new AnnotationAwareOrderComparator()
then: "the default ordering is between 0 and lowest priority (Boot adapters)"
compare.compare(lowestConfig, defaultConfig) > 0
}
def "WebSecurityConfigurerAdapter has Ordered between 0 and lowest priority"() {
when:
def lowestConfig = new LowestPriorityWebSecurityConfig()
def defaultConfig = new DefaultOrderWebSecurityConfig()
def compare = new AnnotationAwareOrderComparator()
then: "the default ordering is between 0 and lowest priority (Boot adapters)"
compare.compare(lowestConfig, defaultConfig) > 0
}
class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {}
class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {}
@Order(Ordered.LOWEST_PRECEDENCE)
class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {}
@Order(Ordered.LOWEST_PRECEDENCE)
class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {}
}
@@ -41,81 +41,81 @@ import spock.lang.Unroll;
*
*/
public class HttpSecurityTests extends BaseSpringSpec {
def "addFilter with unregistered Filter"() {
when:
loadConfig(UnregisteredFilterConfig)
then:
BeanCreationException success = thrown()
success.message.contains "The Filter class ${UnregisteredFilter.name} does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."
}
def "addFilter with unregistered Filter"() {
when:
loadConfig(UnregisteredFilterConfig)
then:
BeanCreationException success = thrown()
success.message.contains "The Filter class ${UnregisteredFilter.name} does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."
}
@Configuration
static class UnregisteredFilterConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(new UnregisteredFilter())
}
}
@Configuration
static class UnregisteredFilterConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(new UnregisteredFilter())
}
}
static class UnregisteredFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(request, response);
}
}
static class UnregisteredFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(request, response);
}
}
// https://github.com/SpringSource/spring-security-javaconfig/issues/104
def "#104 addFilter CasAuthenticationFilter"() {
when:
loadConfig(CasAuthenticationFilterConfig)
then:
findFilter(CasAuthenticationFilter)
}
// https://github.com/SpringSource/spring-security-javaconfig/issues/104
def "#104 addFilter CasAuthenticationFilter"() {
when:
loadConfig(CasAuthenticationFilterConfig)
then:
findFilter(CasAuthenticationFilter)
}
@Configuration
static class CasAuthenticationFilterConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(new CasAuthenticationFilter())
}
}
@Configuration
static class CasAuthenticationFilterConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(new CasAuthenticationFilter())
}
}
@Unroll
def "requestMatchers javadoc"() {
setup: "load configuration like the config on the requestMatchers() javadoc"
loadConfig(RequestMatcherRegistryConfigs)
when:
super.setup()
request.servletPath = "/oauth/a"
springSecurityFilterChain.doFilter(request, response, chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
where:
servletPath | _
"/oauth/a" | _
"/oauth/b" | _
"/api/a" | _
"/api/b" | _
"/oauth2/b" | _
"/api2/b" | _
}
@Unroll
def "requestMatchers javadoc"() {
setup: "load configuration like the config on the requestMatchers() javadoc"
loadConfig(RequestMatcherRegistryConfigs)
when:
super.setup()
request.servletPath = "/oauth/a"
springSecurityFilterChain.doFilter(request, response, chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
where:
servletPath | _
"/oauth/a" | _
"/oauth/b" | _
"/api/a" | _
"/api/b" | _
"/oauth2/b" | _
"/api2/b" | _
}
@EnableWebSecurity
static class RequestMatcherRegistryConfigs extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/api/**")
.antMatchers("/oauth/**")
.and()
.authorizeRequests()
.antMatchers("/**").hasRole("USER")
.and()
.httpBasic()
}
}
@EnableWebSecurity
static class RequestMatcherRegistryConfigs extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/api/**")
.antMatchers("/oauth/**")
.and()
.authorizeRequests()
.antMatchers("/**").hasRole("USER")
.and()
.httpBasic()
}
}
}
@@ -29,57 +29,57 @@ import org.springframework.security.web.debug.DebugFilter;
class EnableWebSecurityTests extends BaseSpringSpec {
def "@Bean(BeanIds.AUTHENTICATION_MANAGER) includes HttpSecurity's AuthenticationManagerBuilder"() {
when:
loadConfig(SecurityConfig)
AuthenticationManager authenticationManager = context.getBean(AuthenticationManager)
AnonymousAuthenticationToken anonymousAuthToken = findFilter(AnonymousAuthenticationFilter).createAuthentication(new MockHttpServletRequest())
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
authenticationManager.authenticate(anonymousAuthToken)
def "@Bean(BeanIds.AUTHENTICATION_MANAGER) includes HttpSecurity's AuthenticationManagerBuilder"() {
when:
loadConfig(SecurityConfig)
AuthenticationManager authenticationManager = context.getBean(AuthenticationManager)
AnonymousAuthenticationToken anonymousAuthToken = findFilter(AnonymousAuthenticationFilter).createAuthentication(new MockHttpServletRequest())
then:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
authenticationManager.authenticate(anonymousAuthToken)
}
}
@EnableWebSecurity
static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
@EnableWebSecurity
static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/*").hasRole("USER")
.and()
.formLogin();
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/*").hasRole("USER")
.and()
.formLogin();
}
}
def "@EnableWebSecurity on superclass"() {
when:
loadConfig(ChildSecurityConfig)
then:
context.getBean("springSecurityFilterChain", DebugFilter)
}
def "@EnableWebSecurity on superclass"() {
when:
loadConfig(ChildSecurityConfig)
then:
context.getBean("springSecurityFilterChain", DebugFilter)
}
@Configuration
static class ChildSecurityConfig extends DebugSecurityConfig {
}
@Configuration
static class ChildSecurityConfig extends DebugSecurityConfig {
}
@EnableWebSecurity(debug=true)
static class DebugSecurityConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity(debug=true)
static class DebugSecurityConfig extends WebSecurityConfigurerAdapter {
}
}
}
@@ -47,295 +47,295 @@ import org.springframework.test.util.ReflectionTestUtils
*/
class WebSecurityConfigurationTests extends BaseSpringSpec {
def "WebSecurityConfigurers are sorted"() {
when:
loadConfig(SortedWebSecurityConfigurerAdaptersConfig);
List<SecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
then:
filterChains[0].requestMatcher.pattern == "/ignore1"
filterChains[0].filters.empty
filterChains[1].requestMatcher.pattern == "/ignore2"
filterChains[1].filters.empty
def "WebSecurityConfigurers are sorted"() {
when:
loadConfig(SortedWebSecurityConfigurerAdaptersConfig);
List<SecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
then:
filterChains[0].requestMatcher.pattern == "/ignore1"
filterChains[0].filters.empty
filterChains[1].requestMatcher.pattern == "/ignore2"
filterChains[1].filters.empty
filterChains[2].requestMatcher.pattern == "/role1/**"
filterChains[3].requestMatcher.pattern == "/role2/**"
filterChains[4].requestMatcher.pattern == "/role3/**"
filterChains[5].requestMatcher.class == AnyRequestMatcher
}
filterChains[2].requestMatcher.pattern == "/role1/**"
filterChains[3].requestMatcher.pattern == "/role2/**"
filterChains[4].requestMatcher.pattern == "/role3/**"
filterChains[5].requestMatcher.class == AnyRequestMatcher
}
@EnableWebSecurity
static class SortedWebSecurityConfigurerAdaptersConfig {
public AuthenticationManager authenticationManager() throws Exception {
return new AuthenticationManagerBuilder()
.inMemoryAuthentication()
.withUser("marissa").password("koala").roles("USER").and()
.withUser("paul").password("emu").roles("USER").and()
.and()
.build();
}
@EnableWebSecurity
static class SortedWebSecurityConfigurerAdaptersConfig {
public AuthenticationManager authenticationManager() throws Exception {
return new AuthenticationManagerBuilder()
.inMemoryAuthentication()
.withUser("marissa").password("koala").roles("USER").and()
.withUser("paul").password("emu").roles("USER").and()
.and()
.build();
}
@Configuration
@Order(1)
public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/ignore1","/ignore2");
}
@Configuration
@Order(1)
public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/ignore1","/ignore2");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role1/**")
.authorizeRequests()
.anyRequest().hasRole("1");
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role1/**")
.authorizeRequests()
.anyRequest().hasRole("1");
}
}
@Configuration
@Order(2)
public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role2/**")
.authorizeRequests()
.anyRequest().hasRole("2");
}
}
@Configuration
@Order(2)
public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role2/**")
.authorizeRequests()
.anyRequest().hasRole("2");
}
}
@Configuration
@Order(3)
public static class WebConfigurer3 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role3/**")
.authorizeRequests()
.anyRequest().hasRole("3");
}
}
@Configuration
@Order(3)
public static class WebConfigurer3 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role3/**")
.authorizeRequests()
.anyRequest().hasRole("3");
}
}
@Configuration
public static class WebConfigurer4 extends WebSecurityConfigurerAdapter {
@Configuration
public static class WebConfigurer4 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("4");
}
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("4");
}
}
}
def "WebSecurityConfigurers fails with duplicate order"() {
when:
loadConfig(DuplicateOrderConfig);
then:
BeanCreationException e = thrown()
e.message.contains "@Order on WebSecurityConfigurers must be unique"
}
def "WebSecurityConfigurers fails with duplicate order"() {
when:
loadConfig(DuplicateOrderConfig);
then:
BeanCreationException e = thrown()
e.message.contains "@Order on WebSecurityConfigurers must be unique"
}
@EnableWebSecurity
static class DuplicateOrderConfig {
public AuthenticationManager authenticationManager() throws Exception {
return new AuthenticationManagerBuilder()
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.and()
.build();
}
@EnableWebSecurity
static class DuplicateOrderConfig {
public AuthenticationManager authenticationManager() throws Exception {
return new AuthenticationManagerBuilder()
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.and()
.build();
}
@Configuration
public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
@Configuration
public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role1/**")
.authorizeRequests()
.anyRequest().hasRole("1");
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role1/**")
.authorizeRequests()
.anyRequest().hasRole("1");
}
}
@Configuration
public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role2/**")
.authorizeRequests()
.anyRequest().hasRole("2");
}
}
}
@Configuration
public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/role2/**")
.authorizeRequests()
.anyRequest().hasRole("2");
}
}
}
def "Override privilegeEvaluator"() {
setup:
WebInvocationPrivilegeEvaluator privilegeEvaluator = Mock()
PrivilegeEvaluatorConfigurerAdapterConfig.PE = privilegeEvaluator
when:
loadConfig(PrivilegeEvaluatorConfigurerAdapterConfig)
then:
context.getBean(WebInvocationPrivilegeEvaluator) == privilegeEvaluator
}
def "Override privilegeEvaluator"() {
setup:
WebInvocationPrivilegeEvaluator privilegeEvaluator = Mock()
PrivilegeEvaluatorConfigurerAdapterConfig.PE = privilegeEvaluator
when:
loadConfig(PrivilegeEvaluatorConfigurerAdapterConfig)
then:
context.getBean(WebInvocationPrivilegeEvaluator) == privilegeEvaluator
}
@EnableWebSecurity
static class PrivilegeEvaluatorConfigurerAdapterConfig extends WebSecurityConfigurerAdapter {
static WebInvocationPrivilegeEvaluator PE
@EnableWebSecurity
static class PrivilegeEvaluatorConfigurerAdapterConfig extends WebSecurityConfigurerAdapter {
static WebInvocationPrivilegeEvaluator PE
@Override
public void configure(WebSecurity web) throws Exception {
web
.privilegeEvaluator(PE)
}
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.privilegeEvaluator(PE)
}
}
def "Override webSecurityExpressionHandler"() {
setup:
SecurityExpressionHandler expressionHandler = Mock()
ExpressionParser parser = Mock()
WebSecurityExpressionHandlerConfig.EH = expressionHandler
when:
loadConfig(WebSecurityExpressionHandlerConfig)
then:
context.getBean(SecurityExpressionHandler) == expressionHandler
1 * expressionHandler.getExpressionParser() >> parser
}
def "Override webSecurityExpressionHandler"() {
setup:
SecurityExpressionHandler expressionHandler = Mock()
ExpressionParser parser = Mock()
WebSecurityExpressionHandlerConfig.EH = expressionHandler
when:
loadConfig(WebSecurityExpressionHandlerConfig)
then:
context.getBean(SecurityExpressionHandler) == expressionHandler
1 * expressionHandler.getExpressionParser() >> parser
}
@EnableWebSecurity
static class WebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
static SecurityExpressionHandler EH
@EnableWebSecurity
static class WebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
static SecurityExpressionHandler EH
@Override
public void configure(WebSecurity web) throws Exception {
web
.expressionHandler(EH)
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.expressionHandler(EH)
.anyRequest().authenticated()
}
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.expressionHandler(EH)
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.expressionHandler(EH)
.anyRequest().authenticated()
}
}
def "#138 webSecurityExpressionHandler defaults"() {
when:
loadConfig(WebSecurityExpressionHandlerDefaultsConfig)
then:
SecurityExpressionHandler wseh = context.getBean(SecurityExpressionHandler)
wseh instanceof DefaultWebSecurityExpressionHandler
}
def "#138 webSecurityExpressionHandler defaults"() {
when:
loadConfig(WebSecurityExpressionHandlerDefaultsConfig)
then:
SecurityExpressionHandler wseh = context.getBean(SecurityExpressionHandler)
wseh instanceof DefaultWebSecurityExpressionHandler
}
@EnableWebSecurity
static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
}
}
def "#138 WebInvocationPrivilegeEvaluator defaults"() {
when:
loadConfig(WebInvocationPrivilegeEvaluatorDefaultsConfig)
then:
WebInvocationPrivilegeEvaluator wipe = context.getBean(WebInvocationPrivilegeEvaluator)
wipe instanceof DefaultWebInvocationPrivilegeEvaluator
wipe.securityInterceptor != null
}
def "#138 WebInvocationPrivilegeEvaluator defaults"() {
when:
loadConfig(WebInvocationPrivilegeEvaluatorDefaultsConfig)
then:
WebInvocationPrivilegeEvaluator wipe = context.getBean(WebInvocationPrivilegeEvaluator)
wipe instanceof DefaultWebInvocationPrivilegeEvaluator
wipe.securityInterceptor != null
}
@EnableWebSecurity
static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
}
}
def "SEC-2303: DefaultExpressionHandler has bean resolver set"() {
when:
loadConfig(DefaultExpressionHandlerSetsBeanResolverConfig)
then: "the exposed bean has a BeanResolver set"
ReflectionTestUtils.getField(context.getBean(SecurityExpressionHandler),"br")
when:
springSecurityFilterChain.doFilter(request, response, chain)
then: "we can use the BeanResolver with a grant"
noExceptionThrown()
when: "we can use the Beanresolver with a deny"
springSecurityFilterChain.doFilter(new MockHttpServletRequest(method:'POST'), response, chain)
then:
noExceptionThrown()
}
def "SEC-2303: DefaultExpressionHandler has bean resolver set"() {
when:
loadConfig(DefaultExpressionHandlerSetsBeanResolverConfig)
then: "the exposed bean has a BeanResolver set"
ReflectionTestUtils.getField(context.getBean(SecurityExpressionHandler),"br")
when:
springSecurityFilterChain.doFilter(request, response, chain)
then: "we can use the BeanResolver with a grant"
noExceptionThrown()
when: "we can use the Beanresolver with a deny"
springSecurityFilterChain.doFilter(new MockHttpServletRequest(method:'POST'), response, chain)
then:
noExceptionThrown()
}
@EnableWebSecurity
static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().access("request.method == 'GET' ? @b.grant() : @b.deny()")
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().access("request.method == 'GET' ? @b.grant() : @b.deny()")
}
@Bean
public MyBean b() {
new MyBean()
}
@Bean
public MyBean b() {
new MyBean()
}
static class MyBean {
boolean deny() {
false
}
static class MyBean {
boolean deny() {
false
}
boolean grant() {
true
}
}
}
boolean grant() {
true
}
}
}
def "SEC-2461: Multiple WebSecurityConfiguration instances cause null springSecurityFilterChain"() {
setup:
def parent = loadConfig(ParentConfig)
def child = new AnnotationConfigApplicationContext()
child.register(ChildConfig)
child.parent = parent
when:
child.refresh()
then: "springSecurityFilterChain can be found in parent and child"
parent.getBean("springSecurityFilterChain")
child.getBean("springSecurityFilterChain")
and: "springSecurityFilterChain is defined in both parent and child (don't search parent)"
parent.containsBeanDefinition("springSecurityFilterChain")
child.containsBeanDefinition("springSecurityFilterChain")
cleanup:
child?.close()
// parent.close() is in superclass
}
def "SEC-2461: Multiple WebSecurityConfiguration instances cause null springSecurityFilterChain"() {
setup:
def parent = loadConfig(ParentConfig)
def child = new AnnotationConfigApplicationContext()
child.register(ChildConfig)
child.parent = parent
when:
child.refresh()
then: "springSecurityFilterChain can be found in parent and child"
parent.getBean("springSecurityFilterChain")
child.getBean("springSecurityFilterChain")
and: "springSecurityFilterChain is defined in both parent and child (don't search parent)"
parent.containsBeanDefinition("springSecurityFilterChain")
child.containsBeanDefinition("springSecurityFilterChain")
cleanup:
child?.close()
// parent.close() is in superclass
}
@EnableWebSecurity
static class ParentConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
}
}
@EnableWebSecurity
static class ParentConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
}
}
@EnableWebSecurity
static class ChildConfig extends WebSecurityConfigurerAdapter { }
@EnableWebSecurity
static class ChildConfig extends WebSecurityConfigurerAdapter { }
def "SEC-2773: delegatingApplicationListener is static method"() {
expect: 'delegatingApplicationListener to prevent premature instantiation of WebSecurityConfiguration'
Modifier.isStatic(WebSecurityConfiguration.metaClass.methods.find { it.name == 'delegatingApplicationListener'}.modifiers)
}
def "SEC-2773: delegatingApplicationListener is static method"() {
expect: 'delegatingApplicationListener to prevent premature instantiation of WebSecurityConfiguration'
Modifier.isStatic(WebSecurityConfiguration.metaClass.methods.find { it.name == 'delegatingApplicationListener'}.modifiers)
}
}
@@ -22,17 +22,17 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
public class Sec2377Tests extends BaseSpringSpec {
def "SEC-2377: Error reporting with multiple EnableWebSecurity from other packages"() {
when:
AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()
parent.register(Sec2377AConfig)
parent.refresh()
def "SEC-2377: Error reporting with multiple EnableWebSecurity from other packages"() {
when:
AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()
parent.register(Sec2377AConfig)
parent.refresh()
AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()
child.register(Sec2377BConfig)
child.parent = parent
child.refresh()
then:
noExceptionThrown();
}
AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()
child.register(Sec2377BConfig)
child.parent = parent
child.refresh()
then:
noExceptionThrown();
}
}
@@ -29,43 +29,43 @@ import spock.lang.Specification
*
*/
class AbstractConfigAttributeRequestMatcherRegistryTests extends Specification {
ConcreteAbstractRequestMatcherMappingConfigurer registry = new ConcreteAbstractRequestMatcherMappingConfigurer()
ConcreteAbstractRequestMatcherMappingConfigurer registry = new ConcreteAbstractRequestMatcherMappingConfigurer()
def "regexMatchers(GET,'/a.*') uses RegexRequestMatcher"() {
when:
def matchers = registry.regexMatchers(HttpMethod.GET,"/a.*")
then: 'matcher is a RegexRequestMatcher'
matchers.collect {it.class } == [RegexRequestMatcher]
}
def "regexMatchers(GET,'/a.*') uses RegexRequestMatcher"() {
when:
def matchers = registry.regexMatchers(HttpMethod.GET,"/a.*")
then: 'matcher is a RegexRequestMatcher'
matchers.collect {it.class } == [RegexRequestMatcher]
}
def "regexMatchers('/a.*') uses RegexRequestMatcher"() {
when:
def matchers = registry.regexMatchers("/a.*")
then: 'matcher is a RegexRequestMatcher'
matchers.collect {it.class } == [RegexRequestMatcher]
}
def "regexMatchers('/a.*') uses RegexRequestMatcher"() {
when:
def matchers = registry.regexMatchers("/a.*")
then: 'matcher is a RegexRequestMatcher'
matchers.collect {it.class } == [RegexRequestMatcher]
}
def "antMatchers(GET,'/a.*') uses AntPathRequestMatcher"() {
when:
def matchers = registry.antMatchers(HttpMethod.GET, "/a.*")
then: 'matcher is a RegexRequestMatcher'
matchers.collect {it.class } == [AntPathRequestMatcher]
}
def "antMatchers(GET,'/a.*') uses AntPathRequestMatcher"() {
when:
def matchers = registry.antMatchers(HttpMethod.GET, "/a.*")
then: 'matcher is a RegexRequestMatcher'
matchers.collect {it.class } == [AntPathRequestMatcher]
}
def "antMatchers('/a.*') uses AntPathRequestMatcher"() {
when:
def matchers = registry.antMatchers("/a.*")
then: 'matcher is a AntPathRequestMatcher'
matchers.collect {it.class } == [AntPathRequestMatcher]
}
def "antMatchers('/a.*') uses AntPathRequestMatcher"() {
when:
def matchers = registry.antMatchers("/a.*")
then: 'matcher is a AntPathRequestMatcher'
matchers.collect {it.class } == [AntPathRequestMatcher]
}
static class ConcreteAbstractRequestMatcherMappingConfigurer extends AbstractConfigAttributeRequestMatcherRegistry<List<RequestMatcher>> {
List<AccessDecisionVoter> decisionVoters() {
return null;
}
static class ConcreteAbstractRequestMatcherMappingConfigurer extends AbstractConfigAttributeRequestMatcherRegistry<List<RequestMatcher>> {
List<AccessDecisionVoter> decisionVoters() {
return null;
}
List<RequestMatcher> chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
return requestMatchers;
}
}
List<RequestMatcher> chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
return requestMatchers;
}
}
}
@@ -31,23 +31,23 @@ import org.springframework.security.web.authentication.logout.LogoutFilter
*/
class AnonymousConfigurerTests extends BaseSpringSpec {
def "invoke logout twice does not override"() {
when:
loadConfig(InvokeTwiceDoesNotOverride)
then:
findFilter(AnonymousAuthenticationFilter).key == "custom"
}
def "invoke logout twice does not override"() {
when:
loadConfig(InvokeTwiceDoesNotOverride)
then:
findFilter(AnonymousAuthenticationFilter).key == "custom"
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.key("custom")
.and()
.anonymous()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.key("custom")
.and()
.anonymous()
}
}
}
@@ -33,46 +33,46 @@ import org.springframework.security.web.access.channel.SecureChannelProcessor
*/
class ChannelSecurityConfigurerTests extends BaseSpringSpec {
def "requiresChannel ObjectPostProcessor"() {
setup: "initialize the AUTH_FILTER as a mock"
AnyObjectPostProcessor objectPostProcessor = Mock()
when:
HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.build()
def "requiresChannel ObjectPostProcessor"() {
setup: "initialize the AUTH_FILTER as a mock"
AnyObjectPostProcessor objectPostProcessor = Mock()
when:
HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.build()
then: "InsecureChannelProcessor is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as InsecureChannelProcessor) >> {InsecureChannelProcessor o -> o}
and: "SecureChannelProcessor is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as SecureChannelProcessor) >> {SecureChannelProcessor o -> o}
and: "ChannelDecisionManagerImpl is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as ChannelDecisionManagerImpl) >> {ChannelDecisionManagerImpl o -> o}
and: "ChannelProcessingFilter is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as ChannelProcessingFilter) >> {ChannelProcessingFilter o -> o}
}
then: "InsecureChannelProcessor is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as InsecureChannelProcessor) >> {InsecureChannelProcessor o -> o}
and: "SecureChannelProcessor is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as SecureChannelProcessor) >> {SecureChannelProcessor o -> o}
and: "ChannelDecisionManagerImpl is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as ChannelDecisionManagerImpl) >> {ChannelDecisionManagerImpl o -> o}
and: "ChannelProcessingFilter is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as ChannelProcessingFilter) >> {ChannelProcessingFilter o -> o}
}
def "invoke requiresChannel twice does not override"() {
setup:
loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost"
}
def "invoke requiresChannel twice does not override"() {
setup:
loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost"
}
@EnableWebSecurity
static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.requiresChannel()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.requiresChannel()
}
}
}
@@ -42,428 +42,428 @@ import spock.lang.Unroll
*/
class CsrfConfigurerTests extends BaseSpringSpec {
@Unroll
def "csrf applied by default"() {
setup:
loadConfig(CsrfAppliedDefaultConfig)
request.method = httpMethod
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == httpStatus
where:
httpMethod | httpStatus
'POST' | HttpServletResponse.SC_FORBIDDEN
'PUT' | HttpServletResponse.SC_FORBIDDEN
'PATCH' | HttpServletResponse.SC_FORBIDDEN
'DELETE' | HttpServletResponse.SC_FORBIDDEN
'INVALID' | HttpServletResponse.SC_FORBIDDEN
'GET' | HttpServletResponse.SC_OK
'HEAD' | HttpServletResponse.SC_OK
'TRACE' | HttpServletResponse.SC_OK
'OPTIONS' | HttpServletResponse.SC_OK
}
@Unroll
def "csrf applied by default"() {
setup:
loadConfig(CsrfAppliedDefaultConfig)
request.method = httpMethod
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == httpStatus
where:
httpMethod | httpStatus
'POST' | HttpServletResponse.SC_FORBIDDEN
'PUT' | HttpServletResponse.SC_FORBIDDEN
'PATCH' | HttpServletResponse.SC_FORBIDDEN
'DELETE' | HttpServletResponse.SC_FORBIDDEN
'INVALID' | HttpServletResponse.SC_FORBIDDEN
'GET' | HttpServletResponse.SC_OK
'HEAD' | HttpServletResponse.SC_OK
'TRACE' | HttpServletResponse.SC_OK
'OPTIONS' | HttpServletResponse.SC_OK
}
def "csrf default creates CsrfRequestDataValueProcessor"() {
when:
loadConfig(CsrfAppliedDefaultConfig)
then:
context.getBean(RequestDataValueProcessor)
}
def "csrf default creates CsrfRequestDataValueProcessor"() {
when:
loadConfig(CsrfAppliedDefaultConfig)
then:
context.getBean(RequestDataValueProcessor)
}
@EnableWebSecurity
static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
def "csrf disable"() {
setup:
loadConfig(DisableCsrfConfig)
request.method = "POST"
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!findFilter(CsrfFilter)
response.status == HttpServletResponse.SC_OK
}
def "csrf disable"() {
setup:
loadConfig(DisableCsrfConfig)
request.method = "POST"
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!findFilter(CsrfFilter)
response.status == HttpServletResponse.SC_OK
}
@EnableWebSecurity
static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
}
}
def "SEC-2498: Disable CSRF enables RequestCache for any method"() {
setup:
loadConfig(DisableCsrfEnablesRequestCacheConfig)
request.requestURI = '/tosave'
request.method = "POST"
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl
when:
super.setupWeb(request.session)
request.method = "POST"
request.servletPath = '/login'
request.parameters['username'] = ['user'] as String[]
request.parameters['password'] = ['password'] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == 'http://localhost/tosave'
}
def "SEC-2498: Disable CSRF enables RequestCache for any method"() {
setup:
loadConfig(DisableCsrfEnablesRequestCacheConfig)
request.requestURI = '/tosave'
request.method = "POST"
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl
when:
super.setupWeb(request.session)
request.method = "POST"
request.servletPath = '/login'
request.parameters['username'] = ['user'] as String[]
request.parameters['password'] = ['password'] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == 'http://localhost/tosave'
}
@EnableWebSecurity
static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.csrf().disable()
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.csrf().disable()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
setup:
loadConfig(InvalidSessionUrlConfig)
request.session.clearAttributes()
request.setParameter("_csrf","abc")
request.method = "POST"
when: "No existing expected CsrfToken (session times out) and a POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the session timeout page page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/error/sessionError"
when: "Existing expected CsrfToken and a POST (invalid token provided)"
response = new MockHttpServletResponse()
request = new MockHttpServletRequest(session: request.session, method:'POST')
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access Denied occurs"
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
setup:
loadConfig(InvalidSessionUrlConfig)
request.session.clearAttributes()
request.setParameter("_csrf","abc")
request.method = "POST"
when: "No existing expected CsrfToken (session times out) and a POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the session timeout page page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/error/sessionError"
when: "Existing expected CsrfToken and a POST (invalid token provided)"
response = new MockHttpServletResponse()
request = new MockHttpServletRequest(session: request.session, method:'POST')
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access Denied occurs"
response.status == HttpServletResponse.SC_FORBIDDEN
}
@EnableWebSecurity
static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().and()
.sessionManagement()
.invalidSessionUrl("/error/sessionError")
}
}
@EnableWebSecurity
static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().and()
.sessionManagement()
.invalidSessionUrl("/error/sessionError")
}
}
def "csrf requireCsrfProtectionMatcher"() {
setup:
RequireCsrfProtectionMatcherConfig.matcher = Mock(RequestMatcher)
RequireCsrfProtectionMatcherConfig.matcher.matches(_) >>> [false,true]
loadConfig(RequireCsrfProtectionMatcherConfig)
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "csrf requireCsrfProtectionMatcher"() {
setup:
RequireCsrfProtectionMatcherConfig.matcher = Mock(RequestMatcher)
RequireCsrfProtectionMatcherConfig.matcher.matches(_) >>> [false,true]
loadConfig(RequireCsrfProtectionMatcherConfig)
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
@EnableWebSecurity
static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
static RequestMatcher matcher
@EnableWebSecurity
static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
static RequestMatcher matcher
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.requireCsrfProtectionMatcher(matcher)
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.requireCsrfProtectionMatcher(matcher)
}
}
def "csrf csrfTokenRepository"() {
setup:
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
loadConfig(CsrfTokenRepositoryConfig)
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_OK
}
def "csrf csrfTokenRepository"() {
setup:
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
loadConfig(CsrfTokenRepositoryConfig)
clearCsrfToken()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_OK
}
def "csrf clears on logout"() {
setup:
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
loadConfig(CsrfTokenRepositoryConfig)
login()
request.method = "POST"
request.servletPath = "/logout"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
1 * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
}
def "csrf clears on logout"() {
setup:
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
loadConfig(CsrfTokenRepositoryConfig)
login()
request.method = "POST"
request.servletPath = "/logout"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
1 * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
}
def "csrf clears on login"() {
setup:
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
(1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
(1.._) * CsrfTokenRepositoryConfig.repo.generateToken(_) >> csrfToken
loadConfig(CsrfTokenRepositoryConfig)
request.method = "POST"
request.getSession()
request.servletPath = "/login"
request.setParameter("username", "user")
request.setParameter("password", "password")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "/"
(1.._) * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
}
def "csrf clears on login"() {
setup:
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
(1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
(1.._) * CsrfTokenRepositoryConfig.repo.generateToken(_) >> csrfToken
loadConfig(CsrfTokenRepositoryConfig)
request.method = "POST"
request.getSession()
request.servletPath = "/login"
request.setParameter("username", "user")
request.setParameter("password", "password")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "/"
(1.._) * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
}
@EnableWebSecurity
static class CsrfTokenRepositoryConfig extends WebSecurityConfigurerAdapter {
static CsrfTokenRepository repo
@EnableWebSecurity
static class CsrfTokenRepositoryConfig extends WebSecurityConfigurerAdapter {
static CsrfTokenRepository repo
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.csrf()
.csrfTokenRepository(repo)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.csrf()
.csrfTokenRepository(repo)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "csrf access denied handler"() {
setup:
AccessDeniedHandlerConfig.deniedHandler = Mock(AccessDeniedHandler)
1 * AccessDeniedHandlerConfig.deniedHandler.handle(_, _, _)
loadConfig(AccessDeniedHandlerConfig)
clearCsrfToken()
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
def "csrf access denied handler"() {
setup:
AccessDeniedHandlerConfig.deniedHandler = Mock(AccessDeniedHandler)
1 * AccessDeniedHandlerConfig.deniedHandler.handle(_, _, _)
loadConfig(AccessDeniedHandlerConfig)
clearCsrfToken()
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
@EnableWebSecurity
static class AccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@EnableWebSecurity
static class AccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.accessDeniedHandler(deniedHandler)
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.accessDeniedHandler(deniedHandler)
}
}
def "formLogin requires CSRF token"() {
setup:
loadConfig(FormLoginConfig)
clearCsrfToken()
request.setParameter("username", "user")
request.setParameter("password", "password")
request.servletPath = "/login"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
currentAuthentication == null
}
def "formLogin requires CSRF token"() {
setup:
loadConfig(FormLoginConfig)
clearCsrfToken()
request.setParameter("username", "user")
request.setParameter("password", "password")
request.servletPath = "/login"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
currentAuthentication == null
}
@EnableWebSecurity
static class FormLoginConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@EnableWebSecurity
static class FormLoginConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
}
}
def "logout requires CSRF token"() {
setup:
loadConfig(LogoutConfig)
clearCsrfToken()
login()
request.servletPath = "/logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "logout is not allowed and user is still authenticated"
response.status == HttpServletResponse.SC_FORBIDDEN
currentAuthentication != null
}
def "logout requires CSRF token"() {
setup:
loadConfig(LogoutConfig)
clearCsrfToken()
login()
request.servletPath = "/logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "logout is not allowed and user is still authenticated"
response.status == HttpServletResponse.SC_FORBIDDEN
currentAuthentication != null
}
def "SEC-2543: CSRF means logout requires POST"() {
setup:
loadConfig(LogoutConfig)
login()
request.servletPath = "/logout"
request.method = "GET"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "logout with GET is not performed"
currentAuthentication != null
}
def "SEC-2543: CSRF means logout requires POST"() {
setup:
loadConfig(LogoutConfig)
login()
request.servletPath = "/logout"
request.method = "GET"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "logout with GET is not performed"
currentAuthentication != null
}
@EnableWebSecurity
static class LogoutConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@EnableWebSecurity
static class LogoutConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
}
}
def "CSRF can explicitly enable GET for logout"() {
setup:
loadConfig(LogoutAllowsGetConfig)
login()
request.servletPath = "/logout"
request.method = "GET"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "logout with GET is not performed"
currentAuthentication == null
}
def "CSRF can explicitly enable GET for logout"() {
setup:
loadConfig(LogoutAllowsGetConfig)
login()
request.servletPath = "/logout"
request.method = "GET"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "logout with GET is not performed"
currentAuthentication == null
}
@EnableWebSecurity
static class LogoutAllowsGetConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@EnableWebSecurity
static class LogoutAllowsGetConfig extends WebSecurityConfigurerAdapter {
static AccessDeniedHandler deniedHandler
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
}
}
def "csrf disables POST requests from RequestCache"() {
setup:
CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
request.servletPath = "/some-url"
request.requestURI = "/some-url"
request.method = "POST"
when: "CSRF passes and our session times out"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "csrf disables POST requests from RequestCache"() {
setup:
CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
request.servletPath = "/some-url"
request.requestURI = "/some-url"
request.method = "POST"
when: "CSRF passes and our session times out"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "csrf enables GET requests with RequestCache"() {
setup:
CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
request.servletPath = "/some-url"
request.requestURI = "/some-url"
request.method = "GET"
when: "CSRF passes and our session times out"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to original URL since it was a GET"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/some-url"
}
def "csrf enables GET requests with RequestCache"() {
setup:
CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
request.servletPath = "/some-url"
request.requestURI = "/some-url"
request.method = "GET"
when: "CSRF passes and our session times out"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to original URL since it was a GET"
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/some-url"
}
@EnableWebSecurity
static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
static CsrfTokenRepository repo
@EnableWebSecurity
static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
static CsrfTokenRepository repo
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf()
.csrfTokenRepository(repo)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf()
.csrfTokenRepository(repo)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def 'SEC-2749: requireCsrfProtectionMatcher null'() {
when:
new CsrfConfigurer<>().requireCsrfProtectionMatcher(null)
then:
thrown(IllegalArgumentException)
}
def 'SEC-2749: requireCsrfProtectionMatcher null'() {
when:
new CsrfConfigurer<>().requireCsrfProtectionMatcher(null)
then:
thrown(IllegalArgumentException)
}
def clearCsrfToken() {
request.removeAllParameters()
}
def clearCsrfToken() {
request.removeAllParameters()
}
}
@@ -54,103 +54,103 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher
*/
class DefaultFiltersTests extends BaseSpringSpec {
def "Default the WebSecurityConfigurerAdapter"() {
when:
context = new AnnotationConfigApplicationContext(FilterChainProxyBuilderMissingConfig)
then:
context.getBean(FilterChainProxy) != null
}
def "Default the WebSecurityConfigurerAdapter"() {
when:
context = new AnnotationConfigApplicationContext(FilterChainProxyBuilderMissingConfig)
then:
context.getBean(FilterChainProxy) != null
}
@EnableWebSecurity
static class FilterChainProxyBuilderMissingConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@EnableWebSecurity
static class FilterChainProxyBuilderMissingConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@EnableWebSecurity
static class FilterChainProxyBuilderNoSecurityFilterBuildersConfig {
@Bean
public WebSecurity filterChainProxyBuilder(ObjectPostProcessor<Object> opp) {
new WebSecurity(opp)
.ignoring()
.antMatchers("/resources/**")
}
}
@EnableWebSecurity
static class FilterChainProxyBuilderNoSecurityFilterBuildersConfig {
@Bean
public WebSecurity filterChainProxyBuilder(ObjectPostProcessor<Object> opp) {
new WebSecurity(opp)
.ignoring()
.antMatchers("/resources/**")
}
}
def "null WebInvocationPrivilegeEvaluator"() {
when:
context = new AnnotationConfigApplicationContext(NullWebInvocationPrivilegeEvaluatorConfig)
then:
List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
filterChains.size() == 1
filterChains[0].requestMatcher instanceof AnyRequestMatcher
filterChains[0].filters.size() == 1
filterChains[0].filters.find { it instanceof UsernamePasswordAuthenticationFilter }
}
def "null WebInvocationPrivilegeEvaluator"() {
when:
context = new AnnotationConfigApplicationContext(NullWebInvocationPrivilegeEvaluatorConfig)
then:
List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
filterChains.size() == 1
filterChains[0].requestMatcher instanceof AnyRequestMatcher
filterChains[0].filters.size() == 1
filterChains[0].filters.find { it instanceof UsernamePasswordAuthenticationFilter }
}
@EnableWebSecurity
static class NullWebInvocationPrivilegeEvaluatorConfig extends BaseWebConfig {
NullWebInvocationPrivilegeEvaluatorConfig() {
super(true)
}
@EnableWebSecurity
static class NullWebInvocationPrivilegeEvaluatorConfig extends BaseWebConfig {
NullWebInvocationPrivilegeEvaluatorConfig() {
super(true)
}
protected void configure(HttpSecurity http) {
http.formLogin()
}
}
protected void configure(HttpSecurity http) {
http.formLogin()
}
}
def "FilterChainProxyBuilder ignoring resources"() {
when:
loadConfig(FilterChainProxyBuilderIgnoringConfig)
then:
List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
filterChains.size() == 2
filterChains[0].requestMatcher.pattern == '/resources/**'
filterChains[0].filters.empty
filterChains[1].requestMatcher instanceof AnyRequestMatcher
filterChains[1].filters.collect { it.class } ==
[WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, RequestCacheAwareFilter,
SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, SessionManagementFilter,
ExceptionTranslationFilter, FilterSecurityInterceptor ]
}
def "FilterChainProxyBuilder ignoring resources"() {
when:
loadConfig(FilterChainProxyBuilderIgnoringConfig)
then:
List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
filterChains.size() == 2
filterChains[0].requestMatcher.pattern == '/resources/**'
filterChains[0].filters.empty
filterChains[1].requestMatcher instanceof AnyRequestMatcher
filterChains[1].filters.collect { it.class } ==
[WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, RequestCacheAwareFilter,
SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, SessionManagementFilter,
ExceptionTranslationFilter, FilterSecurityInterceptor ]
}
@EnableWebSecurity
static class FilterChainProxyBuilderIgnoringConfig extends BaseWebConfig {
@Override
public void configure(WebSecurity builder) throws Exception {
builder
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER");
}
}
@EnableWebSecurity
static class FilterChainProxyBuilderIgnoringConfig extends BaseWebConfig {
@Override
public void configure(WebSecurity builder) throws Exception {
builder
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER");
}
}
def "DefaultFilters.permitAll()"() {
when:
loadConfig(DefaultFiltersConfigPermitAll)
MockHttpServletResponse response = new MockHttpServletResponse()
request = new MockHttpServletRequest(servletPath : uri, queryString: query, method:"POST")
setupCsrf()
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
then:
response.redirectedUrl == "/login?logout"
where:
uri | query
"/logout" | null
}
when:
loadConfig(DefaultFiltersConfigPermitAll)
MockHttpServletResponse response = new MockHttpServletResponse()
request = new MockHttpServletRequest(servletPath : uri, queryString: query, method:"POST")
setupCsrf()
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
then:
response.redirectedUrl == "/login?logout"
where:
uri | query
"/logout" | null
}
@EnableWebSecurity
static class DefaultFiltersConfigPermitAll extends BaseWebConfig {
protected void configure(HttpSecurity http) {
}
}
@EnableWebSecurity
static class DefaultFiltersConfigPermitAll extends BaseWebConfig {
protected void configure(HttpSecurity http) {
}
}
}
@@ -42,295 +42,295 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera
*
*/
public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
def "http/form-login default login generating page"() {
setup:
loadConfig(DefaultLoginPageConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
findFilter(DefaultLoginPageGeneratingFilter)
response.getRedirectedUrl() == "http://localhost/login"
when: "request the login page"
super.setup()
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def "http/form-login default login generating page"() {
setup:
loadConfig(DefaultLoginPageConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
findFilter(DefaultLoginPageGeneratingFilter)
response.getRedirectedUrl() == "http://localhost/login"
when: "request the login page"
super.setup()
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "request the error page"
HttpSession session = request.session
super.setup()
request.session = session
request.requestURI = "/login"
request.queryString = "error"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "request the error page"
HttpSession session = request.session
super.setup()
request.session = session
request.requestURI = "/login"
request.queryString = "error"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<p><font color='red'>Your login attempt was not successful, try again.<br/><br/>Reason: Bad credentials</font></p><h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
def "logout success renders"() {
setup:
loadConfig(DefaultLoginPageConfig)
when: "logout success"
request.requestURI = "/login"
request.queryString = "logout"
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default success page"
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def "logout success renders"() {
setup:
loadConfig(DefaultLoginPageConfig)
when: "logout success"
request.requestURI = "/login"
request.queryString = "logout"
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default success page"
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<p><font color='green'>You have been logged out</font></p><h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
}
}
@Configuration
static class DefaultLoginPageConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
}
}
@Configuration
static class DefaultLoginPageConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
}
}
def "custom logout success handler prevents rendering"() {
setup:
loadConfig(DefaultLoginPageCustomLogoutSuccessHandlerConfig)
when: "logout success"
request.requestURI = "/login"
request.queryString = "logout"
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "default success page is NOT rendered (application is in charge of it)"
response.getContentAsString() == ""
}
def "custom logout success handler prevents rendering"() {
setup:
loadConfig(DefaultLoginPageCustomLogoutSuccessHandlerConfig)
when: "logout success"
request.requestURI = "/login"
request.queryString = "logout"
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "default success page is NOT rendered (application is in charge of it)"
response.getContentAsString() == ""
}
@Configuration
static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.logout()
.logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler())
.and()
.formLogin()
}
}
@Configuration
static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.logout()
.logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler())
.and()
.formLogin()
}
}
def "custom logout success url prevents rendering"() {
setup:
loadConfig(DefaultLoginPageCustomLogoutConfig)
when: "logout success"
request.requestURI = "/login"
request.queryString = "logout"
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "default success page is NOT rendered (application is in charge of it)"
response.getContentAsString() == ""
}
def "custom logout success url prevents rendering"() {
setup:
loadConfig(DefaultLoginPageCustomLogoutConfig)
when: "logout success"
request.requestURI = "/login"
request.queryString = "logout"
request.method = "GET"
springSecurityFilterChain.doFilter(request,response,chain)
then: "default success page is NOT rendered (application is in charge of it)"
response.getContentAsString() == ""
}
@Configuration
static class DefaultLoginPageCustomLogoutConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.and()
.formLogin()
}
}
@Configuration
static class DefaultLoginPageCustomLogoutConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.and()
.formLogin()
}
}
def "http/form-login default login with remember me"() {
setup:
loadConfig(DefaultLoginPageWithRememberMeConfig)
when: "request the login page"
super.setup()
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def "http/form-login default login with remember me"() {
setup:
loadConfig(DefaultLoginPageWithRememberMeConfig)
when: "request the login page"
super.setup()
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form></body></html>"""
}
}
@Configuration
static class DefaultLoginPageWithRememberMeConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
}
@Configuration
static class DefaultLoginPageWithRememberMeConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
}
def "http/form-login default login with openid"() {
setup:
loadConfig(DefaultLoginPageWithOpenIDConfig)
when: "request the login page"
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
def "http/form-login default login with openid"() {
setup:
loadConfig(DefaultLoginPageWithOpenIDConfig)
when: "request the login page"
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
<table>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</form></body></html>"""
}
}
@Configuration
static class DefaultLoginPageWithOpenIDConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
}
}
@Configuration
static class DefaultLoginPageWithOpenIDConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
}
}
def "http/form-login default login with openid, form login, and rememberme"() {
setup:
loadConfig(DefaultLoginPageWithFormLoginOpenIDRememberMeConfig)
when: "request the login page"
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def "http/form-login default login with openid, form login, and rememberme"() {
setup:
loadConfig(DefaultLoginPageWithFormLoginOpenIDRememberMeConfig)
when: "request the login page"
request.requestURI = "/login"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</table>
</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
<table>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td><input type='checkbox' name='remember-me'></td><td>Remember me on this computer.</td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
</form></body></html>"""
}
}
@Configuration
static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.rememberMe()
.and()
.formLogin()
.and()
.openidLogin()
}
}
@Configuration
static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.rememberMe()
.and()
.formLogin()
.and()
.openidLogin()
}
}
def "default login with custom AuthenticationEntryPoint"() {
when:
loadConfig(DefaultLoginWithCustomAuthenticationEntryPointConfig)
then:
!findFilter(DefaultLoginPageGeneratingFilter)
}
def "default login with custom AuthenticationEntryPoint"() {
when:
loadConfig(DefaultLoginWithCustomAuthenticationEntryPointConfig)
then:
!findFilter(DefaultLoginPageGeneratingFilter)
}
@Configuration
static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
.and()
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
}
}
@Configuration
static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
.and()
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
}
}
def "DefaultLoginPage ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor objectPostProcessor = Mock()
when:
HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
DefaultLoginPageConfigurer defaultLoginConfig = new DefaultLoginPageConfigurer([builder:http])
defaultLoginConfig.addObjectPostProcessor(objectPostProcessor)
http
// must set builder manually due to groovy not selecting correct method
.apply(defaultLoginConfig).and()
.exceptionHandling()
.and()
.formLogin()
.and()
.build()
def "DefaultLoginPage ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor objectPostProcessor = Mock()
when:
HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
DefaultLoginPageConfigurer defaultLoginConfig = new DefaultLoginPageConfigurer([builder:http])
defaultLoginConfig.addObjectPostProcessor(objectPostProcessor)
http
// must set builder manually due to groovy not selecting correct method
.apply(defaultLoginConfig).and()
.exceptionHandling()
.and()
.formLogin()
.and()
.build()
then: "DefaultLoginPageGeneratingFilter is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as DefaultLoginPageGeneratingFilter) >> {DefaultLoginPageGeneratingFilter o -> o}
1 * objectPostProcessor.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
1 * objectPostProcessor.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
1 * objectPostProcessor.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
}
then: "DefaultLoginPageGeneratingFilter is registered with LifecycleManager"
1 * objectPostProcessor.postProcess(_ as DefaultLoginPageGeneratingFilter) >> {DefaultLoginPageGeneratingFilter o -> o}
1 * objectPostProcessor.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
1 * objectPostProcessor.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
1 * objectPostProcessor.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
}
}
@@ -46,153 +46,153 @@ import spock.lang.Unroll
*/
class ExceptionHandlingConfigurerTests extends BaseSpringSpec {
def "exception ObjectPostProcessor"() {
setup: "initialize the AUTH_FILTER as a mock"
AnyObjectPostProcessor opp = Mock()
when:
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
http
.exceptionHandling()
.and()
.build()
def "exception ObjectPostProcessor"() {
setup: "initialize the AUTH_FILTER as a mock"
AnyObjectPostProcessor opp = Mock()
when:
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
http
.exceptionHandling()
.and()
.build()
then: "ExceptionTranslationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
}
then: "ExceptionTranslationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
}
@Unroll
def "SEC-2199: defaultEntryPoint for httpBasic and formLogin"(String acceptHeader, int httpStatus) {
setup:
loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
when:
request.addHeader("Accept", acceptHeader)
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == httpStatus
where:
acceptHeader | httpStatus
MediaType.APPLICATION_XHTML_XML_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.IMAGE_GIF_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.IMAGE_JPEG_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.IMAGE_PNG_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.TEXT_HTML_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.TEXT_PLAIN_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.APPLICATION_ATOM_XML_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_FORM_URLENCODED_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_JSON_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_OCTET_STREAM_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_XML_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.MULTIPART_FORM_DATA_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.TEXT_XML_VALUE | HttpServletResponse.SC_UNAUTHORIZED
}
@Unroll
def "SEC-2199: defaultEntryPoint for httpBasic and formLogin"(String acceptHeader, int httpStatus) {
setup:
loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
when:
request.addHeader("Accept", acceptHeader)
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == httpStatus
where:
acceptHeader | httpStatus
MediaType.APPLICATION_XHTML_XML_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.IMAGE_GIF_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.IMAGE_JPEG_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.IMAGE_PNG_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.TEXT_HTML_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.TEXT_PLAIN_VALUE | HttpServletResponse.SC_MOVED_TEMPORARILY
MediaType.APPLICATION_ATOM_XML_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_FORM_URLENCODED_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_JSON_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_OCTET_STREAM_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.APPLICATION_XML_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.MULTIPART_FORM_DATA_VALUE | HttpServletResponse.SC_UNAUTHORIZED
MediaType.TEXT_XML_VALUE | HttpServletResponse.SC_UNAUTHORIZED
}
def "ContentNegotiationStrategy defaults to HeaderContentNegotiationStrategy"() {
when:
loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
then:
delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy.class} == [HeaderContentNegotiationStrategy,HeaderContentNegotiationStrategy]
}
def "ContentNegotiationStrategy defaults to HeaderContentNegotiationStrategy"() {
when:
loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
then:
delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy.class} == [HeaderContentNegotiationStrategy,HeaderContentNegotiationStrategy]
}
@EnableWebSecurity
static class HttpBasicAndFormLoginEntryPointsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HttpBasicAndFormLoginEntryPointsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.formLogin()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.formLogin()
}
}
def "ContentNegotiationStrategy overrides with @Bean"() {
setup:
OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
when:
loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
then:
delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy} == [OverrideContentNegotiationStrategySharedObjectConfig.CNS,OverrideContentNegotiationStrategySharedObjectConfig.CNS]
}
def "ContentNegotiationStrategy overrides with @Bean"() {
setup:
OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
when:
loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
then:
delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy} == [OverrideContentNegotiationStrategySharedObjectConfig.CNS,OverrideContentNegotiationStrategySharedObjectConfig.CNS]
}
def "Override ContentNegotiationStrategy with @Bean"() {
setup:
OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
when:
loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
then:
context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
}
def "Override ContentNegotiationStrategy with @Bean"() {
setup:
OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
when:
loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
then:
context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
}
@EnableWebSecurity
static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
static ContentNegotiationStrategy CNS
@EnableWebSecurity
static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
static ContentNegotiationStrategy CNS
@Bean
public ContentNegotiationStrategy cns() {
return CNS
}
}
@Bean
public ContentNegotiationStrategy cns() {
return CNS
}
}
def "delegatingAuthenticationEntryPoint.defaultEntryPoint is LoginUrlAuthenticationEntryPoint when using DefaultHttpConf"() {
when:
loadConfig(DefaultHttpConf)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.class == LoginUrlAuthenticationEntryPoint
}
def "delegatingAuthenticationEntryPoint.defaultEntryPoint is LoginUrlAuthenticationEntryPoint when using DefaultHttpConf"() {
when:
loadConfig(DefaultHttpConf)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.class == LoginUrlAuthenticationEntryPoint
}
@EnableWebSecurity
static class DefaultHttpConf extends WebSecurityConfigurerAdapter {
}
@EnableWebSecurity
static class DefaultHttpConf extends WebSecurityConfigurerAdapter {
}
def "delegatingAuthenticationEntryPoint.defaultEntryPoint is BasicAuthenticationEntryPoint when httpBasic before formLogin"() {
when:
loadConfig(BasicAuthenticationEntryPointBeforeFormLoginConf)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.defaultEntryPoint.class == BasicAuthenticationEntryPoint
}
def "delegatingAuthenticationEntryPoint.defaultEntryPoint is BasicAuthenticationEntryPoint when httpBasic before formLogin"() {
when:
loadConfig(BasicAuthenticationEntryPointBeforeFormLoginConf)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.defaultEntryPoint.class == BasicAuthenticationEntryPoint
}
@EnableWebSecurity
static class BasicAuthenticationEntryPointBeforeFormLoginConf extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.formLogin()
}
}
@EnableWebSecurity
static class BasicAuthenticationEntryPointBeforeFormLoginConf extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.formLogin()
}
}
def "invoke exceptionHandling twice does not override"() {
setup:
InvokeTwiceDoesNotOverrideConfig.AEP = Mock(AuthenticationEntryPoint)
when:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.AEP
}
def "invoke exceptionHandling twice does not override"() {
setup:
InvokeTwiceDoesNotOverrideConfig.AEP = Mock(AuthenticationEntryPoint)
when:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.AEP
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint AEP
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(AEP)
.and()
.exceptionHandling()
}
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint AEP
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(AEP)
.and()
.exceptionHandling()
}
}
}
@@ -37,494 +37,494 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
public class ExpressionUrlAuthorizationConfigurerTests extends BaseSpringSpec {
def "hasAnyAuthority('ROLE_USER')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
then:
expression == "hasAnyAuthority('ROLE_USER')"
}
def "hasAnyAuthority('ROLE_USER')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
then:
expression == "hasAnyAuthority('ROLE_USER')"
}
def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
then:
expression == "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"
}
def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
then:
expression == "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"
}
def "hasAnyRole('USER')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER")
then:
expression == "hasAnyRole('ROLE_USER')"
}
def "hasAnyRole('USER')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER")
then:
expression == "hasAnyRole('ROLE_USER')"
}
def "hasAnyRole('USER','ADMIN')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
then:
expression == "hasAnyRole('ROLE_USER','ROLE_ADMIN')"
}
def "hasAnyRole('USER','ADMIN')"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
then:
expression == "hasAnyRole('ROLE_USER','ROLE_ADMIN')"
}
def "hasRole('ROLE_USER') is rejected due to starting with ROLE_"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasRole("ROLE_USER")
then:
IllegalArgumentException e = thrown()
e.message == "role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'"
}
def "hasRole('ROLE_USER') is rejected due to starting with ROLE_"() {
when:
def expression = ExpressionUrlAuthorizationConfigurer.hasRole("ROLE_USER")
then:
IllegalArgumentException e = thrown()
e.message == "role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'"
}
def "authorizeRequests() uses AffirmativeBased AccessDecisionManager"() {
when: "Load Config with no specific AccessDecisionManager"
loadConfig(NoSpecificAccessDecessionManagerConfig)
then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
}
def "authorizeRequests() uses AffirmativeBased AccessDecisionManager"() {
when: "Load Config with no specific AccessDecisionManager"
loadConfig(NoSpecificAccessDecessionManagerConfig)
then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
}
@EnableWebSecurity
static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
}
}
@EnableWebSecurity
static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
}
}
def "authorizeRequests() no requests"() {
when: "Load Config with no requests"
loadConfig(NoRequestsConfig)
then: "A meaningful exception is thrown"
BeanCreationException success = thrown()
success.message.contains "At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"
}
def "authorizeRequests() no requests"() {
when: "Load Config with no requests"
loadConfig(NoRequestsConfig)
then: "A meaningful exception is thrown"
BeanCreationException success = thrown()
success.message.contains "At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"
}
@EnableWebSecurity
static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
}
}
@EnableWebSecurity
static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
}
}
def "authorizeRequests() incomplete mapping"() {
when: "Load Config with incomplete mapping"
loadConfig(IncompleteMappingConfig)
then: "A meaningful exception is thrown"
BeanCreationException success = thrown()
success.message.contains "An incomplete mapping was found for "
}
def "authorizeRequests() incomplete mapping"() {
when: "Load Config with incomplete mapping"
loadConfig(IncompleteMappingConfig)
then: "A meaningful exception is thrown"
BeanCreationException success = thrown()
success.message.contains "An incomplete mapping was found for "
}
@EnableWebSecurity
static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/a").authenticated()
.anyRequest()
}
}
@EnableWebSecurity
static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/a").authenticated()
.anyRequest()
}
}
def "authorizeRequests() hasAuthority"() {
setup:
loadConfig(HasAuthorityConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login()
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login("user","ROLE_INVALID")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "authorizeRequests() hasAuthority"() {
setup:
loadConfig(HasAuthorityConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login()
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login("user","ROLE_INVALID")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
@EnableWebSecurity
static class HasAuthorityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasAuthority("ROLE_USER")
}
}
@EnableWebSecurity
static class HasAuthorityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasAuthority("ROLE_USER")
}
}
def "authorizeRequests() hasAnyAuthority"() {
setup:
loadConfig(HasAnyAuthorityConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login("user","ROLE_ADMIN")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login("user","ROLE_DBA")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login("user","ROLE_INVALID")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "authorizeRequests() hasAnyAuthority"() {
setup:
loadConfig(HasAnyAuthorityConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login("user","ROLE_ADMIN")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login("user","ROLE_DBA")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login("user","ROLE_INVALID")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
@EnableWebSecurity
static class HasAnyAuthorityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasAnyAuthority("ROLE_ADMIN","ROLE_DBA")
}
}
@EnableWebSecurity
static class HasAnyAuthorityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasAnyAuthority("ROLE_ADMIN","ROLE_DBA")
}
}
def "authorizeRequests() hasIpAddress"() {
setup:
loadConfig(HasIpAddressConfig)
when:
request.remoteAddr = "192.168.1.1"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
request.remoteAddr = "192.168.1.0"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
def "authorizeRequests() hasIpAddress"() {
setup:
loadConfig(HasIpAddressConfig)
when:
request.remoteAddr = "192.168.1.1"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
request.remoteAddr = "192.168.1.0"
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
@EnableWebSecurity
static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasIpAddress("192.168.1.0")
}
}
@EnableWebSecurity
static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().hasIpAddress("192.168.1.0")
}
}
def "authorizeRequests() anonymous"() {
setup:
loadConfig(AnonymousConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login()
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "authorizeRequests() anonymous"() {
setup:
loadConfig(AnonymousConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login()
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
@EnableWebSecurity
static class AnonymousConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().anonymous()
}
}
@EnableWebSecurity
static class AnonymousConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().anonymous()
}
}
def "authorizeRequests() rememberMe"() {
setup:
loadConfig(RememberMeConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
def "authorizeRequests() rememberMe"() {
setup:
loadConfig(RememberMeConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
@EnableWebSecurity
static class RememberMeConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().rememberMe()
}
@EnableWebSecurity
static class RememberMeConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().rememberMe()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "authorizeRequests() denyAll"() {
setup:
loadConfig(DenyAllConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "authorizeRequests() denyAll"() {
setup:
loadConfig(DenyAllConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
@EnableWebSecurity
static class DenyAllConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().denyAll()
}
}
@EnableWebSecurity
static class DenyAllConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().denyAll()
}
}
def "authorizeRequests() not denyAll"() {
setup:
loadConfig(NotDenyAllConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
def "authorizeRequests() not denyAll"() {
setup:
loadConfig(NotDenyAllConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
@EnableWebSecurity
static class NotDenyAllConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().not().denyAll()
}
}
@EnableWebSecurity
static class NotDenyAllConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().not().denyAll()
}
}
def "authorizeRequests() fullyAuthenticated"() {
setup:
loadConfig(FullyAuthenticatedConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
when:
super.setup()
login()
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
def "authorizeRequests() fullyAuthenticated"() {
setup:
loadConfig(FullyAuthenticatedConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when:
super.setup()
login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
when:
super.setup()
login()
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
}
@EnableWebSecurity
static class FullyAuthenticatedConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().fullyAuthenticated()
}
@EnableWebSecurity
static class FullyAuthenticatedConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().fullyAuthenticated()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "authorizeRequests() access"() {
setup:
loadConfig(AccessConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is granted due to GET"
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login()
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is granted due to role"
response.status == HttpServletResponse.SC_OK
when:
super.setup()
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is denied"
response.status == HttpServletResponse.SC_UNAUTHORIZED
}
def "authorizeRequests() access"() {
setup:
loadConfig(AccessConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is granted due to GET"
response.status == HttpServletResponse.SC_OK
when:
super.setup()
login()
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is granted due to role"
response.status == HttpServletResponse.SC_OK
when:
super.setup()
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is denied"
response.status == HttpServletResponse.SC_UNAUTHORIZED
}
@EnableWebSecurity
static class AccessConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().access("hasRole('ROLE_USER') or request.method == 'GET'")
}
@EnableWebSecurity
static class AccessConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.and()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().access("hasRole('ROLE_USER') or request.method == 'GET'")
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "invoke authorizeUrls twice does not reset"() {
setup:
loadConfig(InvokeTwiceDoesNotResetConfig)
when:
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is denied"
response.status == HttpServletResponse.SC_UNAUTHORIZED
}
def "invoke authorizeUrls twice does not reset"() {
setup:
loadConfig(InvokeTwiceDoesNotResetConfig)
when:
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "Access is denied"
response.status == HttpServletResponse.SC_UNAUTHORIZED
}
@EnableWebSecurity
static class InvokeTwiceDoesNotResetConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.authorizeRequests()
}
@EnableWebSecurity
static class InvokeTwiceDoesNotResetConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.authorizeRequests()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
def "All Properties are accessible and chain properly"() {
when:
loadConfig(AllPropertiesWorkConfig)
then:
noExceptionThrown()
}
def "All Properties are accessible and chain properly"() {
when:
loadConfig(AllPropertiesWorkConfig)
then:
noExceptionThrown()
}
def "AuthorizedRequests withPostProcessor"() {
setup:
ApplicationListener al = Mock()
AuthorizedRequestsWithPostProcessorConfig.AL = al
loadConfig(AuthorizedRequestsWithPostProcessorConfig)
when:
springSecurityFilterChain.doFilter(request, response, chain)
then:
1 * al.onApplicationEvent(_ as AuthorizedEvent)
}
def "AuthorizedRequests withPostProcessor"() {
setup:
ApplicationListener al = Mock()
AuthorizedRequestsWithPostProcessorConfig.AL = al
loadConfig(AuthorizedRequestsWithPostProcessorConfig)
when:
springSecurityFilterChain.doFilter(request, response, chain)
then:
1 * al.onApplicationEvent(_ as AuthorizedEvent)
}
def "Use @permission.check in access"() {
setup:
loadConfig(UseBeansInExpressions)
when: "invoke standard expression that denies access"
login()
request.servletPath = "/admin/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get forbidden"
response.status == HttpServletResponse.SC_FORBIDDEN
when: "invoke standard expression that allows access"
super.setup()
login()
request.servletPath = "/user/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get ok"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that allows access"
super.setup()
login()
request.servletPath = "/allow/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression allows access"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that denies access"
super.setup()
login()
request.servletPath = "/deny/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression denies access"
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "Use @permission.check in access"() {
setup:
loadConfig(UseBeansInExpressions)
when: "invoke standard expression that denies access"
login()
request.servletPath = "/admin/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get forbidden"
response.status == HttpServletResponse.SC_FORBIDDEN
when: "invoke standard expression that allows access"
super.setup()
login()
request.servletPath = "/user/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get ok"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that allows access"
super.setup()
login()
request.servletPath = "/allow/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression allows access"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that denies access"
super.setup()
login()
request.servletPath = "/deny/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression denies access"
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "Use custom expressionroot in access"() {
setup:
loadConfig(CustomExpressionRootConfig)
when: "invoke standard expression that denies access"
login()
request.servletPath = "/admin/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get forbidden"
response.status == HttpServletResponse.SC_FORBIDDEN
when: "invoke standard expression that allows access"
super.setup()
login()
request.servletPath = "/user/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get ok"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that allows access"
super.setup()
login()
request.servletPath = "/allow/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression allows access"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that denies access"
super.setup()
login()
request.servletPath = "/deny/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression denies access"
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "Use custom expressionroot in access"() {
setup:
loadConfig(CustomExpressionRootConfig)
when: "invoke standard expression that denies access"
login()
request.servletPath = "/admin/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get forbidden"
response.status == HttpServletResponse.SC_FORBIDDEN
when: "invoke standard expression that allows access"
super.setup()
login()
request.servletPath = "/user/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "standard expression works - get ok"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that allows access"
super.setup()
login()
request.servletPath = "/allow/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression allows access"
response.status == HttpServletResponse.SC_OK
when: "invoke custom bean as expression that denies access"
super.setup()
login()
request.servletPath = "/deny/1"
springSecurityFilterChain.doFilter(request, response, chain)
then: "custom bean expression denies access"
response.status == HttpServletResponse.SC_FORBIDDEN
}
}
@@ -56,266 +56,266 @@ import spock.lang.Unroll
* @author Rob Winch
*/
class FormLoginConfigurerTests extends BaseSpringSpec {
def "Form Login"() {
when: "load formLogin()"
context = new AnnotationConfigApplicationContext(FormLoginConfig)
def "Form Login"() {
when: "load formLogin()"
context = new AnnotationConfigApplicationContext(FormLoginConfig)
then: "FilterChains configured correctly"
def filterChains = filterChains()
filterChains.size() == 2
filterChains[0].requestMatcher.pattern == '/resources/**'
filterChains[0].filters.empty
filterChains[1].requestMatcher instanceof AnyRequestMatcher
filterChains[1].filters.collect { it.class.name.contains('$') ? it.class.superclass : it.class } ==
[WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, UsernamePasswordAuthenticationFilter,
RequestCacheAwareFilter, SecurityContextHolderAwareRequestFilter,
AnonymousAuthenticationFilter, SessionManagementFilter, ExceptionTranslationFilter, FilterSecurityInterceptor ]
then: "FilterChains configured correctly"
def filterChains = filterChains()
filterChains.size() == 2
filterChains[0].requestMatcher.pattern == '/resources/**'
filterChains[0].filters.empty
filterChains[1].requestMatcher instanceof AnyRequestMatcher
filterChains[1].filters.collect { it.class.name.contains('$') ? it.class.superclass : it.class } ==
[WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, UsernamePasswordAuthenticationFilter,
RequestCacheAwareFilter, SecurityContextHolderAwareRequestFilter,
AnonymousAuthenticationFilter, SessionManagementFilter, ExceptionTranslationFilter, FilterSecurityInterceptor ]
and: "UsernamePasswordAuthentictionFilter is configured correctly"
UsernamePasswordAuthenticationFilter authFilter = findFilter(UsernamePasswordAuthenticationFilter,1)
authFilter.usernameParameter == "username"
authFilter.passwordParameter == "password"
authFilter.failureHandler.defaultFailureUrl == "/login?error"
authFilter.successHandler.defaultTargetUrl == "/"
authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "POST"), new MockHttpServletResponse())
!authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "GET"), new MockHttpServletResponse())
and: "UsernamePasswordAuthentictionFilter is configured correctly"
UsernamePasswordAuthenticationFilter authFilter = findFilter(UsernamePasswordAuthenticationFilter,1)
authFilter.usernameParameter == "username"
authFilter.passwordParameter == "password"
authFilter.failureHandler.defaultFailureUrl == "/login?error"
authFilter.successHandler.defaultTargetUrl == "/"
authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "POST"), new MockHttpServletResponse())
!authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "GET"), new MockHttpServletResponse())
and: "SessionFixationProtectionStrategy is configured correctly"
SessionFixationProtectionStrategy sessionStrategy = ReflectionTestUtils.getField(authFilter,"sessionStrategy").delegateStrategies.find { SessionFixationProtectionStrategy }
sessionStrategy.migrateSessionAttributes
and: "SessionFixationProtectionStrategy is configured correctly"
SessionFixationProtectionStrategy sessionStrategy = ReflectionTestUtils.getField(authFilter,"sessionStrategy").delegateStrategies.find { SessionFixationProtectionStrategy }
sessionStrategy.migrateSessionAttributes
and: "Exception handling is configured correctly"
AuthenticationEntryPoint authEntryPoint = filterChains[1].filters.find { it instanceof ExceptionTranslationFilter}.authenticationEntryPoint
MockHttpServletResponse response = new MockHttpServletResponse()
authEntryPoint.commence(new MockHttpServletRequest(servletPath: "/private/"), response, new BadCredentialsException(""))
response.redirectedUrl == "http://localhost/login"
}
and: "Exception handling is configured correctly"
AuthenticationEntryPoint authEntryPoint = filterChains[1].filters.find { it instanceof ExceptionTranslationFilter}.authenticationEntryPoint
MockHttpServletResponse response = new MockHttpServletResponse()
authEntryPoint.commence(new MockHttpServletRequest(servletPath: "/private/"), response, new BadCredentialsException(""))
response.redirectedUrl == "http://localhost/login"
}
@EnableWebSecurity
static class FormLoginConfig extends BaseWebConfig {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@EnableWebSecurity
static class FormLoginConfig extends BaseWebConfig {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
}
}
def "FormLogin.permitAll()"() {
when: "load formLogin() with permitAll"
context = new AnnotationConfigApplicationContext(FormLoginConfigPermitAll)
FilterChainProxy filterChain = context.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
setupCsrf()
def "FormLogin.permitAll()"() {
when: "load formLogin() with permitAll"
context = new AnnotationConfigApplicationContext(FormLoginConfigPermitAll)
FilterChainProxy filterChain = context.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
setupCsrf()
then: "the formLogin URLs are granted access"
filterChain.doFilter(request, response, new MockFilterChain())
response.redirectedUrl == redirectUrl
then: "the formLogin URLs are granted access"
filterChain.doFilter(request, response, new MockFilterChain())
response.redirectedUrl == redirectUrl
where:
servletPath | method | query | redirectUrl
"/login" | "GET" | null | null
"/login" | "POST" | null | "/login?error"
"/login" | "GET" | "error" | null
}
where:
servletPath | method | query | redirectUrl
"/login" | "GET" | null | null
"/login" | "POST" | null | "/login?error"
"/login" | "GET" | "error" | null
}
@EnableWebSecurity
static class FormLoginConfigPermitAll extends BaseWebConfig {
@EnableWebSecurity
static class FormLoginConfigPermitAll extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.permitAll()
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.permitAll()
}
}
@Unroll
def "FormLogin loginConventions changes defaults"() {
when: "load formLogin() with permitAll"
loadConfig(FormLoginDefaultsConfig)
MockHttpServletResponse response = new MockHttpServletResponse()
request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
setupCsrf()
@Unroll
def "FormLogin loginConventions changes defaults"() {
when: "load formLogin() with permitAll"
loadConfig(FormLoginDefaultsConfig)
MockHttpServletResponse response = new MockHttpServletResponse()
request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
setupCsrf()
then: "the other default login/logout URLs are updated and granted access"
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
response.redirectedUrl == redirectUrl
then: "the other default login/logout URLs are updated and granted access"
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
response.redirectedUrl == redirectUrl
where:
servletPath | method | query | redirectUrl
"/authenticate" | "GET" | null | null
"/authenticate" | "POST" | null | "/authenticate?error"
"/authenticate" | "GET" | "error" | null
"/logout" | "POST" | null | "/authenticate?logout"
"/authenticate" | "GET" | "logout"| null
}
where:
servletPath | method | query | redirectUrl
"/authenticate" | "GET" | null | null
"/authenticate" | "POST" | null | "/authenticate?error"
"/authenticate" | "GET" | "error" | null
"/logout" | "POST" | null | "/authenticate?logout"
"/authenticate" | "GET" | "logout"| null
}
@EnableWebSecurity
static class FormLoginDefaultsConfig extends BaseWebConfig {
@EnableWebSecurity
static class FormLoginDefaultsConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/authenticate")
.permitAll()
.and()
.logout()
.permitAll()
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/authenticate")
.permitAll()
.and()
.logout()
.permitAll()
}
}
def "FormLogin loginProcessingUrl"() {
setup:
loadConfig(FormLoginLoginProcessingUrlConfig)
request.servletPath = "/loginCheck"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
when:
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
then:
response.redirectedUrl == "/"
}
def "FormLogin loginProcessingUrl"() {
setup:
loadConfig(FormLoginLoginProcessingUrlConfig)
request.servletPath = "/loginCheck"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
when:
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
then:
response.redirectedUrl == "/"
}
@EnableWebSecurity
static class FormLoginLoginProcessingUrlConfig extends BaseWebConfig {
@EnableWebSecurity
static class FormLoginLoginProcessingUrlConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/loginCheck")
.loginPage("/login")
//.failureUrl("/loginFailure")
.defaultSuccessUrl("/", true)
.passwordParameter("password")
.usernameParameter("username")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login")
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/loginCheck")
.loginPage("/login")
//.failureUrl("/loginFailure")
.defaultSuccessUrl("/", true)
.passwordParameter("password")
.usernameParameter("username")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login")
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
}
}
def "FormLogin uses PortMapper"() {
when: "load formLogin() with permitAll"
FormLoginUsesPortMapperConfig.PORT_MAPPER = Mock(PortMapper)
loadConfig(FormLoginUsesPortMapperConfig)
then: "the formLogin URLs are granted access"
findFilter(ExceptionTranslationFilter).authenticationEntryPoint.portMapper == FormLoginUsesPortMapperConfig.PORT_MAPPER
}
def "FormLogin uses PortMapper"() {
when: "load formLogin() with permitAll"
FormLoginUsesPortMapperConfig.PORT_MAPPER = Mock(PortMapper)
loadConfig(FormLoginUsesPortMapperConfig)
then: "the formLogin URLs are granted access"
findFilter(ExceptionTranslationFilter).authenticationEntryPoint.portMapper == FormLoginUsesPortMapperConfig.PORT_MAPPER
}
@EnableWebSecurity
static class FormLoginUsesPortMapperConfig extends BaseWebConfig {
static PortMapper PORT_MAPPER
@EnableWebSecurity
static class FormLoginUsesPortMapperConfig extends BaseWebConfig {
static PortMapper PORT_MAPPER
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.permitAll()
.and()
.portMapper()
.portMapper(PORT_MAPPER)
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.permitAll()
.and()
.portMapper()
.portMapper(PORT_MAPPER)
}
}
def "FormLogin permitAll ignores failureUrl when failureHandler set"() {
setup:
PermitAllIgnoresFailureHandlerConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
loadConfig(PermitAllIgnoresFailureHandlerConfig)
FilterChainProxy springSecurityFilterChain = context.getBean(FilterChainProxy)
when: "access default failureUrl and configured explicit FailureHandler"
MockHttpServletRequest request = new MockHttpServletRequest(servletPath:"/login",requestURI:"/login",queryString:"error",method:"GET")
MockHttpServletResponse response = new MockHttpServletResponse()
springSecurityFilterChain.doFilter(request,response,new MockFilterChain())
then: "access is not granted to the failure handler (sent to login page)"
response.status == 302
}
def "FormLogin permitAll ignores failureUrl when failureHandler set"() {
setup:
PermitAllIgnoresFailureHandlerConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
loadConfig(PermitAllIgnoresFailureHandlerConfig)
FilterChainProxy springSecurityFilterChain = context.getBean(FilterChainProxy)
when: "access default failureUrl and configured explicit FailureHandler"
MockHttpServletRequest request = new MockHttpServletRequest(servletPath:"/login",requestURI:"/login",queryString:"error",method:"GET")
MockHttpServletResponse response = new MockHttpServletResponse()
springSecurityFilterChain.doFilter(request,response,new MockFilterChain())
then: "access is not granted to the failure handler (sent to login page)"
response.status == 302
}
@EnableWebSecurity
static class PermitAllIgnoresFailureHandlerConfig extends BaseWebConfig {
static AuthenticationFailureHandler FAILURE_HANDLER
@EnableWebSecurity
static class PermitAllIgnoresFailureHandlerConfig extends BaseWebConfig {
static AuthenticationFailureHandler FAILURE_HANDLER
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.failureHandler(FAILURE_HANDLER)
.permitAll()
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.failureHandler(FAILURE_HANDLER)
.permitAll()
}
}
def "duplicate formLogin does not override"() {
setup:
DuplicateInvocationsDoesNotOverrideConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
when:
loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
then:
findFilter(UsernamePasswordAuthenticationFilter).usernameParameter == "custom-username"
}
def "duplicate formLogin does not override"() {
setup:
DuplicateInvocationsDoesNotOverrideConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
when:
loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
then:
findFilter(UsernamePasswordAuthenticationFilter).usernameParameter == "custom-username"
}
@EnableWebSecurity
static class DuplicateInvocationsDoesNotOverrideConfig extends BaseWebConfig {
static AuthenticationFailureHandler FAILURE_HANDLER
@EnableWebSecurity
static class DuplicateInvocationsDoesNotOverrideConfig extends BaseWebConfig {
static AuthenticationFailureHandler FAILURE_HANDLER
@Override
protected void configure(HttpSecurity http) {
http
.formLogin()
.usernameParameter("custom-username")
.and()
.formLogin()
}
}
@Override
protected void configure(HttpSecurity http) {
http
.formLogin()
.usernameParameter("custom-username")
.and()
.formLogin()
}
}
def "formLogin ObjectPostProcessor"() {
setup: "initialize the AUTH_FILTER as a mock"
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.exceptionHandling()
.and()
.formLogin()
.and()
.build()
def "formLogin ObjectPostProcessor"() {
setup: "initialize the AUTH_FILTER as a mock"
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.exceptionHandling()
.and()
.formLogin()
.and()
.build()
then: "UsernamePasswordAuthenticationFilter is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
and: "LoginUrlAuthenticationEntryPoint is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
and: "ExceptionTranslationFilter is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
}
then: "UsernamePasswordAuthenticationFilter is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
and: "LoginUrlAuthenticationEntryPoint is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
and: "ExceptionTranslationFilter is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
}
}
@@ -39,163 +39,163 @@ import spock.lang.Unroll;
*/
class HeadersConfigurerTests extends BaseSpringSpec {
def "headers"() {
setup:
loadConfig(HeadersConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'DENY',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache',
'X-XSS-Protection' : '1; mode=block']
}
def "headers"() {
setup:
loadConfig(HeadersConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'DENY',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache',
'X-XSS-Protection' : '1; mode=block']
}
@EnableWebSecurity
static class HeadersConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HeadersConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
}
}
def "headers.contentType"() {
setup:
loadConfig(ContentTypeOptionsConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff']
}
def "headers.contentType"() {
setup:
loadConfig(ContentTypeOptionsConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff']
}
@EnableWebSecurity
static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.contentTypeOptions()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.contentTypeOptions()
}
}
def "headers.frameOptions"() {
setup:
loadConfig(FrameOptionsConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Frame-Options':'DENY']
}
def "headers.frameOptions"() {
setup:
loadConfig(FrameOptionsConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Frame-Options':'DENY']
}
@EnableWebSecurity
static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.frameOptions()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.frameOptions()
}
}
def "headers.hsts"() {
setup:
loadConfig(HstsConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
}
def "headers.hsts"() {
setup:
loadConfig(HstsConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
}
@EnableWebSecurity
static class HstsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HstsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.httpStrictTransportSecurity()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.httpStrictTransportSecurity()
}
}
def "headers.cacheControl"() {
setup:
loadConfig(CacheControlConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache']
}
def "headers.cacheControl"() {
setup:
loadConfig(CacheControlConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache']
}
@EnableWebSecurity
static class CacheControlConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class CacheControlConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.cacheControl()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.cacheControl()
}
}
def "headers.xssProtection"() {
setup:
loadConfig(XssProtectionConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-XSS-Protection' : '1; mode=block']
}
def "headers.xssProtection"() {
setup:
loadConfig(XssProtectionConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-XSS-Protection' : '1; mode=block']
}
@EnableWebSecurity
static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.xssProtection()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.defaultsDisabled()
.xssProtection()
}
}
def "headers custom x-frame-options"() {
setup:
loadConfig(HeadersCustomSameOriginConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'SAMEORIGIN',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache',
'X-XSS-Protection' : '1; mode=block']
}
def "headers custom x-frame-options"() {
setup:
loadConfig(HeadersCustomSameOriginConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'SAMEORIGIN',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache',
'X-XSS-Protection' : '1; mode=block']
}
@EnableWebSecurity
static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.frameOptions().sameOrigin()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.frameOptions().sameOrigin()
}
}
}
@@ -33,101 +33,101 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
*/
class HttpBasicConfigurerTests extends BaseSpringSpec {
def "httBasic ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.httpBasic()
.and()
.build()
def "httBasic ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.httpBasic()
.and()
.build()
then: "ExceptionTranslationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as BasicAuthenticationFilter) >> {BasicAuthenticationFilter o -> o}
}
then: "ExceptionTranslationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as BasicAuthenticationFilter) >> {BasicAuthenticationFilter o -> o}
}
def "SEC-2198: http.httpBasic() defaults AuthenticationEntryPoint"() {
setup:
loadConfig(DefaultsEntryPointConfig)
when:
springSecurityFilterChain.doFilter(request, response, chain)
then:
response.status == 401
response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
}
def "SEC-2198: http.httpBasic() defaults AuthenticationEntryPoint"() {
setup:
loadConfig(DefaultsEntryPointConfig)
when:
springSecurityFilterChain.doFilter(request, response, chain)
then:
response.status == 401
response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
}
@EnableWebSecurity
static class DefaultsEntryPointConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
}
@EnableWebSecurity
static class DefaultsEntryPointConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
def "http.httpBasic().authenticationEntryPoint used for AuthenticationEntryPoint"() {
setup:
CustomAuthenticationEntryPointConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
when:
loadConfig(CustomAuthenticationEntryPointConfig)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint == CustomAuthenticationEntryPointConfig.ENTRY_POINT
}
def "http.httpBasic().authenticationEntryPoint used for AuthenticationEntryPoint"() {
setup:
CustomAuthenticationEntryPointConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
when:
loadConfig(CustomAuthenticationEntryPointConfig)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint == CustomAuthenticationEntryPointConfig.ENTRY_POINT
}
@EnableWebSecurity
static class CustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRY_POINT
@EnableWebSecurity
static class CustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRY_POINT
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.authenticationEntryPoint(ENTRY_POINT)
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.authenticationEntryPoint(ENTRY_POINT)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
def "duplicate httpBasic invocations does not override"() {
setup:
DuplicateDoesNotOverrideConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
when:
loadConfig(DuplicateDoesNotOverrideConfig)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint == DuplicateDoesNotOverrideConfig.ENTRY_POINT
}
def "duplicate httpBasic invocations does not override"() {
setup:
DuplicateDoesNotOverrideConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
when:
loadConfig(DuplicateDoesNotOverrideConfig)
then:
findFilter(ExceptionTranslationFilter).authenticationEntryPoint == DuplicateDoesNotOverrideConfig.ENTRY_POINT
}
@EnableWebSecurity
static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRY_POINT
@EnableWebSecurity
static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRY_POINT
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.authenticationEntryPoint(ENTRY_POINT)
.and()
.httpBasic()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.authenticationEntryPoint(ENTRY_POINT)
.and()
.httpBasic()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
}
}
@@ -31,38 +31,38 @@ import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthe
*/
class JeeConfigurerTests extends BaseSpringSpec {
def "jee ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.jee()
.and()
.build()
def "jee ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.jee()
.and()
.build()
then: "J2eePreAuthenticatedProcessingFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as J2eePreAuthenticatedProcessingFilter) >> {J2eePreAuthenticatedProcessingFilter o -> o}
and: "J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource is registered with LifecycleManager"
1 * opp.postProcess(_ as J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource) >> {J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource o -> o}
}
then: "J2eePreAuthenticatedProcessingFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as J2eePreAuthenticatedProcessingFilter) >> {J2eePreAuthenticatedProcessingFilter o -> o}
and: "J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource is registered with LifecycleManager"
1 * opp.postProcess(_ as J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource) >> {J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource o -> o}
}
def "invoke jee twice does not override"() {
when:
loadConfig(InvokeTwiceDoesNotOverride)
then:
findFilter(J2eePreAuthenticatedProcessingFilter).authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER"] as Set
}
def "invoke jee twice does not override"() {
when:
loadConfig(InvokeTwiceDoesNotOverride)
then:
findFilter(J2eePreAuthenticatedProcessingFilter).authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER"] as Set
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.jee()
.mappableRoles("USER")
.and()
.jee()
}
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.jee()
.mappableRoles("USER")
.and()
.jee()
}
}
}
@@ -30,85 +30,85 @@ import org.springframework.security.web.authentication.logout.LogoutFilter
*/
class LogoutConfigurerTests extends BaseSpringSpec {
def "logout ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.logout()
.and()
.build()
def "logout ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.logout()
.and()
.build()
then: "LogoutFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as LogoutFilter) >> {LogoutFilter o -> o}
}
then: "LogoutFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as LogoutFilter) >> {LogoutFilter o -> o}
}
def "invoke logout twice does not override"() {
when:
loadConfig(InvokeTwiceDoesNotOverride)
request.method = "POST"
request.servletPath = "/custom/logout"
findFilter(LogoutFilter).doFilter(request,response,chain)
then:
response.redirectedUrl == "/login?logout"
}
def "invoke logout twice does not override"() {
when:
loadConfig(InvokeTwiceDoesNotOverride)
request.method = "POST"
request.servletPath = "/custom/logout"
findFilter(LogoutFilter).doFilter(request,response,chain)
then:
response.redirectedUrl == "/login?logout"
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/custom/logout")
.and()
.logout()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/custom/logout")
.and()
.logout()
}
}
def "SEC-2311: Logout allows other methods if CSRF is disabled"() {
when:
loadConfig(CsrfDisabledConfig)
request.method = "GET"
request.servletPath = "/logout"
findFilter(LogoutFilter).doFilter(request,response,chain)
then:
response.redirectedUrl == "/login?logout"
}
def "SEC-2311: Logout allows other methods if CSRF is disabled"() {
when:
loadConfig(CsrfDisabledConfig)
request.method = "GET"
request.servletPath = "/logout"
findFilter(LogoutFilter).doFilter(request,response,chain)
then:
response.redirectedUrl == "/login?logout"
}
@EnableWebSecurity
static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.logout()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.logout()
}
}
def "SEC-2311: Logout allows other methods if CSRF is disabled with custom logout URL"() {
when:
loadConfig(CsrfDisabledCustomLogoutUrlConfig)
request.method = "GET"
request.servletPath = "/custom/logout"
findFilter(LogoutFilter).doFilter(request,response,chain)
then:
response.redirectedUrl == "/login?logout"
}
def "SEC-2311: Logout allows other methods if CSRF is disabled with custom logout URL"() {
when:
loadConfig(CsrfDisabledCustomLogoutUrlConfig)
request.method = "GET"
request.servletPath = "/custom/logout"
findFilter(LogoutFilter).doFilter(request,response,chain)
then:
response.redirectedUrl == "/login?logout"
}
@EnableWebSecurity
static class CsrfDisabledCustomLogoutUrlConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class CsrfDisabledCustomLogoutUrlConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/custom/logout")
.and()
.csrf().disable()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/custom/logout")
.and()
.csrf().disable()
}
}
}
@@ -64,14 +64,14 @@ import spock.lang.Ignore;
*
*/
public class NamespaceDebugTests extends BaseSpringSpec {
def "debug=true"() {
when: "Load configuraiton with debug enabled"
loadConfig(DebugWebSecurity)
then: "The DebugFilter is present"
context.getBean("springSecurityFilterChain").class == DebugFilter
}
def "debug=true"() {
when: "Load configuraiton with debug enabled"
loadConfig(DebugWebSecurity)
then: "The DebugFilter is present"
context.getBean("springSecurityFilterChain").class == DebugFilter
}
@EnableWebSecurity(debug=true)
static class DebugWebSecurity extends WebSecurityConfigurerAdapter {
}
@EnableWebSecurity(debug=true)
static class DebugWebSecurity extends WebSecurityConfigurerAdapter {
}
}
@@ -37,44 +37,44 @@ import org.springframework.security.web.access.ExceptionTranslationFilter;
*
*/
public class NamespaceHttpAccessDeniedHandlerTests extends BaseSpringSpec {
def "http/access-denied-handler@error-page"() {
when:
loadConfig(AccessDeniedPageConfig)
then:
findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
}
def "http/access-denied-handler@error-page"() {
when:
loadConfig(AccessDeniedPageConfig)
then:
findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
}
@Configuration
static class AccessDeniedPageConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http.
exceptionHandling()
.accessDeniedPage("/AccessDeniedPageConfig")
}
}
@Configuration
static class AccessDeniedPageConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http.
exceptionHandling()
.accessDeniedPage("/AccessDeniedPageConfig")
}
}
def "http/access-denied-handler@ref"() {
when:
loadConfig(AccessDeniedHandlerRefConfig)
then:
findFilter(ExceptionTranslationFilter).accessDeniedHandler.class == AccessDeniedHandlerRefConfig.CustomAccessDeniedHandler
}
def "http/access-denied-handler@ref"() {
when:
loadConfig(AccessDeniedHandlerRefConfig)
then:
findFilter(ExceptionTranslationFilter).accessDeniedHandler.class == AccessDeniedHandlerRefConfig.CustomAccessDeniedHandler
}
@Configuration
static class AccessDeniedHandlerRefConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler()
http.
exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
}
@Configuration
static class AccessDeniedHandlerRefConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler()
http.
exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
}
static class CustomAccessDeniedHandler implements AccessDeniedHandler {
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException)
throws IOException, ServletException {
}
}
}
static class CustomAccessDeniedHandler implements AccessDeniedHandler {
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException)
throws IOException, ServletException {
}
}
}
}
@@ -32,98 +32,98 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
*
*/
public class NamespaceHttpAnonymousTests extends BaseSpringSpec {
def "http/anonymous@enabled = true (default)"() {
when:
loadConfig(AnonymousConfig)
then:
def filter = findFilter(AnonymousAuthenticationFilter)
filter != null
def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
}
def "http/anonymous@enabled = true (default)"() {
when:
loadConfig(AnonymousConfig)
then:
def filter = findFilter(AnonymousAuthenticationFilter)
filter != null
def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
}
@Configuration
static class AnonymousConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER");
}
}
@Configuration
static class AnonymousConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER");
}
}
def "http/anonymous@enabled = false"() {
when:
loadConfig(AnonymousDisabledConfig)
then:
findFilter(AnonymousAuthenticationFilter) == null
}
def "http/anonymous@enabled = false"() {
when:
loadConfig(AnonymousDisabledConfig)
then:
findFilter(AnonymousAuthenticationFilter) == null
}
@Configuration
static class AnonymousDisabledConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http.anonymous().disable()
}
}
@Configuration
static class AnonymousDisabledConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http.anonymous().disable()
}
}
def "http/anonymous@granted-authority"() {
when:
loadConfig(AnonymousGrantedAuthorityConfig)
then:
findFilter(AnonymousAuthenticationFilter).authorities == AuthorityUtils.createAuthorityList("ROLE_ANON")
}
def "http/anonymous@granted-authority"() {
when:
loadConfig(AnonymousGrantedAuthorityConfig)
then:
findFilter(AnonymousAuthenticationFilter).authorities == AuthorityUtils.createAuthorityList("ROLE_ANON")
}
@Configuration
static class AnonymousGrantedAuthorityConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.anonymous()
.authorities("ROLE_ANON")
}
}
@Configuration
static class AnonymousGrantedAuthorityConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.anonymous()
.authorities("ROLE_ANON")
}
}
def "http/anonymous@key"() {
when:
loadConfig(AnonymousKeyConfig)
then:
def filter = findFilter(AnonymousAuthenticationFilter)
filter != null
filter.key == "AnonymousKeyConfig"
def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
}
def "http/anonymous@key"() {
when:
loadConfig(AnonymousKeyConfig)
then:
def filter = findFilter(AnonymousAuthenticationFilter)
filter != null
filter.key == "AnonymousKeyConfig"
def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
}
@Configuration
static class AnonymousKeyConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.anonymous().key("AnonymousKeyConfig")
}
}
@Configuration
static class AnonymousKeyConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.anonymous().key("AnonymousKeyConfig")
}
}
def "http/anonymous@username"() {
when:
loadConfig(AnonymousUsernameConfig)
then:
def filter = findFilter(AnonymousAuthenticationFilter)
filter != null
filter.principal == "AnonymousUsernameConfig"
def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).principal == "AnonymousUsernameConfig"
}
def "http/anonymous@username"() {
when:
loadConfig(AnonymousUsernameConfig)
then:
def filter = findFilter(AnonymousAuthenticationFilter)
filter != null
filter.principal == "AnonymousUsernameConfig"
def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).principal == "AnonymousUsernameConfig"
}
@Configuration
static class AnonymousUsernameConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.anonymous().principal("AnonymousUsernameConfig")
}
}
@Configuration
static class AnonymousUsernameConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.anonymous().principal("AnonymousUsernameConfig")
}
}
}
@@ -40,117 +40,117 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
*/
public class NamespaceHttpBasicTests extends BaseSpringSpec {
def "http/http-basic"() {
setup:
loadConfig(HttpBasicConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when: "fail to log in"
super.setup()
basicLogin("user","invalid")
springSecurityFilterChain.doFilter(request,response,chain)
then: "unauthorized"
response.status == HttpServletResponse.SC_UNAUTHORIZED
response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
when: "login success"
super.setup()
basicLogin()
then: "sent to default succes page"
!response.committed
}
def "http/http-basic"() {
setup:
loadConfig(HttpBasicConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_UNAUTHORIZED
when: "fail to log in"
super.setup()
basicLogin("user","invalid")
springSecurityFilterChain.doFilter(request,response,chain)
then: "unauthorized"
response.status == HttpServletResponse.SC_UNAUTHORIZED
response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
when: "login success"
super.setup()
basicLogin()
then: "sent to default succes page"
!response.committed
}
@Configuration
static class HttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.httpBasic();
}
}
@Configuration
static class HttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.httpBasic();
}
}
def "http@realm"() {
setup:
loadConfig(CustomHttpBasicConfig)
when:
basicLogin("user","invalid")
springSecurityFilterChain.doFilter(request,response,chain)
then: "unauthorized"
response.status == HttpServletResponse.SC_UNAUTHORIZED
response.getHeader("WWW-Authenticate") == 'Basic realm="Custom Realm"'
}
def "http@realm"() {
setup:
loadConfig(CustomHttpBasicConfig)
when:
basicLogin("user","invalid")
springSecurityFilterChain.doFilter(request,response,chain)
then: "unauthorized"
response.status == HttpServletResponse.SC_UNAUTHORIZED
response.getHeader("WWW-Authenticate") == 'Basic realm="Custom Realm"'
}
@Configuration
static class CustomHttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.httpBasic().realmName("Custom Realm");
}
}
@Configuration
static class CustomHttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.httpBasic().realmName("Custom Realm");
}
}
def "http-basic@authentication-details-source-ref"() {
when:
loadConfig(AuthenticationDetailsSourceHttpBasicConfig)
then:
findFilter(BasicAuthenticationFilter).authenticationDetailsSource.class == CustomAuthenticationDetailsSource
}
def "http-basic@authentication-details-source-ref"() {
when:
loadConfig(AuthenticationDetailsSourceHttpBasicConfig)
then:
findFilter(BasicAuthenticationFilter).authenticationDetailsSource.class == CustomAuthenticationDetailsSource
}
@Configuration
static class AuthenticationDetailsSourceHttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.httpBasic()
.authenticationDetailsSource(new CustomAuthenticationDetailsSource())
}
}
@Configuration
static class AuthenticationDetailsSourceHttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.httpBasic()
.authenticationDetailsSource(new CustomAuthenticationDetailsSource())
}
}
static class CustomAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
static class CustomAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
def "http-basic@entry-point-ref"() {
setup:
loadConfig(EntryPointRefHttpBasicConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
when: "fail to log in"
super.setup()
basicLogin("user","invalid")
springSecurityFilterChain.doFilter(request,response,chain)
then: "custom"
response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
when: "login success"
super.setup()
basicLogin()
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
!response.committed
}
def "http-basic@entry-point-ref"() {
setup:
loadConfig(EntryPointRefHttpBasicConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
when: "fail to log in"
super.setup()
basicLogin("user","invalid")
springSecurityFilterChain.doFilter(request,response,chain)
then: "custom"
response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
when: "login success"
super.setup()
basicLogin()
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
!response.committed
}
@Configuration
static class EntryPointRefHttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.httpBasic()
.authenticationEntryPoint(new AuthenticationEntryPoint() {
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
}
})
}
}
@Configuration
static class EntryPointRefHttpBasicConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.httpBasic()
.authenticationEntryPoint(new AuthenticationEntryPoint() {
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
}
})
}
}
def basicLogin(String username="user",String password="password") {
def credentials = username + ":" + password
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
}
def basicLogin(String username="user",String password="password") {
def credentials = username + ":" + password
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
}
}
@@ -65,105 +65,105 @@ import spock.lang.Ignore;
*
*/
public class NamespaceHttpCustomFilterTests extends BaseSpringSpec {
def "http/custom-filter@before"() {
when:
loadConfig(CustomFilterBeforeConfig)
then:
filterChain().filters[0].class == CustomFilter
}
def "http/custom-filter@before"() {
when:
loadConfig(CustomFilterBeforeConfig)
then:
filterChain().filters[0].class == CustomFilter
}
@Configuration
static class CustomFilterBeforeConfig extends BaseWebConfig {
CustomFilterBeforeConfig() {
// do not add the default filters to make testing easier
super(true)
}
@Configuration
static class CustomFilterBeforeConfig extends BaseWebConfig {
CustomFilterBeforeConfig() {
// do not add the default filters to make testing easier
super(true)
}
protected void configure(HttpSecurity http) {
http
.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
.formLogin()
}
}
protected void configure(HttpSecurity http) {
http
.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
.formLogin()
}
}
def "http/custom-filter@after"() {
when:
loadConfig(CustomFilterAfterConfig)
then:
filterChain().filters[1].class == CustomFilter
}
def "http/custom-filter@after"() {
when:
loadConfig(CustomFilterAfterConfig)
then:
filterChain().filters[1].class == CustomFilter
}
@Configuration
static class CustomFilterAfterConfig extends BaseWebConfig {
CustomFilterAfterConfig() {
// do not add the default filters to make testing easier
super(true)
}
@Configuration
static class CustomFilterAfterConfig extends BaseWebConfig {
CustomFilterAfterConfig() {
// do not add the default filters to make testing easier
super(true)
}
protected void configure(HttpSecurity http) {
http
.addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
.formLogin()
}
}
protected void configure(HttpSecurity http) {
http
.addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
.formLogin()
}
}
def "http/custom-filter@position"() {
when:
loadConfig(CustomFilterPositionConfig)
then:
filterChain().filters.collect { it.class } == [CustomFilter]
}
def "http/custom-filter@position"() {
when:
loadConfig(CustomFilterPositionConfig)
then:
filterChain().filters.collect { it.class } == [CustomFilter]
}
@Configuration
static class CustomFilterPositionConfig extends BaseWebConfig {
CustomFilterPositionConfig() {
// do not add the default filters to make testing easier
super(true)
}
@Configuration
static class CustomFilterPositionConfig extends BaseWebConfig {
CustomFilterPositionConfig() {
// do not add the default filters to make testing easier
super(true)
}
protected void configure(HttpSecurity http) {
http
// this works so long as the CustomFilter extends one of the standard filters
// if not, use addFilterBefore or addFilterAfter
.addFilter(new CustomFilter())
}
protected void configure(HttpSecurity http) {
http
// this works so long as the CustomFilter extends one of the standard filters
// if not, use addFilterBefore or addFilterAfter
.addFilter(new CustomFilter())
}
}
}
def "http/custom-filter no AuthenticationManager in HttpSecurity"() {
when:
loadConfig(NoAuthenticationManagerInHtppConfigurationConfig)
then:
filterChain().filters[0].class == CustomFilter
}
def "http/custom-filter no AuthenticationManager in HttpSecurity"() {
when:
loadConfig(NoAuthenticationManagerInHtppConfigurationConfig)
then:
filterChain().filters[0].class == CustomFilter
}
@EnableWebSecurity
static class NoAuthenticationManagerInHtppConfigurationConfig extends WebSecurityConfigurerAdapter {
NoAuthenticationManagerInHtppConfigurationConfig() {
super(true)
}
@EnableWebSecurity
static class NoAuthenticationManagerInHtppConfigurationConfig extends WebSecurityConfigurerAdapter {
NoAuthenticationManagerInHtppConfigurationConfig() {
super(true)
}
protected AuthenticationManager authenticationManager()
throws Exception {
return new CustomAuthenticationManager();
}
protected AuthenticationManager authenticationManager()
throws Exception {
return new CustomAuthenticationManager();
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
}
}
static class CustomFilter extends UsernamePasswordAuthenticationFilter {}
static class CustomFilter extends UsernamePasswordAuthenticationFilter {}
static class CustomAuthenticationManager implements AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return null;
}
}
static class CustomAuthenticationManager implements AuthenticationManager {
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return null;
}
}
}
@@ -30,27 +30,27 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
*
*/
public class NamespaceHttpExpressionHandlerTests extends BaseSpringSpec {
def "http/expression-handler@ref"() {
when:
def parser = new SpelExpressionParser()
ExpressionHandlerConfig.EXPRESSION_HANDLER = Mock(SecurityExpressionHandler.class)
ExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser() >> parser
loadConfig(ExpressionHandlerConfig)
then:
noExceptionThrown()
}
def "http/expression-handler@ref"() {
when:
def parser = new SpelExpressionParser()
ExpressionHandlerConfig.EXPRESSION_HANDLER = Mock(SecurityExpressionHandler.class)
ExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser() >> parser
loadConfig(ExpressionHandlerConfig)
then:
noExceptionThrown()
}
@EnableWebSecurity
static class ExpressionHandlerConfig extends BaseWebConfig {
static EXPRESSION_HANDLER;
@EnableWebSecurity
static class ExpressionHandlerConfig extends BaseWebConfig {
static EXPRESSION_HANDLER;
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.expressionHandler(EXPRESSION_HANDLER)
.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
.antMatchers("/signup").permitAll()
.anyRequest().hasRole("USER")
}
}
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.expressionHandler(EXPRESSION_HANDLER)
.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
.antMatchers("/signup").permitAll()
.anyRequest().hasRole("USER")
}
}
}
@@ -38,73 +38,73 @@ import org.springframework.security.web.firewall.RequestRejectedException
*
*/
public class NamespaceHttpFirewallTests extends BaseSpringSpec {
FilterChainProxy springSecurityFilterChain
MockHttpServletRequest request
MockHttpServletResponse response
MockFilterChain chain
FilterChainProxy springSecurityFilterChain
MockHttpServletRequest request
MockHttpServletResponse response
MockFilterChain chain
def setup() {
request = new MockHttpServletRequest()
response = new MockHttpServletResponse()
chain = new MockFilterChain()
}
def setup() {
request = new MockHttpServletRequest()
response = new MockHttpServletResponse()
chain = new MockFilterChain()
}
def "http-firewall"() {
setup:
loadConfig(HttpFirewallConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
request.setPathInfo("/public/../private/")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "the default firewall is used"
thrown(RequestRejectedException)
}
def "http-firewall"() {
setup:
loadConfig(HttpFirewallConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
request.setPathInfo("/public/../private/")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "the default firewall is used"
thrown(RequestRejectedException)
}
@Configuration
static class HttpFirewallConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
}
}
@Configuration
static class HttpFirewallConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
}
}
def "http-firewall@ref"() {
setup:
loadConfig(CustomHttpFirewallConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
request.setParameter("deny", "true")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "the custom firewall is used"
thrown(RequestRejectedException)
}
def "http-firewall@ref"() {
setup:
loadConfig(CustomHttpFirewallConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
request.setParameter("deny", "true")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then: "the custom firewall is used"
thrown(RequestRejectedException)
}
@Configuration
static class CustomHttpFirewallConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) { }
@Configuration
static class CustomHttpFirewallConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) { }
@Override
public void configure(WebSecurity builder) throws Exception {
builder
.httpFirewall(new CustomHttpFirewall())
}
}
@Override
public void configure(WebSecurity builder) throws Exception {
builder
.httpFirewall(new CustomHttpFirewall())
}
}
static class CustomHttpFirewall extends DefaultHttpFirewall {
static class CustomHttpFirewall extends DefaultHttpFirewall {
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request)
throws RequestRejectedException {
if(request.getParameter("deny")) {
throw new RequestRejectedException("custom rejection")
}
return super.getFirewalledRequest(request)
}
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request)
throws RequestRejectedException {
if(request.getParameter("deny")) {
throw new RequestRejectedException("custom rejection")
}
return super.getFirewalledRequest(request)
}
@Override
public HttpServletResponse getFirewalledResponse(
HttpServletResponse response) {
return super.getFirewalledRequest(response)
}
@Override
public HttpServletResponse getFirewalledResponse(
HttpServletResponse response) {
return super.getFirewalledRequest(response)
}
}
}
}
@@ -38,133 +38,133 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
*
*/
public class NamespaceHttpFormLoginTests extends BaseSpringSpec {
FilterChainProxy springSecurityFilterChain
FilterChainProxy springSecurityFilterChain
def "http/form-login"() {
setup:
loadConfig(FormLoginConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
def "http/form-login"() {
setup:
loadConfig(FormLoginConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/"
}
@Configuration
static class FormLoginConfig extends BaseWebConfig {
@Configuration
static class FormLoginConfig extends BaseWebConfig {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
}
}
@Override
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
}
}
def "http/form-login custom"() {
setup:
loadConfig(FormLoginCustomConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/authentication/login"
when: "fail to log in"
super.setup()
request.servletPath = "/authentication/login/process"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/authentication/login?failed"
when: "login success"
super.setup()
request.servletPath = "/authentication/login/process"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/default"
}
def "http/form-login custom"() {
setup:
loadConfig(FormLoginCustomConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/authentication/login"
when: "fail to log in"
super.setup()
request.servletPath = "/authentication/login/process"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/authentication/login?failed"
when: "login success"
super.setup()
request.servletPath = "/authentication/login/process"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/default"
}
@Configuration
static class FormLoginCustomConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
boolean alwaysUseDefaultSuccess = true;
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.usernameParameter("username") // form-login@username-parameter
.passwordParameter("password") // form-login@password-parameter
.loginPage("/authentication/login") // form-login@login-page
.failureUrl("/authentication/login?failed") // form-login@authentication-failure-url
.loginProcessingUrl("/authentication/login/process") // form-login@login-processing-url
.defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // form-login@default-target-url / form-login@always-use-default-target
}
}
@Configuration
static class FormLoginCustomConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
boolean alwaysUseDefaultSuccess = true;
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.usernameParameter("username") // form-login@username-parameter
.passwordParameter("password") // form-login@password-parameter
.loginPage("/authentication/login") // form-login@login-page
.failureUrl("/authentication/login?failed") // form-login@authentication-failure-url
.loginProcessingUrl("/authentication/login/process") // form-login@login-processing-url
.defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // form-login@default-target-url / form-login@always-use-default-target
}
}
def "http/form-login custom refs"() {
when:
loadConfig(FormLoginCustomRefsConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
then: "CustomWebAuthenticationDetailsSource is used"
findFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
when: "fail to log in"
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/custom/failure"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/custom/targetUrl"
}
def "http/form-login custom refs"() {
when:
loadConfig(FormLoginCustomRefsConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
then: "CustomWebAuthenticationDetailsSource is used"
findFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
when: "fail to log in"
request.servletPath = "/login"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/custom/failure"
when: "login success"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default succes page"
response.getRedirectedUrl() == "/custom/targetUrl"
}
@Configuration
static class FormLoginCustomRefsConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // form-login@authentication-failure-handler-ref
.successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // form-login@authentication-success-handler-ref
.authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()) // form-login@authentication-details-source-ref
.and();
}
}
@Configuration
static class FormLoginCustomRefsConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // form-login@authentication-failure-handler-ref
.successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // form-login@authentication-success-handler-ref
.authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()) // form-login@authentication-details-source-ref
.and();
}
}
static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
}
@@ -38,230 +38,230 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
*/
public class NamespaceHttpHeadersTests extends BaseSpringSpec {
def "http/headers"() {
setup:
loadConfig(HeadersDefaultConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'DENY',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Pragma':'no-cache',
'Expires' : '0',
'X-XSS-Protection' : '1; mode=block']
}
def "http/headers"() {
setup:
loadConfig(HeadersDefaultConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options':'nosniff',
'X-Frame-Options':'DENY',
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Pragma':'no-cache',
'Expires' : '0',
'X-XSS-Protection' : '1; mode=block']
}
@Configuration
static class HeadersDefaultConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
}
}
@Configuration
static class HeadersDefaultConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
}
}
def "http/headers/cache-control"() {
setup:
loadConfig(HeadersCacheControlConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache']
}
def "http/headers/cache-control"() {
setup:
loadConfig(HeadersCacheControlConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
'Pragma':'no-cache']
}
@Configuration
static class HeadersCacheControlConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
.defaultsDisabled()
.cacheControl()
}
}
@Configuration
static class HeadersCacheControlConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
.defaultsDisabled()
.cacheControl()
}
}
def "http/headers/hsts"() {
setup:
loadConfig(HstsConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
}
def "http/headers/hsts"() {
setup:
loadConfig(HstsConfig)
request.secure = true
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
}
@Configuration
static class HstsConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
.defaultsDisabled()
.httpStrictTransportSecurity()
}
}
@Configuration
static class HstsConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
.defaultsDisabled()
.httpStrictTransportSecurity()
}
}
def "http/headers/hsts custom"() {
setup:
loadConfig(HstsCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Strict-Transport-Security': 'max-age=15768000']
}
def "http/headers/hsts custom"() {
setup:
loadConfig(HstsCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['Strict-Transport-Security': 'max-age=15768000']
}
@Configuration
static class HstsCustomConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
.defaultsDisabled()
.httpStrictTransportSecurity()
.requestMatcher(AnyRequestMatcher.INSTANCE)
.maxAgeInSeconds(15768000)
.includeSubDomains(false)
}
}
@Configuration
static class HstsCustomConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
.defaultsDisabled()
.httpStrictTransportSecurity()
.requestMatcher(AnyRequestMatcher.INSTANCE)
.maxAgeInSeconds(15768000)
.includeSubDomains(false)
}
}
def "http/headers/frame-options@policy=SAMEORIGIN"() {
setup:
loadConfig(FrameOptionsSameOriginConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Frame-Options': 'SAMEORIGIN']
}
def "http/headers/frame-options@policy=SAMEORIGIN"() {
setup:
loadConfig(FrameOptionsSameOriginConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Frame-Options': 'SAMEORIGIN']
}
@Configuration
static class FrameOptionsSameOriginConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// frame-options@policy=SAMEORIGIN
.defaultsDisabled()
.frameOptions()
.sameOrigin()
}
}
@Configuration
static class FrameOptionsSameOriginConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// frame-options@policy=SAMEORIGIN
.defaultsDisabled()
.frameOptions()
.sameOrigin()
}
}
// frame-options@strategy, frame-options@value, frame-options@parameter are not provided instead use frame-options@ref
// frame-options@strategy, frame-options@value, frame-options@parameter are not provided instead use frame-options@ref
def "http/headers/frame-options"() {
setup:
loadConfig(FrameOptionsAllowFromConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Frame-Options': 'ALLOW-FROM https://example.com']
}
def "http/headers/frame-options"() {
setup:
loadConfig(FrameOptionsAllowFromConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Frame-Options': 'ALLOW-FROM https://example.com']
}
@Configuration
static class FrameOptionsAllowFromConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// frame-options@ref
.defaultsDisabled()
.addHeaderWriter(new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI("https://example.com"))))
}
}
@Configuration
static class FrameOptionsAllowFromConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// frame-options@ref
.defaultsDisabled()
.addHeaderWriter(new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI("https://example.com"))))
}
}
def "http/headers/xss-protection"() {
setup:
loadConfig(XssProtectionConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-XSS-Protection': '1; mode=block']
}
def "http/headers/xss-protection"() {
setup:
loadConfig(XssProtectionConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-XSS-Protection': '1; mode=block']
}
@Configuration
static class XssProtectionConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// xss-protection
.defaultsDisabled()
.xssProtection()
}
}
@Configuration
static class XssProtectionConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// xss-protection
.defaultsDisabled()
.xssProtection()
}
}
def "http/headers/xss-protection custom"() {
setup:
loadConfig(XssProtectionCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-XSS-Protection': '1']
}
def "http/headers/xss-protection custom"() {
setup:
loadConfig(XssProtectionCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-XSS-Protection': '1']
}
@Configuration
static class XssProtectionCustomConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// xss-protection@enabled and xss-protection@block
.defaultsDisabled()
.xssProtection()
.xssProtectionEnabled(true)
.block(false)
}
}
@Configuration
static class XssProtectionCustomConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// xss-protection@enabled and xss-protection@block
.defaultsDisabled()
.xssProtection()
.xssProtectionEnabled(true)
.block(false)
}
}
def "http/headers/content-type-options"() {
setup:
loadConfig(ContentTypeOptionsConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options': 'nosniff']
}
def "http/headers/content-type-options"() {
setup:
loadConfig(ContentTypeOptionsConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['X-Content-Type-Options': 'nosniff']
}
@Configuration
static class ContentTypeOptionsConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// content-type-options
.defaultsDisabled()
.contentTypeOptions()
}
}
@Configuration
static class ContentTypeOptionsConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
// content-type-options
.defaultsDisabled()
.contentTypeOptions()
}
}
// header@name / header@value are not provided instead use header@ref
// header@name / header@value are not provided instead use header@ref
def "http/headers/header@ref"() {
setup:
loadConfig(HeaderRefConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['customHeaderName': 'customHeaderValue']
}
def "http/headers/header@ref"() {
setup:
loadConfig(HeaderRefConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
responseHeaders == ['customHeaderName': 'customHeaderValue']
}
@Configuration
static class HeaderRefConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
.defaultsDisabled()
.addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"))
}
}
@Configuration
static class HeaderRefConfig extends BaseWebConfig {
@Override
protected void configure(HttpSecurity http) {
http
.headers()
.defaultsDisabled()
.addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"))
}
}
}
@@ -42,128 +42,128 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
*/
public class NamespaceHttpInterceptUrlTests extends BaseSpringSpec {
def "http/intercept-url denied when not logged in"() {
setup:
loadConfig(HttpInterceptUrlConfig)
request.servletPath == "/users"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "http/intercept-url denied when not logged in"() {
setup:
loadConfig(HttpInterceptUrlConfig)
request.servletPath == "/users"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "http/intercept-url denied when logged in"() {
setup:
loadConfig(HttpInterceptUrlConfig)
login()
request.setServletPath("/users")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "http/intercept-url denied when logged in"() {
setup:
loadConfig(HttpInterceptUrlConfig)
login()
request.setServletPath("/users")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
}
def "http/intercept-url allowed when logged in"() {
setup:
loadConfig(HttpInterceptUrlConfig)
login("admin","ROLE_ADMIN")
request.setServletPath("/users")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
!response.isCommitted()
}
def "http/intercept-url allowed when logged in"() {
setup:
loadConfig(HttpInterceptUrlConfig)
login("admin","ROLE_ADMIN")
request.setServletPath("/users")
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
!response.isCommitted()
}
def "http/intercept-url@method=POST"() {
setup:
loadConfig(HttpInterceptUrlConfig)
when:
login()
request.setServletPath("/admin/post")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
!response.isCommitted()
when:
super.setup()
login()
request.setServletPath("/admin/post")
request.setMethod("POST")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
when:
super.setup()
login("admin","ROLE_ADMIN")
request.setServletPath("/admin/post")
request.setMethod("POST")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
!response.committed
}
def "http/intercept-url@method=POST"() {
setup:
loadConfig(HttpInterceptUrlConfig)
when:
login()
request.setServletPath("/admin/post")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
!response.isCommitted()
when:
super.setup()
login()
request.setServletPath("/admin/post")
request.setMethod("POST")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
when:
super.setup()
login("admin","ROLE_ADMIN")
request.setServletPath("/admin/post")
request.setMethod("POST")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_OK
!response.committed
}
def "http/intercept-url@requires-channel"() {
setup:
loadConfig(HttpInterceptUrlConfig)
when:
request.setServletPath("/login")
request.setRequestURI("/login")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost/login"
when:
super.setup()
request.setServletPath("/secured/a")
request.setRequestURI("/secured/a")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost/secured/a"
when:
super.setup()
request.setSecure(true)
request.setScheme("https")
request.setServletPath("/user")
request.setRequestURI("/user")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "http://localhost/user"
}
def "http/intercept-url@requires-channel"() {
setup:
loadConfig(HttpInterceptUrlConfig)
when:
request.setServletPath("/login")
request.setRequestURI("/login")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost/login"
when:
super.setup()
request.setServletPath("/secured/a")
request.setRequestURI("/secured/a")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost/secured/a"
when:
super.setup()
request.setSecure(true)
request.setScheme("https")
request.setServletPath("/user")
request.setRequestURI("/user")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "http://localhost/user"
}
@EnableWebSecurity
static class HttpInterceptUrlConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HttpInterceptUrlConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// the line below is similar to intercept-url@pattern:
// <intercept-url pattern="/users**" access="hasRole('ROLE_ADMIN')"/>
// <intercept-url pattern="/sessions/**" access="hasRole('ROLE_ADMIN')"/>
.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
// the line below is similar to intercept-url@method:
// <intercept-url pattern="/admin/post" access="hasRole('ROLE_ADMIN')" method="POST"/>
// <intercept-url pattern="/admin/another-post/**" access="hasRole('ROLE_ADMIN')" method="POST"/>
.antMatchers(HttpMethod.POST, "/admin/post","/admin/another-post/**").hasRole("ADMIN")
.antMatchers("/signup").permitAll()
.anyRequest().hasRole("USER")
.and()
.requiresChannel()
// NOTE: channel security is configured separately of authorization (i.e. intercept-url@access
// the line below is similar to intercept-url@requires-channel="https":
// <intercept-url pattern="/login" requires-channel="https"/>
// <intercept-url pattern="/secured/**" requires-channel="https"/>
.antMatchers("/login","/secured/**").requiresSecure()
// the line below is similar to intercept-url@requires-channel="http":
// <intercept-url pattern="/**" requires-channel="http"/>
.anyRequest().requiresInsecure()
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN")
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// the line below is similar to intercept-url@pattern:
// <intercept-url pattern="/users**" access="hasRole('ROLE_ADMIN')"/>
// <intercept-url pattern="/sessions/**" access="hasRole('ROLE_ADMIN')"/>
.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
// the line below is similar to intercept-url@method:
// <intercept-url pattern="/admin/post" access="hasRole('ROLE_ADMIN')" method="POST"/>
// <intercept-url pattern="/admin/another-post/**" access="hasRole('ROLE_ADMIN')" method="POST"/>
.antMatchers(HttpMethod.POST, "/admin/post","/admin/another-post/**").hasRole("ADMIN")
.antMatchers("/signup").permitAll()
.anyRequest().hasRole("USER")
.and()
.requiresChannel()
// NOTE: channel security is configured separately of authorization (i.e. intercept-url@access
// the line below is similar to intercept-url@requires-channel="https":
// <intercept-url pattern="/login" requires-channel="https"/>
// <intercept-url pattern="/secured/**" requires-channel="https"/>
.antMatchers("/login","/secured/**").requiresSecure()
// the line below is similar to intercept-url@requires-channel="http":
// <intercept-url pattern="/**" requires-channel="http"/>
.anyRequest().requiresInsecure()
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN")
}
}
}
@@ -80,64 +80,64 @@ import org.springframework.test.util.ReflectionTestUtils;
*/
public class NamespaceHttpJeeTests extends BaseSpringSpec {
def "http/jee@mappable-roles"() {
when:
loadConfig(JeeMappableRolesConfig)
J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == PreAuthenticatedGrantedAuthoritiesUserDetailsService
}
def "http/jee@mappable-roles"() {
when:
loadConfig(JeeMappableRolesConfig)
J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == PreAuthenticatedGrantedAuthoritiesUserDetailsService
}
@EnableWebSecurity
public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee()
.mappableRoles("USER","ADMIN");
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee()
.mappableRoles("USER","ADMIN");
}
}
def "http/jee@user-service-ref"() {
when:
loadConfig(JeeUserServiceRefConfig)
J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == CustomUserService
}
def "http/jee@user-service-ref"() {
when:
loadConfig(JeeUserServiceRefConfig)
J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == CustomUserService
}
@EnableWebSecurity
public static class JeeUserServiceRefConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
public static class JeeUserServiceRefConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee()
.mappableAuthorities("ROLE_USER","ROLE_ADMIN")
.authenticatedUserDetailsService(new CustomUserService());
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee()
.mappableAuthorities("ROLE_USER","ROLE_ADMIN")
.authenticatedUserDetailsService(new CustomUserService());
}
}
static class CustomUserService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
public UserDetails loadUserDetails(
PreAuthenticatedAuthenticationToken token)
throws UsernameNotFoundException {
return null;
}
}
static class CustomUserService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
public UserDetails loadUserDetails(
PreAuthenticatedAuthenticationToken token)
throws UsernameNotFoundException {
return null;
}
}
}
@@ -72,90 +72,90 @@ import org.springframework.security.web.util.matcher.RequestMatcher
*/
public class NamespaceHttpLogoutTests extends BaseSpringSpec {
def "http/logout"() {
setup:
loadConfig(HttpLogoutConfig)
login()
request.servletPath = "/logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!authenticated()
!request.getSession(false)
response.redirectedUrl == "/login?logout"
!response.getCookies()
}
def "http/logout"() {
setup:
loadConfig(HttpLogoutConfig)
login()
request.servletPath = "/logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!authenticated()
!request.getSession(false)
response.redirectedUrl == "/login?logout"
!response.getCookies()
}
@Configuration
static class HttpLogoutConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
}
}
@Configuration
static class HttpLogoutConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
}
}
def "http/logout custom"() {
setup:
loadConfig(CustomHttpLogoutConfig)
login()
request.servletPath = "/custom-logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!authenticated()
request.getSession(false)
response.redirectedUrl == "/logout-success"
response.getCookies().length == 1
response.getCookies()[0].name == "remove"
response.getCookies()[0].maxAge == 0
}
def "http/logout custom"() {
setup:
loadConfig(CustomHttpLogoutConfig)
login()
request.servletPath = "/custom-logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!authenticated()
request.getSession(false)
response.redirectedUrl == "/logout-success"
response.getCookies().length == 1
response.getCookies()[0].name == "remove"
response.getCookies()[0].maxAge == 0
}
@Configuration
static class CustomHttpLogoutConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.deleteCookies("remove") // logout@delete-cookies
.invalidateHttpSession(false) // logout@invalidate-session=false (default is true)
.logoutUrl("/custom-logout") // logout@logout-url (default is /logout)
.logoutSuccessUrl("/logout-success") // logout@success-url (default is /login?logout)
}
}
@Configuration
static class CustomHttpLogoutConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.deleteCookies("remove") // logout@delete-cookies
.invalidateHttpSession(false) // logout@invalidate-session=false (default is true)
.logoutUrl("/custom-logout") // logout@logout-url (default is /logout)
.logoutSuccessUrl("/logout-success") // logout@success-url (default is /login?logout)
}
}
def "http/logout@success-handler-ref"() {
setup:
loadConfig(SuccessHandlerRefHttpLogoutConfig)
login()
request.servletPath = "/logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!authenticated()
!request.getSession(false)
response.redirectedUrl == "/SuccessHandlerRefHttpLogoutConfig"
!response.getCookies()
}
def "http/logout@success-handler-ref"() {
setup:
loadConfig(SuccessHandlerRefHttpLogoutConfig)
login()
request.servletPath = "/logout"
request.method = "POST"
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
!authenticated()
!request.getSession(false)
response.redirectedUrl == "/SuccessHandlerRefHttpLogoutConfig"
!response.getCookies()
}
@Configuration
static class SuccessHandlerRefHttpLogoutConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(defaultTargetUrl:"/SuccessHandlerRefHttpLogoutConfig")
http
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
}
}
@Configuration
static class SuccessHandlerRefHttpLogoutConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(defaultTargetUrl:"/SuccessHandlerRefHttpLogoutConfig")
http
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
}
}
def login(String username="user", String role="ROLE_USER") {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
repo.loadContext(requestResponseHolder)
repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
}
def login(String username="user", String role="ROLE_USER") {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
repo.loadContext(requestResponseHolder)
repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
}
def authenticated() {
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication?.authenticated
}
def authenticated() {
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication?.authenticated
}
}
@@ -44,185 +44,185 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
*
*/
public class NamespaceHttpOpenIDLoginTests extends BaseSpringSpec {
def "http/openid-login"() {
when:
loadConfig(OpenIDLoginConfig)
then:
findFilter(OpenIDAuthenticationFilter).consumer.class == OpenID4JavaConsumer
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login/openid"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
}
def "http/openid-login"() {
when:
loadConfig(OpenIDLoginConfig)
then:
findFilter(OpenIDAuthenticationFilter).consumer.class == OpenID4JavaConsumer
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login/openid"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
}
@Configuration
static class OpenIDLoginConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
.permitAll();
}
}
@Configuration
static class OpenIDLoginConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
.permitAll();
}
}
def "http/openid-login/attribute-exchange"() {
when:
loadConfig(OpenIDLoginAttributeExchangeConfig)
OpenID4JavaConsumer consumer = findFilter(OpenIDAuthenticationFilter).consumer
then:
consumer.class == OpenID4JavaConsumer
def "http/openid-login/attribute-exchange"() {
when:
loadConfig(OpenIDLoginAttributeExchangeConfig)
OpenID4JavaConsumer consumer = findFilter(OpenIDAuthenticationFilter).consumer
then:
consumer.class == OpenID4JavaConsumer
def googleAttrs = consumer.attributesToFetchFactory.createAttributeList("https://www.google.com/1")
googleAttrs[0].name == "email"
googleAttrs[0].type == "http://axschema.org/contact/email"
googleAttrs[0].required
googleAttrs[1].name == "firstname"
googleAttrs[1].type == "http://axschema.org/namePerson/first"
googleAttrs[1].required
googleAttrs[2].name == "lastname"
googleAttrs[2].type == "http://axschema.org/namePerson/last"
googleAttrs[2].required
def googleAttrs = consumer.attributesToFetchFactory.createAttributeList("https://www.google.com/1")
googleAttrs[0].name == "email"
googleAttrs[0].type == "http://axschema.org/contact/email"
googleAttrs[0].required
googleAttrs[1].name == "firstname"
googleAttrs[1].type == "http://axschema.org/namePerson/first"
googleAttrs[1].required
googleAttrs[2].name == "lastname"
googleAttrs[2].type == "http://axschema.org/namePerson/last"
googleAttrs[2].required
def yahooAttrs = consumer.attributesToFetchFactory.createAttributeList("https://rwinch.yahoo.com/rwinch/id")
yahooAttrs[0].name == "email"
yahooAttrs[0].type == "http://schema.openid.net/contact/email"
yahooAttrs[0].required
yahooAttrs[1].name == "fullname"
yahooAttrs[1].type == "http://axschema.org/namePerson"
yahooAttrs[1].required
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login/openid"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
}
def yahooAttrs = consumer.attributesToFetchFactory.createAttributeList("https://rwinch.yahoo.com/rwinch/id")
yahooAttrs[0].name == "email"
yahooAttrs[0].type == "http://schema.openid.net/contact/email"
yahooAttrs[0].required
yahooAttrs[1].name == "fullname"
yahooAttrs[1].type == "http://axschema.org/namePerson"
yahooAttrs[1].required
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/login"
when: "fail to log in"
super.setup()
request.servletPath = "/login/openid"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/login?error"
}
@Configuration
static class OpenIDLoginAttributeExchangeConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
.attributeExchange("https://www.google.com/.*") // attribute-exchange@identifier-match
.attribute("email") // openid-attribute@name
.type("http://axschema.org/contact/email") // openid-attribute@type
.required(true) // openid-attribute@required
.count(1) // openid-attribute@count
.and()
.attribute("firstname")
.type("http://axschema.org/namePerson/first")
.required(true)
.and()
.attribute("lastname")
.type("http://axschema.org/namePerson/last")
.required(true)
.and()
.and()
.attributeExchange(".*yahoo.com.*")
.attribute("email")
.type("http://schema.openid.net/contact/email")
.required(true)
.and()
.attribute("fullname")
.type("http://axschema.org/namePerson")
.required(true)
.and()
.and()
.permitAll();
}
}
@Configuration
static class OpenIDLoginAttributeExchangeConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
.attributeExchange("https://www.google.com/.*") // attribute-exchange@identifier-match
.attribute("email") // openid-attribute@name
.type("http://axschema.org/contact/email") // openid-attribute@type
.required(true) // openid-attribute@required
.count(1) // openid-attribute@count
.and()
.attribute("firstname")
.type("http://axschema.org/namePerson/first")
.required(true)
.and()
.attribute("lastname")
.type("http://axschema.org/namePerson/last")
.required(true)
.and()
.and()
.attributeExchange(".*yahoo.com.*")
.attribute("email")
.type("http://schema.openid.net/contact/email")
.required(true)
.and()
.attribute("fullname")
.type("http://axschema.org/namePerson")
.required(true)
.and()
.and()
.permitAll();
}
}
def "http/openid-login custom"() {
setup:
loadConfig(OpenIDLoginCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/authentication/login"
when: "fail to log in"
super.setup()
request.servletPath = "/authentication/login/process"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/authentication/login?failed"
}
def "http/openid-login custom"() {
setup:
loadConfig(OpenIDLoginCustomConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getRedirectedUrl() == "http://localhost/authentication/login"
when: "fail to log in"
super.setup()
request.servletPath = "/authentication/login/process"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/authentication/login?failed"
}
@Configuration
static class OpenIDLoginCustomConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
boolean alwaysUseDefaultSuccess = true;
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
.permitAll()
.loginPage("/authentication/login") // openid-login@login-page
.failureUrl("/authentication/login?failed") // openid-login@authentication-failure-url
.loginProcessingUrl("/authentication/login/process") // openid-login@login-processing-url
.defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // openid-login@default-target-url / openid-login@always-use-default-target
}
}
@Configuration
static class OpenIDLoginCustomConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
boolean alwaysUseDefaultSuccess = true;
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
.permitAll()
.loginPage("/authentication/login") // openid-login@login-page
.failureUrl("/authentication/login?failed") // openid-login@authentication-failure-url
.loginProcessingUrl("/authentication/login/process") // openid-login@login-processing-url
.defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // openid-login@default-target-url / openid-login@always-use-default-target
}
}
def "http/openid-login custom refs"() {
when:
OpenIDLoginCustomRefsConfig.AUDS = Mock(AuthenticationUserDetailsService)
loadConfig(OpenIDLoginCustomRefsConfig)
then: "CustomWebAuthenticationDetailsSource is used"
findFilter(OpenIDAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
findAuthenticationProvider(OpenIDAuthenticationProvider).userDetailsService == OpenIDLoginCustomRefsConfig.AUDS
when: "fail to log in"
request.servletPath = "/login/openid"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/custom/failure"
}
def "http/openid-login custom refs"() {
when:
OpenIDLoginCustomRefsConfig.AUDS = Mock(AuthenticationUserDetailsService)
loadConfig(OpenIDLoginCustomRefsConfig)
then: "CustomWebAuthenticationDetailsSource is used"
findFilter(OpenIDAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
findAuthenticationProvider(OpenIDAuthenticationProvider).userDetailsService == OpenIDLoginCustomRefsConfig.AUDS
when: "fail to log in"
request.servletPath = "/login/openid"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to login error page"
response.getRedirectedUrl() == "/custom/failure"
}
@Configuration
static class OpenIDLoginCustomRefsConfig extends BaseWebConfig {
static AuthenticationUserDetailsService AUDS
@Configuration
static class OpenIDLoginCustomRefsConfig extends BaseWebConfig {
static AuthenticationUserDetailsService AUDS
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
// if using UserDetailsService wrap with new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>()
.authenticationUserDetailsService(AUDS) // openid-login@user-service-ref
.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // openid-login@authentication-failure-handler-ref
.successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // openid-login@authentication-success-handler-ref
.authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()); // openid-login@authentication-details-source-ref
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.openidLogin()
// if using UserDetailsService wrap with new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>()
.authenticationUserDetailsService(AUDS) // openid-login@user-service-ref
.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // openid-login@authentication-failure-handler-ref
.successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // openid-login@authentication-success-handler-ref
.authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()); // openid-login@authentication-details-source-ref
}
// only necessary to have easy access to the AuthenticationManager for testing/verification
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
// only necessary to have easy access to the AuthenticationManager for testing/verification
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
}
static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
}
@@ -38,78 +38,78 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
*
*/
public class NamespaceHttpPortMappingsTests extends BaseSpringSpec {
FilterChainProxy springSecurityFilterChain
MockHttpServletRequest request
MockHttpServletResponse response
MockFilterChain chain
FilterChainProxy springSecurityFilterChain
MockHttpServletRequest request
MockHttpServletResponse response
MockFilterChain chain
def setup() {
request = new MockHttpServletRequest()
request.setMethod("GET")
response = new MockHttpServletResponse()
chain = new MockFilterChain()
}
def setup() {
request = new MockHttpServletRequest()
request.setMethod("GET")
response = new MockHttpServletResponse()
chain = new MockFilterChain()
}
def "http/port-mapper works with http/intercept-url@requires-channel"() {
setup:
loadConfig(HttpInterceptUrlWithPortMapperConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
when:
request.setServletPath("/login")
request.setRequestURI("/login")
request.setServerPort(9080);
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost:9443/login"
when:
setup()
request.setServletPath("/secured/a")
request.setRequestURI("/secured/a")
request.setServerPort(9080);
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost:9443/secured/a"
when:
setup()
request.setSecure(true)
request.setScheme("https")
request.setServerPort(9443);
request.setServletPath("/user")
request.setRequestURI("/user")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "http://localhost:9080/user"
}
def "http/port-mapper works with http/intercept-url@requires-channel"() {
setup:
loadConfig(HttpInterceptUrlWithPortMapperConfig)
springSecurityFilterChain = context.getBean(FilterChainProxy)
when:
request.setServletPath("/login")
request.setRequestURI("/login")
request.setServerPort(9080);
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost:9443/login"
when:
setup()
request.setServletPath("/secured/a")
request.setRequestURI("/secured/a")
request.setServerPort(9080);
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost:9443/secured/a"
when:
setup()
request.setSecure(true)
request.setScheme("https")
request.setServerPort(9443);
request.setServletPath("/user")
request.setRequestURI("/user")
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "http://localhost:9080/user"
}
@EnableWebSecurity
static class HttpInterceptUrlWithPortMapperConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class HttpInterceptUrlWithPortMapperConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.portMapper()
.http(9080).mapsTo(9443)
.and()
.requiresChannel()
.antMatchers("/login","/secured/**").requiresSecure()
.anyRequest().requiresInsecure()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.portMapper()
.http(9080).mapsTo(9443)
.and()
.requiresChannel()
.antMatchers("/login","/secured/**").requiresSecure()
.anyRequest().requiresInsecure()
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN")
}
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN")
}
}
def login(String username="user", String role="ROLE_USER") {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
repo.loadContext(requestResponseHolder)
repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
}
def login(String username="user", String role="ROLE_USER") {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
repo.loadContext(requestResponseHolder)
repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
}
}
@@ -39,35 +39,35 @@ import org.springframework.security.web.savedrequest.RequestCache;
*
*/
public class NamespaceHttpRequestCacheTests extends BaseSpringSpec {
def "http/request-cache@ref"() {
setup:
RequestCacheRefConfig.REQUEST_CACHE = Mock(RequestCache)
when:
loadConfig(RequestCacheRefConfig)
then:
findFilter(ExceptionTranslationFilter).requestCache == RequestCacheRefConfig.REQUEST_CACHE
}
def "http/request-cache@ref"() {
setup:
RequestCacheRefConfig.REQUEST_CACHE = Mock(RequestCache)
when:
loadConfig(RequestCacheRefConfig)
then:
findFilter(ExceptionTranslationFilter).requestCache == RequestCacheRefConfig.REQUEST_CACHE
}
@Configuration
static class RequestCacheRefConfig extends BaseWebConfig {
static RequestCache REQUEST_CACHE
protected void configure(HttpSecurity http) {
http.
requestCache()
.requestCache(REQUEST_CACHE)
}
}
@Configuration
static class RequestCacheRefConfig extends BaseWebConfig {
static RequestCache REQUEST_CACHE
protected void configure(HttpSecurity http) {
http.
requestCache()
.requestCache(REQUEST_CACHE)
}
}
def "http/request-cache@ref defaults to HttpSessionRequestCache"() {
when:
loadConfig(DefaultRequestCacheRefConfig)
then:
findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
}
def "http/request-cache@ref defaults to HttpSessionRequestCache"() {
when:
loadConfig(DefaultRequestCacheRefConfig)
then:
findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
}
@Configuration
static class DefaultRequestCacheRefConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
}
}
@Configuration
static class DefaultRequestCacheRefConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) {
}
}
}
@@ -55,201 +55,201 @@ import org.springframework.test.util.ReflectionTestUtils
*
*/
public class NamespaceHttpX509Tests extends BaseSpringSpec {
def "http/x509 can authenticate"() {
setup:
X509Certificate certificate = loadCert("rod.cer")
loadConfig(X509Config)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'rod'
}
def "http/x509 can authenticate"() {
setup:
X509Certificate certificate = loadCert("rod.cer")
loadConfig(X509Config)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'rod'
}
def "http/x509"() {
when:
loadConfig(X509Config)
X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource.class == WebAuthenticationDetailsSource
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
}
def "http/x509"() {
when:
loadConfig(X509Config)
X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource.class == WebAuthenticationDetailsSource
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
}
@EnableWebSecurity
public static class X509Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
@EnableWebSecurity
public static class X509Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509();
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509();
}
}
def "http/x509@authentication-details-source-ref"() {
setup:
AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE = Mock(AuthenticationDetailsSource)
when:
loadConfig(AuthenticationDetailsSourceRefConfig)
X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource == AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
}
def "http/x509@authentication-details-source-ref"() {
setup:
AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE = Mock(AuthenticationDetailsSource)
when:
loadConfig(AuthenticationDetailsSourceRefConfig)
X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
then:
authenticationManager
filter.authenticationDetailsSource == AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE
authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
}
@EnableWebSecurity
public static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter {
static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
@EnableWebSecurity
public static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter {
static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.authenticationDetailsSource(AUTHENTICATION_DETAILS_SOURCE);
}
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.authenticationDetailsSource(AUTHENTICATION_DETAILS_SOURCE);
}
}
def "http/x509@subject-principal-regex"() {
setup:
X509Certificate certificate = loadCert("rodatexampledotcom.cer")
loadConfig(SubjectPrincipalRegexConfig)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'rod'
}
def "http/x509@subject-principal-regex"() {
setup:
X509Certificate certificate = loadCert("rodatexampledotcom.cer")
loadConfig(SubjectPrincipalRegexConfig)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'rod'
}
@EnableWebSecurity
public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
@EnableWebSecurity
public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.subjectPrincipalRegex('CN=(.*?)@example.com(?:,|$)');
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.subjectPrincipalRegex('CN=(.*?)@example.com(?:,|$)');
}
}
def "http/x509@user-service-ref"() {
setup:
X509Certificate certificate = loadCert("rodatexampledotcom.cer")
loadConfig(UserDetailsServiceRefConfig)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'customuser'
}
def "http/x509@user-service-ref"() {
setup:
X509Certificate certificate = loadCert("rodatexampledotcom.cer")
loadConfig(UserDetailsServiceRefConfig)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'customuser'
}
@EnableWebSecurity
public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
@EnableWebSecurity
public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.userDetailsService(new CustomUserDetailsService());
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.userDetailsService(new CustomUserDetailsService());
}
}
def "http/x509 custom AuthenticationUserDetailsService"() {
setup:
X509Certificate certificate = loadCert("rodatexampledotcom.cer")
loadConfig(AuthenticationUserDetailsServiceConfig)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'customuser'
}
def "http/x509 custom AuthenticationUserDetailsService"() {
setup:
X509Certificate certificate = loadCert("rodatexampledotcom.cer")
loadConfig(AuthenticationUserDetailsServiceConfig)
when:
request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
springSecurityFilterChain.doFilter(request, response, chain);
then:
response.status == 200
authentication().name == 'customuser'
}
@EnableWebSecurity
public static class AuthenticationUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
@EnableWebSecurity
public static class AuthenticationUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
inMemoryAuthentication()
.withUser("rod").password("password").roles("USER","ADMIN");
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.userDetailsService(new CustomUserDetailsService());
}
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.x509()
.userDetailsService(new CustomUserDetailsService());
}
}
def loadCert(String location) {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
certFactory.generateCertificate(Thread.currentThread().contextClassLoader.getResourceAsStream(location))
}
def loadCert(String location) {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
certFactory.generateCertificate(Thread.currentThread().contextClassLoader.getResourceAsStream(location))
}
static class CustomUserDetailsService implements UserDetailsService {
static class CustomUserDetailsService implements UserDetailsService {
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
}
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
}
}
}
static class CustomAuthenticationUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
public UserDetails loadUserDetails(
PreAuthenticatedAuthenticationToken token)
throws UsernameNotFoundException {
return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
}
}
static class CustomAuthenticationUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
public UserDetails loadUserDetails(
PreAuthenticatedAuthenticationToken token)
throws UsernameNotFoundException {
return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
}
}
def authentication() {
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication
}
def authentication() {
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication
}
}
@@ -55,333 +55,333 @@ import org.springframework.test.util.ReflectionTestUtils;
*/
public class NamespaceRememberMeTests extends BaseSpringSpec {
def "http/remember-me"() {
setup:
loadConfig(RememberMeConfig)
when: "login with remember me"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
Cookie rememberMeCookie = getRememberMeCookie()
then: "response contains remember me cookie"
rememberMeCookie != null
when: "session expires"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
MockHttpSession session = request.getSession()
then: "initialized to RememberMeAuthenticationToken"
SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
context.getAuthentication() instanceof RememberMeAuthenticationToken
when: "logout"
super.setup()
request.setSession(session)
super.setupCsrf()
request.setCookies(rememberMeCookie)
request.servletPath = "/logout"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
rememberMeCookie = getRememberMeCookie()
then: "logout cookie expired"
response.getRedirectedUrl() == "/login?logout"
rememberMeCookie.maxAge == 0
when: "use remember me after logout"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default login page"
response.getRedirectedUrl() == "http://localhost/login"
}
def "http/remember-me"() {
setup:
loadConfig(RememberMeConfig)
when: "login with remember me"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
Cookie rememberMeCookie = getRememberMeCookie()
then: "response contains remember me cookie"
rememberMeCookie != null
when: "session expires"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
MockHttpSession session = request.getSession()
then: "initialized to RememberMeAuthenticationToken"
SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
context.getAuthentication() instanceof RememberMeAuthenticationToken
when: "logout"
super.setup()
request.setSession(session)
super.setupCsrf()
request.setCookies(rememberMeCookie)
request.servletPath = "/logout"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
rememberMeCookie = getRememberMeCookie()
then: "logout cookie expired"
response.getRedirectedUrl() == "/login?logout"
rememberMeCookie.maxAge == 0
when: "use remember me after logout"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default login page"
response.getRedirectedUrl() == "http://localhost/login"
}
@Configuration
static class RememberMeConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
}
@Configuration
static class RememberMeConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
}
def "http/remember-me@services-ref"() {
setup:
RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = Mock(RememberMeServices)
when: "use custom remember-me services"
loadConfig(RememberMeServicesRefConfig)
then: "custom remember-me services used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
findFilter(UsernamePasswordAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
}
def "http/remember-me@services-ref"() {
setup:
RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = Mock(RememberMeServices)
when: "use custom remember-me services"
loadConfig(RememberMeServicesRefConfig)
then: "custom remember-me services used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
findFilter(UsernamePasswordAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
}
@Configuration
static class RememberMeServicesRefConfig extends BaseWebConfig {
static RememberMeServices REMEMBER_ME_SERVICES
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.rememberMeServices(REMEMBER_ME_SERVICES)
}
}
@Configuration
static class RememberMeServicesRefConfig extends BaseWebConfig {
static RememberMeServices REMEMBER_ME_SERVICES
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.rememberMeServices(REMEMBER_ME_SERVICES)
}
}
def "http/remember-me@authentication-success-handler-ref"() {
setup:
AuthSuccessConfig.SUCCESS_HANDLER = Mock(AuthenticationSuccessHandler)
when: "use custom success handler"
loadConfig(AuthSuccessConfig)
then: "custom remember-me success handler is used"
findFilter(RememberMeAuthenticationFilter).successHandler == AuthSuccessConfig.SUCCESS_HANDLER
}
def "http/remember-me@authentication-success-handler-ref"() {
setup:
AuthSuccessConfig.SUCCESS_HANDLER = Mock(AuthenticationSuccessHandler)
when: "use custom success handler"
loadConfig(AuthSuccessConfig)
then: "custom remember-me success handler is used"
findFilter(RememberMeAuthenticationFilter).successHandler == AuthSuccessConfig.SUCCESS_HANDLER
}
@Configuration
static class AuthSuccessConfig extends BaseWebConfig {
static AuthenticationSuccessHandler SUCCESS_HANDLER
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.authenticationSuccessHandler(SUCCESS_HANDLER)
}
}
@Configuration
static class AuthSuccessConfig extends BaseWebConfig {
static AuthenticationSuccessHandler SUCCESS_HANDLER
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.authenticationSuccessHandler(SUCCESS_HANDLER)
}
}
// http/remember-me@data-source-ref is not supported directly. Instead use http/remember-me@token-repository-ref example
// http/remember-me@data-source-ref is not supported directly. Instead use http/remember-me@token-repository-ref example
def "http/remember-me@key"() {
when: "use custom key"
loadConfig(KeyConfig)
AuthenticationManager authManager = context.getBean(AuthenticationManager)
then: "custom key services used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.key == "KeyConfig"
authManager.authenticate(new RememberMeAuthenticationToken("KeyConfig", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
}
def "http/remember-me@key"() {
when: "use custom key"
loadConfig(KeyConfig)
AuthenticationManager authManager = context.getBean(AuthenticationManager)
then: "custom key services used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.key == "KeyConfig"
authManager.authenticate(new RememberMeAuthenticationToken("KeyConfig", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
}
@Configuration
static class KeyConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.key("KeyConfig")
}
@Configuration
static class KeyConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.key("KeyConfig")
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
}
// http/remember-me@services-alias is not supported use standard aliasing instead (i.e. @Bean("alias"))
// http/remember-me@services-alias is not supported use standard aliasing instead (i.e. @Bean("alias"))
def "http/remember-me@token-repository-ref"() {
setup:
TokenRepositoryRefConfig.TOKEN_REPOSITORY = Mock(PersistentTokenRepository)
when: "use custom token services"
loadConfig(TokenRepositoryRefConfig)
then: "custom token services used with PersistentTokenBasedRememberMeServices"
PersistentTokenBasedRememberMeServices rememberMeServices = findFilter(RememberMeAuthenticationFilter).rememberMeServices
findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenRepository == TokenRepositoryRefConfig.TOKEN_REPOSITORY
}
def "http/remember-me@token-repository-ref"() {
setup:
TokenRepositoryRefConfig.TOKEN_REPOSITORY = Mock(PersistentTokenRepository)
when: "use custom token services"
loadConfig(TokenRepositoryRefConfig)
then: "custom token services used with PersistentTokenBasedRememberMeServices"
PersistentTokenBasedRememberMeServices rememberMeServices = findFilter(RememberMeAuthenticationFilter).rememberMeServices
findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenRepository == TokenRepositoryRefConfig.TOKEN_REPOSITORY
}
@Configuration
static class TokenRepositoryRefConfig extends BaseWebConfig {
static PersistentTokenRepository TOKEN_REPOSITORY
protected void configure(HttpSecurity http) throws Exception {
// JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl()
// tokenRepository.setDataSource(dataSource);
http
.formLogin()
.and()
.rememberMe()
.tokenRepository(TOKEN_REPOSITORY)
}
}
@Configuration
static class TokenRepositoryRefConfig extends BaseWebConfig {
static PersistentTokenRepository TOKEN_REPOSITORY
protected void configure(HttpSecurity http) throws Exception {
// JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl()
// tokenRepository.setDataSource(dataSource);
http
.formLogin()
.and()
.rememberMe()
.tokenRepository(TOKEN_REPOSITORY)
}
}
def "http/remember-me@token-validity-seconds"() {
when: "use token validity"
loadConfig(TokenValiditySecondsConfig)
then: "custom token validity used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == 1
}
def "http/remember-me@token-validity-seconds"() {
when: "use token validity"
loadConfig(TokenValiditySecondsConfig)
then: "custom token validity used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == 1
}
@Configuration
static class TokenValiditySecondsConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.tokenValiditySeconds(1)
}
}
@Configuration
static class TokenValiditySecondsConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.tokenValiditySeconds(1)
}
}
def "http/remember-me@token-validity-seconds default"() {
when: "use token validity"
loadConfig(DefaultTokenValiditySecondsConfig)
then: "custom token validity used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == AbstractRememberMeServices.TWO_WEEKS_S
}
def "http/remember-me@token-validity-seconds default"() {
when: "use token validity"
loadConfig(DefaultTokenValiditySecondsConfig)
then: "custom token validity used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == AbstractRememberMeServices.TWO_WEEKS_S
}
@Configuration
static class DefaultTokenValiditySecondsConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
}
}
@Configuration
static class DefaultTokenValiditySecondsConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
}
}
def "http/remember-me@use-secure-cookie"() {
when: "use secure cookies = true"
loadConfig(UseSecureCookieConfig)
then: "secure cookies will be used"
ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == true
}
def "http/remember-me@use-secure-cookie"() {
when: "use secure cookies = true"
loadConfig(UseSecureCookieConfig)
then: "secure cookies will be used"
ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == true
}
@Configuration
static class UseSecureCookieConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.useSecureCookie(true)
}
}
@Configuration
static class UseSecureCookieConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.useSecureCookie(true)
}
}
def "http/remember-me@remember-me-parameter"() {
when: "use custom rememberMeParameter"
loadConfig(RememberMeParameterConfig)
then: "custom rememberMeParameter will be used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.parameter == "rememberMe"
}
def "http/remember-me@remember-me-parameter"() {
when: "use custom rememberMeParameter"
loadConfig(RememberMeParameterConfig)
then: "custom rememberMeParameter will be used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.parameter == "rememberMe"
}
@Configuration
static class RememberMeParameterConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.rememberMeParameter("rememberMe")
}
}
@Configuration
static class RememberMeParameterConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.rememberMeParameter("rememberMe")
}
}
// SEC-2880
def "http/remember-me@remember-me-cookie"() {
when: "use custom rememberMeCookieName"
loadConfig(RememberMeCookieNameConfig)
then: "custom rememberMeCookieName will be used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.cookieName == "rememberMe"
}
// SEC-2880
def "http/remember-me@remember-me-cookie"() {
when: "use custom rememberMeCookieName"
loadConfig(RememberMeCookieNameConfig)
then: "custom rememberMeCookieName will be used"
findFilter(RememberMeAuthenticationFilter).rememberMeServices.cookieName == "rememberMe"
}
@Configuration
static class RememberMeCookieNameConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.rememberMeCookieName("rememberMe")
}
}
@Configuration
static class RememberMeCookieNameConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.rememberMeCookieName("rememberMe")
}
}
def "http/remember-me@use-secure-cookie defaults"() {
when: "use secure cookies not specified"
loadConfig(DefaultUseSecureCookieConfig)
then: "secure cookies will be null (use secure if the request is secure)"
ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == null
}
def "http/remember-me@use-secure-cookie defaults"() {
when: "use secure cookies not specified"
loadConfig(DefaultUseSecureCookieConfig)
then: "secure cookies will be null (use secure if the request is secure)"
ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == null
}
@Configuration
static class DefaultUseSecureCookieConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
}
}
@Configuration
static class DefaultUseSecureCookieConfig extends BaseWebConfig {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
}
}
def "http/remember-me defaults UserDetailsService with custom UserDetailsService"() {
setup:
DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
loadConfig(DefaultsUserDetailsServiceWithDaoConfig)
when:
request.setCookies(createRememberMeCookie())
springSecurityFilterChain.doFilter(request, response, chain)
then: "RememberMeServices defaults to the custom UserDetailsService"
1 * DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE.loadUserByUsername("user")
}
def "http/remember-me defaults UserDetailsService with custom UserDetailsService"() {
setup:
DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
loadConfig(DefaultsUserDetailsServiceWithDaoConfig)
when:
request.setCookies(createRememberMeCookie())
springSecurityFilterChain.doFilter(request, response, chain)
then: "RememberMeServices defaults to the custom UserDetailsService"
1 * DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE.loadUserByUsername("user")
}
@EnableWebSecurity
static class DefaultsUserDetailsServiceWithDaoConfig extends WebSecurityConfigurerAdapter {
static UserDetailsService USERDETAILS_SERVICE
@EnableWebSecurity
static class DefaultsUserDetailsServiceWithDaoConfig extends WebSecurityConfigurerAdapter {
static UserDetailsService USERDETAILS_SERVICE
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
}
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(USERDETAILS_SERVICE);
}
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(USERDETAILS_SERVICE);
}
}
def "http/remember-me@user-service-ref"() {
setup:
UserServiceRefConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
when: "use custom UserDetailsService"
loadConfig(UserServiceRefConfig)
then: "custom UserDetailsService is used"
ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "userDetailsService") == UserServiceRefConfig.USERDETAILS_SERVICE
}
def "http/remember-me@user-service-ref"() {
setup:
UserServiceRefConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
when: "use custom UserDetailsService"
loadConfig(UserServiceRefConfig)
then: "custom UserDetailsService is used"
ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "userDetailsService") == UserServiceRefConfig.USERDETAILS_SERVICE
}
@Configuration
static class UserServiceRefConfig extends BaseWebConfig {
static UserDetailsService USERDETAILS_SERVICE
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.userDetailsService(USERDETAILS_SERVICE)
}
}
@Configuration
static class UserServiceRefConfig extends BaseWebConfig {
static UserDetailsService USERDETAILS_SERVICE
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.rememberMe()
.userDetailsService(USERDETAILS_SERVICE)
}
}
Cookie createRememberMeCookie() {
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)
Cookie createRememberMeCookie() {
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)
MockFilterChain chain = new MockFilterChain()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request, response, chain)
response.getCookie("remember-me")
}
MockFilterChain chain = new MockFilterChain()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request, response, chain)
response.getCookie("remember-me")
}
Cookie getRememberMeCookie(String cookieName="remember-me") {
response.getCookie(cookieName)
}
Cookie getRememberMeCookie(String cookieName="remember-me") {
response.getCookie(cookieName)
}
}
@@ -30,40 +30,40 @@ import org.springframework.security.web.util.matcher.RequestMatcher
*
*/
class PermitAllSupportTests extends BaseSpringSpec {
def "PermitAllSupport.ExactUrlRequestMatcher"() {
expect:
RequestMatcher matcher = new PermitAllSupport.ExactUrlRequestMatcher(processUrl)
matcher.matches(new MockHttpServletRequest(requestURI:requestURI,contextPath:contextPath,queryString: query)) == matches
where:
processUrl | requestURI | contextPath | query | matches
"/login" | "/sample/login" | "/sample" | null | true
"/login" | "/sample/login" | "/sample" | "error" | false
"/login?error" | "/sample/login" | "/sample" | "error" | true
}
def "PermitAllSupport.ExactUrlRequestMatcher"() {
expect:
RequestMatcher matcher = new PermitAllSupport.ExactUrlRequestMatcher(processUrl)
matcher.matches(new MockHttpServletRequest(requestURI:requestURI,contextPath:contextPath,queryString: query)) == matches
where:
processUrl | requestURI | contextPath | query | matches
"/login" | "/sample/login" | "/sample" | null | true
"/login" | "/sample/login" | "/sample" | "error" | false
"/login?error" | "/sample/login" | "/sample" | "error" | true
}
def "PermitAllSupport throws Exception when authorizedUrls() not invoked"() {
when:
loadConfig(NoAuthorizedUrlsConfig)
then:
BeanCreationException e = thrown()
e.message.contains "permitAll only works with HttpSecurity.authorizeRequests"
def "PermitAllSupport throws Exception when authorizedUrls() not invoked"() {
when:
loadConfig(NoAuthorizedUrlsConfig)
then:
BeanCreationException e = thrown()
e.message.contains "permitAll only works with HttpSecurity.authorizeRequests"
}
}
@EnableWebSecurity
static class NoAuthorizedUrlsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class NoAuthorizedUrlsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.permitAll()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.permitAll()
}
}
}
@@ -36,28 +36,28 @@ import org.springframework.security.web.session.SessionManagementFilter
*/
class PortMapperConfigurerTests extends BaseSpringSpec {
def "invoke portMapper twice does not override"() {
setup:
loadConfig(InvokeTwiceDoesNotOverride)
request.setServerPort(543)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost:123"
}
def "invoke portMapper twice does not override"() {
setup:
loadConfig(InvokeTwiceDoesNotOverride)
request.setServerPort(543)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl == "https://localhost:123"
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.portMapper()
.http(543).mapsTo(123)
.and()
.portMapper()
}
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.portMapper()
.http(543).mapsTo(123)
.and()
.portMapper()
}
}
}
@@ -48,151 +48,151 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
*/
public class RememberMeConfigurerTests extends BaseSpringSpec {
def "rememberMe() null UserDetailsService provides meaningful error"() {
setup: "Load Config without UserDetailsService specified"
loadConfig(NullUserDetailsConfig)
when:
request.setCookies(createRememberMeCookie())
springSecurityFilterChain.doFilter(request, response, chain)
then: "A good error message is provided"
Exception success = thrown()
success.message.contains "UserDetailsService is required"
}
def "rememberMe() null UserDetailsService provides meaningful error"() {
setup: "Load Config without UserDetailsService specified"
loadConfig(NullUserDetailsConfig)
when:
request.setCookies(createRememberMeCookie())
springSecurityFilterChain.doFilter(request, response, chain)
then: "A good error message is provided"
Exception success = thrown()
success.message.contains "UserDetailsService is required"
}
@EnableWebSecurity
static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
@EnableWebSecurity
static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
provider.userDetailsService = new InMemoryUserDetailsManager([user])
auth
.authenticationProvider(provider)
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
provider.userDetailsService = new InMemoryUserDetailsManager([user])
auth
.authenticationProvider(provider)
}
}
def "rememberMe ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
when:
http
.rememberMe()
.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
.and()
.build()
def "rememberMe ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
when:
http
.rememberMe()
.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
.and()
.build()
then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as RememberMeAuthenticationFilter) >> {RememberMeAuthenticationFilter o -> o}
}
then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as RememberMeAuthenticationFilter) >> {RememberMeAuthenticationFilter o -> o}
}
def "invoke rememberMe twice does not reset"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
when:
http
.rememberMe()
.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
.and()
.rememberMe()
then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
http.getConfigurer(RememberMeConfigurer).userDetailsService != null
}
def "invoke rememberMe twice does not reset"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
when:
http
.rememberMe()
.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
.and()
.rememberMe()
then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
http.getConfigurer(RememberMeConfigurer).userDetailsService != null
}
def "http/remember-me with Global AuthenticationManagerBuilder"() {
setup:
loadConfig(RememberMeConfig)
when: "login with remember me"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
Cookie rememberMeCookie = getRememberMeCookie()
then: "response contains remember me cookie"
rememberMeCookie != null
when: "session expires"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
MockHttpSession session = request.getSession()
then: "initialized to RememberMeAuthenticationToken"
SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
context.getAuthentication() instanceof RememberMeAuthenticationToken
when: "logout"
super.setup()
request.setSession(session)
super.setupCsrf()
request.setCookies(rememberMeCookie)
request.servletPath = "/logout"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
rememberMeCookie = getRememberMeCookie()
then: "logout cookie expired"
response.getRedirectedUrl() == "/login?logout"
rememberMeCookie.maxAge == 0
when: "use remember me after logout"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default login page"
response.getRedirectedUrl() == "http://localhost/login"
}
def "http/remember-me with Global AuthenticationManagerBuilder"() {
setup:
loadConfig(RememberMeConfig)
when: "login with remember me"
super.setup()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request,response,chain)
Cookie rememberMeCookie = getRememberMeCookie()
then: "response contains remember me cookie"
rememberMeCookie != null
when: "session expires"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
MockHttpSession session = request.getSession()
then: "initialized to RememberMeAuthenticationToken"
SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
context.getAuthentication() instanceof RememberMeAuthenticationToken
when: "logout"
super.setup()
request.setSession(session)
super.setupCsrf()
request.setCookies(rememberMeCookie)
request.servletPath = "/logout"
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
rememberMeCookie = getRememberMeCookie()
then: "logout cookie expired"
response.getRedirectedUrl() == "/login?logout"
rememberMeCookie.maxAge == 0
when: "use remember me after logout"
super.setup()
request.setCookies(rememberMeCookie)
request.requestURI = "/abc"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default login page"
response.getRedirectedUrl() == "http://localhost/login"
}
@EnableWebSecurity
static class RememberMeConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
@EnableWebSecurity
static class RememberMeConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.formLogin()
.and()
.rememberMe()
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
Cookie createRememberMeCookie() {
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)
Cookie createRememberMeCookie() {
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)
MockFilterChain chain = new MockFilterChain()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request, response, chain)
response.getCookie("remember-me")
}
MockFilterChain chain = new MockFilterChain()
request.servletPath = "/login"
request.method = "POST"
request.parameters.username = ["user"] as String[]
request.parameters.password = ["password"] as String[]
request.parameters.'remember-me' = ["true"] as String[]
springSecurityFilterChain.doFilter(request, response, chain)
response.getCookie("remember-me")
}
Cookie getRememberMeCookie(String cookieName="remember-me") {
response.getCookie(cookieName)
}
Cookie getRememberMeCookie(String cookieName="remember-me") {
response.getCookie(cookieName)
}
}
@@ -36,149 +36,149 @@ import spock.lang.Unroll;
*/
class RequestCacheConfigurerTests extends BaseSpringSpec {
def "requestCache ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.requestCache()
.and()
.build()
def "requestCache ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.requestCache()
.and()
.build()
then: "RequestCacheAwareFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as RequestCacheAwareFilter) >> {RequestCacheAwareFilter o -> o}
}
then: "RequestCacheAwareFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as RequestCacheAwareFilter) >> {RequestCacheAwareFilter o -> o}
}
def "invoke requestCache twice does not reset"() {
setup:
RequestCache RC = Mock()
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.requestCache()
.requestCache(RC)
.and()
.requestCache()
def "invoke requestCache twice does not reset"() {
setup:
RequestCache RC = Mock()
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.requestCache()
.requestCache(RC)
.and()
.requestCache()
then:
http.getSharedObject(RequestCache) == RC
}
then:
http.getSharedObject(RequestCache) == RC
}
def "RequestCache disables faviocon.ico"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.servletPath = "/favicon.ico"
request.requestURI = "/favicon.ico"
request.method = "GET"
when: "request favicon.ico"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default URL since it was favicon.ico"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "RequestCache disables faviocon.ico"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.servletPath = "/favicon.ico"
request.requestURI = "/favicon.ico"
request.method = "GET"
when: "request favicon.ico"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default URL since it was favicon.ico"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "SEC-2321: RequestCache disables application/json"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE)
request.method = "GET"
request.servletPath = "/messages"
request.requestURI = "/messages"
when: "request application/json"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default URL since it was application/json. This is desirable since JSON requests are typically not invoked directly from the browser and we don't want the browser to replay them"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "SEC-2321: RequestCache disables application/json"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE)
request.method = "GET"
request.servletPath = "/messages"
request.requestURI = "/messages"
when: "request application/json"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default URL since it was application/json. This is desirable since JSON requests are typically not invoked directly from the browser and we don't want the browser to replay them"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "SEC-2321: RequestCache disables X-Requested-With"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.addHeader("X-Requested-With", "XMLHttpRequest")
request.method = "GET"
request.servletPath = "/messages"
request.requestURI = "/messages"
when: "request X-Requested-With"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default URL since it was X-Requested-With"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
def "SEC-2321: RequestCache disables X-Requested-With"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.addHeader("X-Requested-With", "XMLHttpRequest")
request.method = "GET"
request.servletPath = "/messages"
request.requestURI = "/messages"
when: "request X-Requested-With"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to the login page"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/login"
when: "authenticate successfully"
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to default URL since it was X-Requested-With"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "/"
}
@Unroll
def "RequestCache saves #headerName: #headerValue"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.addHeader(headerName, headerValue)
request.method = "GET"
request.servletPath = "/messages"
request.requestURI = "/messages"
when: "request content type"
springSecurityFilterChain.doFilter(request,response,chain)
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to saved URL"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/messages"
where:
headerName << ["Accept", "Accept", "Accept", "X-Requested-With"]
headerValue << [MediaType.ALL_VALUE, MediaType.TEXT_HTML, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","com.android"]
@Unroll
def "RequestCache saves #headerName: #headerValue"() {
setup:
loadConfig(RequestCacheDefautlsConfig)
request.addHeader(headerName, headerValue)
request.method = "GET"
request.servletPath = "/messages"
request.requestURI = "/messages"
when: "request content type"
springSecurityFilterChain.doFilter(request,response,chain)
super.setupWeb(request.session)
request.servletPath = "/login"
request.setParameter("username","user")
request.setParameter("password","password")
request.method = "POST"
springSecurityFilterChain.doFilter(request,response,chain)
then: "sent to saved URL"
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
response.redirectedUrl == "http://localhost/messages"
where:
headerName << ["Accept", "Accept", "Accept", "X-Requested-With"]
headerValue << [MediaType.ALL_VALUE, MediaType.TEXT_HTML, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","com.android"]
}
}
@EnableWebSecurity
static class RequestCacheDefautlsConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class RequestCacheDefautlsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
}
@@ -51,34 +51,34 @@ import spock.lang.Unroll;
class RequestMatcherConfigurerTests extends BaseSpringSpec {
@Unroll
def "SEC-2908 - multiple invocations of authorizeRequests() chains #path"(def path) {
setup:
loadConfig(Sec2908Config)
request.servletPath = path
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
where:
path << ['/oauth/abc','/api/abc']
}
@Unroll
def "SEC-2908 - multiple invocations of authorizeRequests() chains #path"(def path) {
setup:
loadConfig(Sec2908Config)
request.servletPath = path
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.status == HttpServletResponse.SC_FORBIDDEN
where:
path << ['/oauth/abc','/api/abc']
}
@Configuration
@EnableWebSecurity
static class Sec2908Config extends WebSecurityConfigurerAdapter {
@Configuration
@EnableWebSecurity
static class Sec2908Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/api/**")
.and()
.requestMatchers()
.antMatchers("/oauth/**")
.and()
.authorizeRequests()
.anyRequest().denyAll();
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/api/**")
.and()
.requestMatchers()
.antMatchers("/oauth/**")
.and()
.authorizeRequests()
.anyRequest().denyAll();
}
}
}
@@ -31,40 +31,40 @@ import org.springframework.security.web.context.SecurityContextRepository
*/
class SecurityContextConfigurerTests extends BaseSpringSpec {
def "securityContext ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.securityContext()
.and()
.build()
def "securityContext ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.securityContext()
.and()
.build()
then: "SecurityContextPersistenceFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as SecurityContextPersistenceFilter) >> {SecurityContextPersistenceFilter o -> o}
}
then: "SecurityContextPersistenceFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as SecurityContextPersistenceFilter) >> {SecurityContextPersistenceFilter o -> o}
}
def "invoke securityContext twice does not override"() {
setup:
InvokeTwiceDoesNotOverrideConfig.SCR = Mock(SecurityContextRepository)
when:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
then:
findFilter(SecurityContextPersistenceFilter).repo == InvokeTwiceDoesNotOverrideConfig.SCR
}
def "invoke securityContext twice does not override"() {
setup:
InvokeTwiceDoesNotOverrideConfig.SCR = Mock(SecurityContextRepository)
when:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
then:
findFilter(SecurityContextPersistenceFilter).repo == InvokeTwiceDoesNotOverrideConfig.SCR
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static SecurityContextRepository SCR
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static SecurityContextRepository SCR
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.securityContext()
.securityContextRepository(SCR)
.and()
.securityContext()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.securityContext()
.securityContextRepository(SCR)
.and()
.securityContext()
}
}
}
@@ -36,116 +36,116 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
*/
class ServletApiConfigurerTests extends BaseSpringSpec {
def "servletApi ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.servletApi()
.and()
.build()
def "servletApi ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.servletApi()
.and()
.build()
then: "SecurityContextHolderAwareRequestFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as SecurityContextHolderAwareRequestFilter) >> {SecurityContextHolderAwareRequestFilter o -> o}
}
then: "SecurityContextHolderAwareRequestFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as SecurityContextHolderAwareRequestFilter) >> {SecurityContextHolderAwareRequestFilter o -> o}
}
def "SecurityContextHolderAwareRequestFilter properties set"() {
when:
loadConfig(ServletApiConfig)
SecurityContextHolderAwareRequestFilter filter = findFilter(SecurityContextHolderAwareRequestFilter)
then: "SEC-2215: authenticationManager != null"
filter.authenticationManager != null
and: "authenticationEntryPoint != null"
filter.authenticationEntryPoint != null
and: "requestFactory != null"
filter.requestFactory != null
and: "logoutHandlers populated"
filter.logoutHandlers.collect { it.class } == [CsrfLogoutHandler, SecurityContextLogoutHandler]
}
def "SecurityContextHolderAwareRequestFilter properties set"() {
when:
loadConfig(ServletApiConfig)
SecurityContextHolderAwareRequestFilter filter = findFilter(SecurityContextHolderAwareRequestFilter)
then: "SEC-2215: authenticationManager != null"
filter.authenticationManager != null
and: "authenticationEntryPoint != null"
filter.authenticationEntryPoint != null
and: "requestFactory != null"
filter.requestFactory != null
and: "logoutHandlers populated"
filter.logoutHandlers.collect { it.class } == [CsrfLogoutHandler, SecurityContextLogoutHandler]
}
@CompileStatic
@EnableWebSecurity
static class ServletApiConfig extends WebSecurityConfigurerAdapter {
@CompileStatic
@EnableWebSecurity
static class ServletApiConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint = customEntryPoint"() {
setup:
CustomEntryPointConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
when: "load config with customEntryPoint"
loadConfig(CustomEntryPointConfig)
then: "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint == customEntryPoint"
findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == CustomEntryPointConfig.ENTRYPOINT
}
def "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint = customEntryPoint"() {
setup:
CustomEntryPointConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
when: "load config with customEntryPoint"
loadConfig(CustomEntryPointConfig)
then: "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint == customEntryPoint"
findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == CustomEntryPointConfig.ENTRYPOINT
}
@EnableWebSecurity
static class CustomEntryPointConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRYPOINT
@EnableWebSecurity
static class CustomEntryPointConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRYPOINT
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(ENTRYPOINT)
.and()
.formLogin()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(ENTRYPOINT)
.and()
.formLogin()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
}
}
def "invoke servletApi twice does not override"() {
setup:
InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
when:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
then:
findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT
}
def "invoke servletApi twice does not override"() {
setup:
InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
when:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
then:
findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRYPOINT
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
static AuthenticationEntryPoint ENTRYPOINT
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(ENTRYPOINT)
.and()
.exceptionHandling()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(ENTRYPOINT)
.and()
.exceptionHandling()
}
}
def "use sharedObject trustResolver"() {
setup:
SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(SharedTrustResolverConfig)
then:
findFilter(SecurityContextHolderAwareRequestFilter).trustResolver == SharedTrustResolverConfig.TR
}
def "use sharedObject trustResolver"() {
setup:
SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(SharedTrustResolverConfig)
then:
findFilter(SecurityContextHolderAwareRequestFilter).trustResolver == SharedTrustResolverConfig.TR
}
@EnableWebSecurity
static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
static AuthenticationTrustResolver TR
@EnableWebSecurity
static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
static AuthenticationTrustResolver TR
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.setSharedObject(AuthenticationTrustResolver, TR)
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.setSharedObject(AuthenticationTrustResolver, TR)
}
}
}
@@ -32,48 +32,48 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
*/
public class UrlAuthorizationsTests extends BaseSpringSpec {
def "hasAnyAuthority('ROLE_USER')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
then:
expression == ["ROLE_USER"]
}
def "hasAnyAuthority('ROLE_USER')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
then:
expression == ["ROLE_USER"]
}
def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
then:
expression == ["ROLE_USER","ROLE_ADMIN"]
}
def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
then:
expression == ["ROLE_USER","ROLE_ADMIN"]
}
def "hasAnyRole('USER')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyRole("USER")
then:
expression == ["ROLE_USER"]
}
def "hasAnyRole('USER')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyRole("USER")
then:
expression == ["ROLE_USER"]
}
def "hasAnyRole('ROLE_USER','ROLE_ADMIN')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
then:
expression == ["ROLE_USER","ROLE_ADMIN"]
}
def "hasAnyRole('ROLE_USER','ROLE_ADMIN')"() {
when:
def expression = UrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
then:
expression == ["ROLE_USER","ROLE_ADMIN"]
}
def "uses AffirmativeBased AccessDecisionManager"() {
when: "Load Config with no specific AccessDecisionManager"
loadConfig(NoSpecificAccessDecessionManagerConfig)
then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
}
def "uses AffirmativeBased AccessDecisionManager"() {
when: "Load Config with no specific AccessDecisionManager"
loadConfig(NoSpecificAccessDecessionManagerConfig)
then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
}
@EnableWebSecurity
static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.apply(new UrlAuthorizationConfigurer()).getRegistry()
.antMatchers("/a").hasRole("ADMIN")
.anyRequest().hasRole("USER")
}
}
@EnableWebSecurity
static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.apply(new UrlAuthorizationConfigurer()).getRegistry()
.antMatchers("/a").hasRole("ADMIN")
.anyRequest().hasRole("USER")
}
}
}
@@ -30,31 +30,31 @@ import org.springframework.security.web.authentication.preauth.x509.X509Authenti
*/
class X509ConfigurerTests extends BaseSpringSpec {
def "x509 ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.x509()
.and()
.build()
def "x509 ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.x509()
.and()
.build()
then: "X509AuthenticationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as X509AuthenticationFilter) >> {X509AuthenticationFilter o -> o}
}
then: "X509AuthenticationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as X509AuthenticationFilter) >> {X509AuthenticationFilter o -> o}
}
def "invoke x509 twice does not override"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.x509()
.subjectPrincipalRegex(".*")
.and()
.x509()
then:
http.getConfigurer(X509Configurer).subjectPrincipalRegex == ".*"
}
def "invoke x509 twice does not override"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
when:
http
.x509()
.subjectPrincipalRegex(".*")
.and()
.x509()
then:
http.getConfigurer(X509Configurer).subjectPrincipalRegex == ".*"
}
}
@@ -34,53 +34,53 @@ import org.springframework.security.openid.OpenIDAuthenticationToken
*/
class OpenIDLoginConfigurerTests extends BaseSpringSpec {
def "openidLogin ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
when:
http
.openidLogin()
.authenticationUserDetailsService(new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>(uds))
.and()
.build()
def "openidLogin ObjectPostProcessor"() {
setup:
AnyObjectPostProcessor opp = Mock()
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
when:
http
.openidLogin()
.authenticationUserDetailsService(new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>(uds))
.and()
.build()
then: "OpenIDAuthenticationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as OpenIDAuthenticationFilter) >> {OpenIDAuthenticationFilter o -> o}
and: "OpenIDAuthenticationProvider is registered with LifecycleManager"
1 * opp.postProcess(_ as OpenIDAuthenticationProvider) >> {OpenIDAuthenticationProvider o -> o}
}
then: "OpenIDAuthenticationFilter is registered with LifecycleManager"
1 * opp.postProcess(_ as OpenIDAuthenticationFilter) >> {OpenIDAuthenticationFilter o -> o}
and: "OpenIDAuthenticationProvider is registered with LifecycleManager"
1 * opp.postProcess(_ as OpenIDAuthenticationProvider) >> {OpenIDAuthenticationProvider o -> o}
}
def "invoke openidLogin twice does not override"() {
setup:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl.endsWith("/login/custom")
def "invoke openidLogin twice does not override"() {
setup:
loadConfig(InvokeTwiceDoesNotOverrideConfig)
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.redirectedUrl.endsWith("/login/custom")
}
}
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
@EnableWebSecurity
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.openidLogin()
.loginPage("/login/custom")
.and()
.openidLogin()
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.openidLogin()
.loginPage("/login/custom")
.and()
.openidLogin()
}
}
}
@@ -22,18 +22,18 @@ import org.springframework.security.web.debug.DebugFilter;
class SecurityDebugBeanFactoryPostProcessorTest extends AbstractHttpConfigTests {
// SEC-1885
def 'SEC-1885 - SecurityDebugBeanFactoryPostProcessor works when dependencies have Autowired constructor'() {
when: 'debug used and FilterChainProxy has dependency with @Autowired constructor'
xml.debug()
httpAutoConfig {}
xml.'authentication-manager'() {
'authentication-provider'('ref': 'authProvider')
}
xml.'context:component-scan'('base-package':'org.springframework.security.config.debug')
createAppContext('')
then: 'TestAuthenticationProvider.<init>() is not thrown'
appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN) instanceof DebugFilter
appContext.getBean(BeanIds.FILTER_CHAIN_PROXY) instanceof FilterChainProxy
}
// SEC-1885
def 'SEC-1885 - SecurityDebugBeanFactoryPostProcessor works when dependencies have Autowired constructor'() {
when: 'debug used and FilterChainProxy has dependency with @Autowired constructor'
xml.debug()
httpAutoConfig {}
xml.'authentication-manager'() {
'authentication-provider'('ref': 'authProvider')
}
xml.'context:component-scan'('base-package':'org.springframework.security.config.debug')
createAppContext('')
then: 'TestAuthenticationProvider.<init>() is not thrown'
appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN) instanceof DebugFilter
appContext.getBean(BeanIds.FILTER_CHAIN_PROXY) instanceof FilterChainProxy
}
}
@@ -10,104 +10,104 @@ import org.springframework.mock.web.MockHttpServletResponse
*/
class FormLoginBeanDefinitionParserTests extends AbstractHttpConfigTests {
def 'form-login default login page'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def 'form-login default login page'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form></body></html>"""
}
}
def 'form-login default login page custom attributes'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
def 'form-login default login page custom attributes'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login_custom' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form></body></html>"""
}
}
def 'openid-login default login page'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
'openid-login'()
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def 'openid-login default login page'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
'openid-login'()
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
<table>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form></body></html>"""
}
}
def 'openid-login default login page custom attributes'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
'openid-login'('login-processing-url':'/login_custom')
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
def 'openid-login default login page custom attributes'() {
setup:
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
httpAutoConfig {
'openid-login'('login-processing-url':'/login_custom')
csrf(disabled:true)
}
createAppContext()
when:
springSecurityFilterChain.doFilter(request,response,chain)
then:
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
<table>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login_custom' method='POST'>
<table>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form></body></html>"""
}
}
}
@@ -45,101 +45,101 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
*/
class SecurityContextHolderAwareRequestConfigTests extends AbstractHttpConfigTests {
def withAutoConfig() {
httpAutoConfig () {
csrf(disabled:true)
}
createAppContext(AUTH_PROVIDER_XML)
def withAutoConfig() {
httpAutoConfig () {
csrf(disabled:true)
}
createAppContext(AUTH_PROVIDER_XML)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers.size() == 1
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
}
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers.size() == 1
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
}
def explicitEntryPoint() {
xml.http() {
'http-basic'('entry-point-ref': 'ep')
}
bean('ep', BasicAuthenticationEntryPoint.class.name, ['realmName':'whocares'],[:])
createAppContext(AUTH_PROVIDER_XML)
def explicitEntryPoint() {
xml.http() {
'http-basic'('entry-point-ref': 'ep')
}
bean('ep', BasicAuthenticationEntryPoint.class.name, ['realmName':'whocares'],[:])
createAppContext(AUTH_PROVIDER_XML)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
expect:
securityContextAwareFilter.authenticationEntryPoint == getFilter(ExceptionTranslationFilter).authenticationEntryPoint
securityContextAwareFilter.authenticationManager == getFilter(BasicAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers == null
}
expect:
securityContextAwareFilter.authenticationEntryPoint == getFilter(ExceptionTranslationFilter).authenticationEntryPoint
securityContextAwareFilter.authenticationManager == getFilter(BasicAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers == null
}
def formLogin() {
xml.http() {
'form-login'()
}
createAppContext(AUTH_PROVIDER_XML)
def formLogin() {
xml.http() {
'form-login'()
}
createAppContext(AUTH_PROVIDER_XML)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers == null
}
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers == null
}
def multiHttp() {
xml.http('authentication-manager-ref' : 'authManager', 'pattern' : '/first/**') {
'form-login'('login-page' : '/login')
'logout'('invalidate-session' : 'true')
csrf(disabled:true)
}
xml.http('authentication-manager-ref' : 'authManager2') {
'form-login'('login-page' : '/login2')
'logout'('invalidate-session' : 'false')
csrf(disabled:true)
}
def multiHttp() {
xml.http('authentication-manager-ref' : 'authManager', 'pattern' : '/first/**') {
'form-login'('login-page' : '/login')
'logout'('invalidate-session' : 'true')
csrf(disabled:true)
}
xml.http('authentication-manager-ref' : 'authManager2') {
'form-login'('login-page' : '/login2')
'logout'('invalidate-session' : 'false')
csrf(disabled:true)
}
String secondAuthManager = AUTH_PROVIDER_XML.replace("alias='authManager'", "id='authManager2'")
createAppContext(AUTH_PROVIDER_XML + secondAuthManager)
String secondAuthManager = AUTH_PROVIDER_XML.replace("alias='authManager'", "id='authManager2'")
createAppContext(AUTH_PROVIDER_XML + secondAuthManager)
def securityContextAwareFilter = getFilters('/first/filters').find { it instanceof SecurityContextHolderAwareRequestFilter }
def secondSecurityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
def securityContextAwareFilter = getFilters('/first/filters').find { it instanceof SecurityContextHolderAwareRequestFilter }
def secondSecurityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login'
securityContextAwareFilter.authenticationManager == getFilters('/first/filters').find { it instanceof UsernamePasswordAuthenticationFilter}.authenticationManager
securityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager')
securityContextAwareFilter.logoutHandlers.size() == 1
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == true
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login'
securityContextAwareFilter.authenticationManager == getFilters('/first/filters').find { it instanceof UsernamePasswordAuthenticationFilter}.authenticationManager
securityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager')
securityContextAwareFilter.logoutHandlers.size() == 1
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == true
secondSecurityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login2'
secondSecurityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
secondSecurityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager2')
securityContextAwareFilter.logoutHandlers.size() == 1
secondSecurityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
secondSecurityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
}
secondSecurityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login2'
secondSecurityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
secondSecurityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager2')
securityContextAwareFilter.logoutHandlers.size() == 1
secondSecurityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
secondSecurityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
}
def logoutCustom() {
xml.http() {
'form-login'('login-page' : '/login')
'logout'('invalidate-session' : 'false', 'logout-success-url' : '/login?logout', 'delete-cookies' : 'JSESSIONID')
csrf(disabled:true)
}
createAppContext(AUTH_PROVIDER_XML)
def logoutCustom() {
xml.http() {
'form-login'('login-page' : '/login')
'logout'('invalidate-session' : 'false', 'logout-success-url' : '/login?logout', 'delete-cookies' : 'JSESSIONID')
csrf(disabled:true)
}
createAppContext(AUTH_PROVIDER_XML)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers.size() == 2
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
securityContextAwareFilter.logoutHandlers[1].class == CookieClearingLogoutHandler
securityContextAwareFilter.logoutHandlers[1].cookiesToClear == ['JSESSIONID']
}
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers.size() == 2
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
securityContextAwareFilter.logoutHandlers[1].class == CookieClearingLogoutHandler
securityContextAwareFilter.logoutHandlers[1].cookiesToClear == ['JSESSIONID']
}
}
@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<context:annotation-config/>
<context:annotation-config/>
<bean class="org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests$WithBanNameAutoProxyCreatorConfig"/>
<bean class="org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests$WithBanNameAutoProxyCreatorConfig"/>
<bean id="interceptor" class="org.springframework.security.config.annotation.configuration.AroundMethodInterceptor"/>
<bean id="myBean" class="org.springframework.security.config.annotation.configuration.MyAdvisedBean"/>
<bean id="autoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
p:beanNames="myBean"
p:interceptorNames="interceptor"/>
<bean id="pointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
p:mappedName="doStuff"
p:advice-ref="interceptor"/>
<bean id="interceptor" class="org.springframework.security.config.annotation.configuration.AroundMethodInterceptor"/>
<bean id="myBean" class="org.springframework.security.config.annotation.configuration.MyAdvisedBean"/>
<bean id="autoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
p:beanNames="myBean"
p:interceptorNames="interceptor"/>
<bean id="pointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
p:mappedName="doStuff"
p:advice-ref="interceptor"/>
</beans>
@@ -1,41 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean
class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
<map>
<entry key="SPRINGSECURITY">
<array>
<bean
class="javax.security.auth.login.AppConfigurationEntry">
<constructor-arg
value="org.springframework.security.authentication.jaas.TestLoginModule" />
<constructor-arg>
<util:constant
static-field="javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED" />
</constructor-arg>
<constructor-arg>
<map></map>
</constructor-arg>
</bean>
</array>
</entry>
</map>
</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
<bean
class="org.springframework.security.authentication.jaas.TestAuthorityGranter" />
</list>
</property>
</bean>
<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean
class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
<map>
<entry key="SPRINGSECURITY">
<array>
<bean
class="javax.security.auth.login.AppConfigurationEntry">
<constructor-arg
value="org.springframework.security.authentication.jaas.TestLoginModule" />
<constructor-arg>
<util:constant
static-field="javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED" />
</constructor-arg>
<constructor-arg>
<map></map>
</constructor-arg>
</bean>
</array>
</entry>
</map>
</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
<bean
class="org.springframework.security.authentication.jaas.TestAuthorityGranter" />
</list>
</property>
</bean>
</beans>
@@ -1,15 +1,15 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
<logger name="org.apache.directory" level="ERROR"/>
<root level="${root.level}:-WARN">
<appender-ref ref="STDOUT" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -1,32 +1,32 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<bean id="userRepository" class="org.springframework.security.integration.StubUserRepository"/>
<bean id="userRepository" class="org.springframework.security.integration.StubUserRepository"/>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="userDetailsService" />
</security:authentication-manager>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="userDetailsService" />
</security:authentication-manager>
<bean id="userDetailsService" class="org.springframework.security.integration.UserDetailsServiceImpl">
<property name="userRepository" ref="userRepository"/>
</bean>
<bean id="userDetailsService" class="org.springframework.security.integration.UserDetailsServiceImpl">
<property name="userRepository" ref="userRepository"/>
</bean>
<security:global-method-security>
<security:protect-pointcut
expression="execution(* org.springframework.security.integration.*Repository+.*(..))"
access="ROLE_LOGGEDIN" />
</security:global-method-security>
<security:global-method-security>
<security:protect-pointcut
expression="execution(* org.springframework.security.integration.*Repository+.*(..))"
access="ROLE_LOGGEDIN" />
</security:global-method-security>
<aop:aspectj-autoproxy/>
<aop:aspectj-autoproxy/>
</beans>
@@ -1,54 +1,54 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:user-service>
<security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:user-service>
<security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg>
<util:list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</util:list>
</constructor-arg>
<property name="allowIfAllAbstainDecisions" value="false"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg>
<util:list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</util:list>
</constructor-arg>
<property name="allowIfAllAbstainDecisions" value="false"/>
</bean>
<bean id="securityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="validateConfigAttributes" value="true"/>
<property name="rejectPublicInvocations" value="true"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:method-security-metadata-source>
<security:protect method="org.springframework.security.core.session.SessionRegistry.get*" access="ROLE_C" />
</security:method-security-metadata-source>
</property>
</bean>
<bean id="securityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="validateConfigAttributes" value="true"/>
<property name="rejectPublicInvocations" value="true"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:method-security-metadata-source>
<security:protect method="org.springframework.security.core.session.SessionRegistry.get*" access="ROLE_C" />
</security:method-security-metadata-source>
</property>
</bean>
<bean id="httpRemoteService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.springframework.security.core.session.SessionRegistry"/>
<property name="interceptorNames">
<list>
<value>securityInterceptor</value>
<value>httpInvokerClientInterceptor</value>
</list>
</property>
</bean>
<bean id="httpRemoteService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.springframework.security.core.session.SessionRegistry"/>
<property name="interceptorNames">
<list>
<value>securityInterceptor</value>
<value>httpInvokerClientInterceptor</value>
</list>
</property>
</bean>
<bean id="httpInvokerClientInterceptor" class="org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor">
<property name="serviceUrl" value="http://somehost/someUrl"/>
</bean>
<bean id="httpInvokerClientInterceptor" class="org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor">
<property name="serviceUrl" value="http://somehost/someUrl"/>
</bean>
</beans>
@@ -28,185 +28,185 @@ import java.util.Random;
* @author Luke Taylor
*/
public class SessionRegistryImplMTTests extends TestCase {
private static final Random rnd = new Random();
private static boolean errorOccurred;
private static final Random rnd = new Random();
private static boolean errorOccurred;
protected void setUp() throws Exception {
errorOccurred = false;
}
protected void setUp() throws Exception {
errorOccurred = false;
}
/**
* Reproduces the NPE mentioned in SEC-484 where a sessionId is removed from
* the set of sessions before it is removed from the list of sessions for a principal.
* getAllSessions(principal, false) then finds the sessionId in the principal's session list
* but reads null for the SessionInformation with the same Id.
* Note that this is not guaranteed to produce the error but is a good testing point. Increasing the number
* of sessions makes a failure more likely, but slows the test considerably.
* Inserting temporary sleep statements in SessionRegistryClassImpl will also help.
*/
public void testConcurrencyOfReadAndRemoveIsSafe() {
Object principal = "Joe Principal";
SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
Set sessions = Collections.synchronizedSet(new HashSet());
// Register some sessions
for (int i = 0; i < 50; i++) {
String sessionId = Integer.toString(i);
sessions.add(sessionId);
sessionregistry.registerNewSession(sessionId, principal);
}
/**
* Reproduces the NPE mentioned in SEC-484 where a sessionId is removed from
* the set of sessions before it is removed from the list of sessions for a principal.
* getAllSessions(principal, false) then finds the sessionId in the principal's session list
* but reads null for the SessionInformation with the same Id.
* Note that this is not guaranteed to produce the error but is a good testing point. Increasing the number
* of sessions makes a failure more likely, but slows the test considerably.
* Inserting temporary sleep statements in SessionRegistryClassImpl will also help.
*/
public void testConcurrencyOfReadAndRemoveIsSafe() {
Object principal = "Joe Principal";
SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
Set sessions = Collections.synchronizedSet(new HashSet());
// Register some sessions
for (int i = 0; i < 50; i++) {
String sessionId = Integer.toString(i);
sessions.add(sessionId);
sessionregistry.registerNewSession(sessionId, principal);
}
// Pile of readers to hammer the getAllSessions method.
for (int i=0; i < 10; i++) {
Thread reader = new Thread(new SessionRegistryReader(principal, sessionregistry));
reader.start();
}
// Pile of readers to hammer the getAllSessions method.
for (int i=0; i < 10; i++) {
Thread reader = new Thread(new SessionRegistryReader(principal, sessionregistry));
reader.start();
}
Thread remover = new Thread(new SessionRemover("remover", sessionregistry, sessions));
Thread remover = new Thread(new SessionRemover("remover", sessionregistry, sessions));
remover.start();
remover.start();
while(remover.isAlive()) {
pause(250);
}
while(remover.isAlive()) {
pause(250);
}
assertFalse("Thread errors detected; review log output for details", errorOccurred);
}
assertFalse("Thread errors detected; review log output for details", errorOccurred);
}
public void testConcurrentRemovalIsSafe() {
Object principal = "Some principal object";
SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
// The session list (effectivelly the containers sessions).
Set sessions = Collections.synchronizedSet(new HashSet());
Thread registerer = new Thread(new SessionRegisterer(principal, sessionregistry, 100, sessions));
public void testConcurrentRemovalIsSafe() {
Object principal = "Some principal object";
SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
// The session list (effectivelly the containers sessions).
Set sessions = Collections.synchronizedSet(new HashSet());
Thread registerer = new Thread(new SessionRegisterer(principal, sessionregistry, 100, sessions));
registerer.start();
registerer.start();
int nRemovers = 4;
int nRemovers = 4;
SessionRemover[] removers = new SessionRemover[nRemovers];
Thread[] removerThreads = new Thread[nRemovers];
SessionRemover[] removers = new SessionRemover[nRemovers];
Thread[] removerThreads = new Thread[nRemovers];
for (int i = 0; i < removers.length; i++) {
removers[i] = new SessionRemover("remover" + i, sessionregistry, sessions);
removerThreads[i] = new Thread(removers[i], "remover" + i);
removerThreads[i].start();
}
for (int i = 0; i < removers.length; i++) {
removers[i] = new SessionRemover("remover" + i, sessionregistry, sessions);
removerThreads[i] = new Thread(removers[i], "remover" + i);
removerThreads[i].start();
}
while (stillRunning(removerThreads)) {
pause(500);
}
}
while (stillRunning(removerThreads)) {
pause(500);
}
}
private boolean stillRunning(Thread[] threads) {
for (int i = 0; i < threads.length; i++) {
if (threads[i].isAlive()) {
return true;
}
}
private boolean stillRunning(Thread[] threads) {
for (int i = 0; i < threads.length; i++) {
if (threads[i].isAlive()) {
return true;
}
}
return false;
}
return false;
}
private static class SessionRegisterer implements Runnable {
private SessionRegistry sessionregistry;
private int nIterations;
private Set sessionList;
private Object principal;
private static class SessionRegisterer implements Runnable {
private SessionRegistry sessionregistry;
private int nIterations;
private Set sessionList;
private Object principal;
public SessionRegisterer(Object principal, SessionRegistry sessionregistry, int nIterations, Set sessionList) {
this.sessionregistry = sessionregistry;
this.nIterations = nIterations;
this.sessionList = sessionList;
this.principal = principal;
}
public SessionRegisterer(Object principal, SessionRegistry sessionregistry, int nIterations, Set sessionList) {
this.sessionregistry = sessionregistry;
this.nIterations = nIterations;
this.sessionList = sessionList;
this.principal = principal;
}
public void run() {
for (int i=0; i < nIterations && !errorOccurred; i++) {
String sessionId = Integer.toString(i);
sessionList.add(sessionId);
try {
sessionregistry.registerNewSession(sessionId,principal);
pause(20);
Thread.yield();
} catch(Exception e) {
e.printStackTrace();
errorOccurred = true;
}
}
}
}
public void run() {
for (int i=0; i < nIterations && !errorOccurred; i++) {
String sessionId = Integer.toString(i);
sessionList.add(sessionId);
try {
sessionregistry.registerNewSession(sessionId,principal);
pause(20);
Thread.yield();
} catch(Exception e) {
e.printStackTrace();
errorOccurred = true;
}
}
}
}
private static class SessionRegistryReader implements Runnable {
private SessionRegistry sessionRegistry;
private Object principal;
private static class SessionRegistryReader implements Runnable {
private SessionRegistry sessionRegistry;
private Object principal;
public SessionRegistryReader(Object principal, SessionRegistry sessionregistry) {
this.sessionRegistry = sessionregistry;
this.principal = principal;
}
public SessionRegistryReader(Object principal, SessionRegistry sessionregistry) {
this.sessionRegistry = sessionregistry;
this.principal = principal;
}
public void run() {
while (!errorOccurred) {
try {
sessionRegistry.getAllSessions(principal, false);
sessionRegistry.getAllPrincipals();
sessionRegistry.getAllSessions(principal, true);
Thread.yield();
} catch (Exception e) {
e.printStackTrace();
errorOccurred = true;
}
}
}
}
public void run() {
while (!errorOccurred) {
try {
sessionRegistry.getAllSessions(principal, false);
sessionRegistry.getAllPrincipals();
sessionRegistry.getAllSessions(principal, true);
Thread.yield();
} catch (Exception e) {
e.printStackTrace();
errorOccurred = true;
}
}
}
}
private static class SessionRemover implements Runnable {
private SessionRegistry sessionregistry;
private Set sessionList;
private String name;
private static class SessionRemover implements Runnable {
private SessionRegistry sessionregistry;
private Set sessionList;
private String name;
public SessionRemover(String name, SessionRegistry sessionregistry, Set sessionList) {
this.name = name;
this.sessionregistry = sessionregistry;
this.sessionList = sessionList;
}
public SessionRemover(String name, SessionRegistry sessionregistry, Set sessionList) {
this.name = name;
this.sessionregistry = sessionregistry;
this.sessionList = sessionList;
}
public void run() {
boolean finished = false;
public void run() {
boolean finished = false;
while (!finished && !errorOccurred) {
if (sessionList.isEmpty()) {
finished = true;
// List of sessions appears to be empty but give it a chance to fill up again
System.out.println(name + ": Session list empty. Waiting.");
pause(500);
}
while (!finished && !errorOccurred) {
if (sessionList.isEmpty()) {
finished = true;
// List of sessions appears to be empty but give it a chance to fill up again
System.out.println(name + ": Session list empty. Waiting.");
pause(500);
}
Object[] sessions = sessionList.toArray();
Object[] sessions = sessionList.toArray();
if (sessions.length > 0) {
finished = false;
String sessionId = (String) sessions[0];
if (sessions.length > 0) {
finished = false;
String sessionId = (String) sessions[0];
// System.out.println(name + ": removing " + sessionId);
try {
sessionregistry.removeSessionInformation(sessionId);
try {
sessionregistry.removeSessionInformation(sessionId);
pause(rnd.nextInt(100));
pause(rnd.nextInt(100));
sessionList.remove(sessionId);
Thread.yield();
} catch (Exception e) {
e.printStackTrace();
errorOccurred = true;
}
}
}
}
}
sessionList.remove(sessionId);
Thread.yield();
} catch (Exception e) {
e.printStackTrace();
errorOccurred = true;
}
}
}
}
}
private static void pause(int length) {
try {
Thread.sleep(length);
} catch (InterruptedException ignore) {}
}
private static void pause(int length) {
try {
Thread.sleep(length);
} catch (InterruptedException ignore) {}
}
}
@@ -16,201 +16,201 @@ import org.springframework.security.providers.UsernamePasswordAuthenticationToke
* @Author Luke Taylor
*/
public class SecurityContextHolderMTTests extends TestCase{
private int errors = 0;
private int errors = 0;
private static final int NUM_OPS = 25;
private static final int NUM_THREADS = 25;
private static final int NUM_OPS = 25;
private static final int NUM_THREADS = 25;
public final void setUp() throws Exception {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
public final void setUp() throws Exception {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
public void testSynchronizationCustomStrategyLoading() {
SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName());
assertTrue(new SecurityContextHolder().toString()
.lastIndexOf("SecurityContextHolder[strategy='org.springframework.security.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationCustomStrategyLoading() {
SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName());
assertTrue(new SecurityContextHolder().toString()
.lastIndexOf("SecurityContextHolder[strategy='org.springframework.security.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationGlobal() throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationGlobal() throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationInheritableThreadLocal()
throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationInheritableThreadLocal()
throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationThreadLocal() throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationThreadLocal() throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
private void startAndRun(Thread[] threads) {
// Start them up
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
private void startAndRun(Thread[] threads) {
// Start them up
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
// Wait for them to finish
while (stillRunning(threads)) {
try {
Thread.sleep(250);
} catch (InterruptedException ignore) {}
}
}
// Wait for them to finish
while (stillRunning(threads)) {
try {
Thread.sleep(250);
} catch (InterruptedException ignore) {}
}
}
private boolean stillRunning(Thread[] threads) {
for (int i = 0; i < threads.length; i++) {
if (threads[i].isAlive()) {
return true;
}
}
private boolean stillRunning(Thread[] threads) {
for (int i = 0; i < threads.length; i++) {
if (threads[i].isAlive()) {
return true;
}
}
return false;
}
return false;
}
private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads,
boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) {
Thread[] threads = new Thread[createThreads];
errors = 0;
private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads,
boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) {
Thread[] threads = new Thread[createThreads];
errors = 0;
if (topLevelThread) {
// PARENT (TOP-LEVEL) THREAD CREATION
if (expectChildrenToShareAuthenticationWithParent) {
// An InheritableThreadLocal
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread; neither current thread or child will have authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null);
} else {
// Inject auth into current thread, but not child; current thread will have auth, child will also have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true,
prefix + "Auth_Parent_" + i);
}
}
} else if (expectAllThreadsToUseIdenticalAuthentication) {
// A global
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME",
"pass"));
if (topLevelThread) {
// PARENT (TOP-LEVEL) THREAD CREATION
if (expectChildrenToShareAuthenticationWithParent) {
// An InheritableThreadLocal
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread; neither current thread or child will have authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null);
} else {
// Inject auth into current thread, but not child; current thread will have auth, child will also have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true,
prefix + "Auth_Parent_" + i);
}
}
} else if (expectAllThreadsToUseIdenticalAuthentication) {
// A global
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME",
"pass"));
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread;both current thread and child will have same authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true,
"GLOBAL_USERNAME");
} else {
// Inject auth into current thread; current thread will have auth, child will also have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME");
}
}
} else {
// A standard ThreadLocal
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread; neither current thread or child will have authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null);
} else {
// Inject auth into current thread, but not child; current thread will have auth, child will not have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false,
prefix + "Auth_Parent_" + i);
}
}
}
} else {
// CHILD THREAD CREATION
if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) {
// The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent)
for (int i = 0; i < threads.length; i++) {
String expectedUsername = prefix;
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread;both current thread and child will have same authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true,
"GLOBAL_USERNAME");
} else {
// Inject auth into current thread; current thread will have auth, child will also have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME");
}
}
} else {
// A standard ThreadLocal
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread; neither current thread or child will have authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null);
} else {
// Inject auth into current thread, but not child; current thread will have auth, child will not have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false,
prefix + "Auth_Parent_" + i);
}
}
}
} else {
// CHILD THREAD CREATION
if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) {
// The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent)
for (int i = 0; i < threads.length; i++) {
String expectedUsername = prefix;
if (expectAllThreadsToUseIdenticalAuthentication) {
expectedUsername = "GLOBAL_USERNAME";
}
if (expectAllThreadsToUseIdenticalAuthentication) {
expectedUsername = "GLOBAL_USERNAME";
}
// Don't inject auth into current thread; the current thread will obtain auth from its parent
// NB: As topLevelThread = true, no further child threads will be created
threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false,
expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername);
}
} else {
// The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent)
for (int i = 0; i < threads.length; i++) {
// Don't inject auth into current thread; neither current thread or child will have authentication
// NB: As topLevelThread = true, no further child threads will be created
threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null);
}
}
}
// Don't inject auth into current thread; the current thread will obtain auth from its parent
// NB: As topLevelThread = true, no further child threads will be created
threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false,
expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername);
}
} else {
// The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent)
for (int i = 0; i < threads.length; i++) {
// Don't inject auth into current thread; neither current thread or child will have authentication
// NB: As topLevelThread = true, no further child threads will be created
threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null);
}
}
}
// Start and execute the threads
startAndRun(threads);
}
// Start and execute the threads
startAndRun(threads);
}
private Thread makeThread(final String threadIdentifier, final boolean topLevelThread,
final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication,
final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) {
final Random rnd = new Random();
private Thread makeThread(final String threadIdentifier, final boolean topLevelThread,
final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication,
final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) {
final Random rnd = new Random();
Thread t = new Thread(new Runnable() {
public void run() {
if (injectAuthIntoCurrentThread) {
// Set authentication in this thread
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
expectedUsername, "pass"));
Thread t = new Thread(new Runnable() {
public void run() {
if (injectAuthIntoCurrentThread) {
// Set authentication in this thread
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
expectedUsername, "pass"));
//System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication());
} else {
//System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")");
}
//System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication());
} else {
//System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")");
}
// Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it)
for (int i = 0; i < NUM_OPS; i++) {
String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null)
? null : SecurityContextHolder.getContext().getAuthentication().getName();
// Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it)
for (int i = 0; i < NUM_OPS; i++) {
String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null)
? null : SecurityContextHolder.getContext().getAuthentication().getName();
if ((i % 7) == 0) {
System.out.println(threadIdentifier + " at " + i + " username " + currentUsername);
}
if ((i % 7) == 0) {
System.out.println(threadIdentifier + " at " + i + " username " + currentUsername);
}
try {
assertEquals("Failed on iteration " + i + "; Authentication was '"
+ currentUsername + "' but principal was expected to contain username '"
+ expectedUsername + "'", expectedUsername, currentUsername);
} catch (ComparisonFailure err) {
errors++;
throw err;
}
try {
assertEquals("Failed on iteration " + i + "; Authentication was '"
+ currentUsername + "' but principal was expected to contain username '"
+ expectedUsername + "'", expectedUsername, currentUsername);
} catch (ComparisonFailure err) {
errors++;
throw err;
}
try {
Thread.sleep(rnd.nextInt(250));
} catch (InterruptedException ignore) {}
}
try {
Thread.sleep(rnd.nextInt(250));
} catch (InterruptedException ignore) {}
}
// Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it)
if (topLevelThread) {
// Make four children, but we don't want the children to have any more children (so anti-nature, huh?)
if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) {
loadStartAndWaitForThreads(false, threadIdentifier, 4,
expectAllThreadsToUseIdenticalAuthentication, true);
} else {
loadStartAndWaitForThreads(false, threadIdentifier, 4,
expectAllThreadsToUseIdenticalAuthentication, false);
}
}
}
}, threadIdentifier);
// Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it)
if (topLevelThread) {
// Make four children, but we don't want the children to have any more children (so anti-nature, huh?)
if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) {
loadStartAndWaitForThreads(false, threadIdentifier, 4,
expectAllThreadsToUseIdenticalAuthentication, true);
} else {
loadStartAndWaitForThreads(false, threadIdentifier, 4,
expectAllThreadsToUseIdenticalAuthentication, false);
}
}
}
}, threadIdentifier);
return t;
}
return t;
}
}
@@ -1,15 +1,15 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
<logger name="org.apache.directory" level="ERROR"/>
<root level="${root.level}:-WARN">
<appender-ref ref="STDOUT" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
<http-basic />
</http>
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
<http-basic />
</http>
</beans:beans>
@@ -1,34 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<debug />
<debug />
<!--
Http App Context to test form login, remember-me and concurrent session control.
Needs to be supplemented with authentication provider(s)
-->
<http pattern="/login.jsp" security="none" />
<!--
Http App Context to test form login, remember-me and concurrent session control.
Needs to be supplemented with authentication provider(s)
-->
<http pattern="/login.jsp" security="none" />
<http>
<intercept-url pattern="/secure/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
<intercept-url pattern="/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
<http>
<intercept-url pattern="/secure/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
<intercept-url pattern="/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=true"/>
<http-basic/>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=true"/>
<http-basic/>
<!-- Default logout configuration -->
<logout logout-url="/logout"/>
<!-- Default logout configuration -->
<logout logout-url="/logout"/>
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
<csrf disabled="true"/>
</http>
<csrf disabled="true"/>
</http>
</beans:beans>
@@ -1,56 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<http pattern="/login.jsp" security="none" />
<http pattern="/login.jsp" security="none" />
<http entry-point-ref="aep" use-expressions="false">
<intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
<http entry-point-ref="aep" use-expressions="false">
<intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
<session-management session-authentication-strategy-ref="sas"/>
<logout />
<session-management session-authentication-strategy-ref="sas"/>
<logout />
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
<csrf disabled="true"/>
</http>
<csrf disabled="true"/>
</http>
<beans:bean id="aep" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:constructor-arg value="/login.jsp" />
</beans:bean>
<beans:bean id="aep" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:constructor-arg value="/login.jsp" />
</beans:bean>
<beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:constructor-arg ref="sessionRegistry" />
<beans:constructor-arg value="/session-expired.htm" />
</beans:bean>
<beans:bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:constructor-arg ref="sessionRegistry" />
<beans:constructor-arg value="/session-expired.htm" />
</beans:bean>
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
<beans:property name="maximumSessions" value="1" />
<beans:property name="exceptionIfMaximumExceeded" value="true" />
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
<beans:property name="maximumSessions" value="1" />
<beans:property name="exceptionIfMaximumExceeded" value="true" />
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry"/>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
</beans:beans>
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="miles" password="milespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_TRUMPETER"/>
<user name="johnc" password="johncspassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SAXOPHONIST"/>
<user name="jimi" password="jimispassword" authorities="ROLE_USER,ROLE_ROCK,ROLE_GUITARIST"/>
<user name="bessie" password="bessiespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SINGER"/>
<user name="theescapist&lt;&gt;&amp;." password="theescapistspassword" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="miles" password="milespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_TRUMPETER"/>
<user name="johnc" password="johncspassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SAXOPHONIST"/>
<user name="jimi" password="jimispassword" authorities="ROLE_USER,ROLE_ROCK,ROLE_GUITARIST"/>
<user name="bessie" password="bessiespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SINGER"/>
<user name="theescapist&lt;&gt;&amp;." password="theescapistspassword" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
@@ -1,48 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<sec:global-method-security secured-annotations="enabled" mode="aspectj" />
<sec:global-method-security secured-annotations="enabled" mode="aspectj" />
<!--
<bean id="aspectJSecurityInterceptor"
class="org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource">
<bean
class="org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource" />
</property>
</bean>
<bean id="aspectJSecurityInterceptor"
class="org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource">
<bean
class="org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource" />
</property>
</bean>
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<bean
class="org.springframework.security.authentication.TestingAuthenticationProvider" />
</property>
</bean>
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<bean
class="org.springframework.security.authentication.TestingAuthenticationProvider" />
</property>
</bean>
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean
class="org.springframework.security.access.vote.RoleVoter" />
</list>
</property>
</bean>
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean
class="org.springframework.security.access.vote.RoleVoter" />
</list>
</property>
</bean>
<bean
class="org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"
factory-method="aspectOf">
<property name="securityInterceptor" ref="aspectJSecurityInterceptor" />
</bean>
<bean
class="org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"
factory-method="aspectOf">
<property name="securityInterceptor" ref="aspectJSecurityInterceptor" />
</bean>
-->
<bean class="sample.aspectj.Service" />
<bean class="sample.aspectj.Service" />
<bean class="sample.aspectj.SecuredService" />
<bean class="sample.aspectj.SecuredService" />
</beans>
@@ -1,14 +1,14 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
<root level="${root.level}:-WARN">
<appender-ref ref="STDOUT" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -33,90 +33,90 @@ import spock.lang.*
*/
@Stepwise
class CasSampleProxyTests extends AbstractCasTests {
HttpClient client = new HttpClient()
@Shared String casServerUrl = LoginPage.url.replaceFirst('/login','')
@Shared JettyCasService service = new JettyCasService().init(casServerUrl)
@Shared Cas20ProxyRetriever retriever = new Cas20ProxyRetriever(casServerUrl,'UTF-8')
@Shared String pt
HttpClient client = new HttpClient()
@Shared String casServerUrl = LoginPage.url.replaceFirst('/login','')
@Shared JettyCasService service = new JettyCasService().init(casServerUrl)
@Shared Cas20ProxyRetriever retriever = new Cas20ProxyRetriever(casServerUrl,'UTF-8')
@Shared String pt
def cleanupSpec() {
service.stop()
}
def cleanupSpec() {
service.stop()
}
def 'access secure page succeeds with ROLE_USER'() {
setup: 'Obtain a pgt for a user with ROLE_USER'
driver.get LoginPage.url+"?service="+service.serviceUrl()
at LoginPage
login 'scott'
when: 'User with ROLE_USER accesses the secure page'
def content = getSecured(getBaseUrl()+SecurePage.url).responseBodyAsString
then: 'The secure page is returned'
content.contains('<h1>Secure Page</h1>')
}
def 'access secure page succeeds with ROLE_USER'() {
setup: 'Obtain a pgt for a user with ROLE_USER'
driver.get LoginPage.url+"?service="+service.serviceUrl()
at LoginPage
login 'scott'
when: 'User with ROLE_USER accesses the secure page'
def content = getSecured(getBaseUrl()+SecurePage.url).responseBodyAsString
then: 'The secure page is returned'
content.contains('<h1>Secure Page</h1>')
}
def 'access proxy ticket sample succeeds with ROLE_USER'() {
when: 'a proxy ticket is used to create another proxy ticket'
def content = getSecured(getBaseUrl()+ProxyTicketSamplePage.url).responseBodyAsString
then: 'The proxy ticket sample page is returned'
content.contains('<h1>Secure Page using a Proxy Ticket</h1>')
}
def 'access proxy ticket sample succeeds with ROLE_USER'() {
when: 'a proxy ticket is used to create another proxy ticket'
def content = getSecured(getBaseUrl()+ProxyTicketSamplePage.url).responseBodyAsString
then: 'The proxy ticket sample page is returned'
content.contains('<h1>Secure Page using a Proxy Ticket</h1>')
}
def 'access extremely secure page with ROLE_USER is denied'() {
when: 'User with ROLE_USER accesses the extremely secure page'
GetMethod method = getSecured(getBaseUrl()+ExtremelySecurePage.url)
then: 'access is denied'
assert method.responseBodyAsString =~ /(?i)403.*?Denied/
assert 403 == method.statusCode
}
def 'access extremely secure page with ROLE_USER is denied'() {
when: 'User with ROLE_USER accesses the extremely secure page'
GetMethod method = getSecured(getBaseUrl()+ExtremelySecurePage.url)
then: 'access is denied'
assert method.responseBodyAsString =~ /(?i)403.*?Denied/
assert 403 == method.statusCode
}
def 'access secure page with ROLE_SUPERVISOR succeeds'() {
setup: 'Obtain pgt for user with ROLE_SUPERVISOR'
to LocalLogoutPage
casServerLogout.click()
driver.get(LoginPage.url+"?service="+service.serviceUrl())
at LoginPage
login 'rod'
when: 'User with ROLE_SUPERVISOR accesses the secure page'
def content = getSecured(getBaseUrl()+ExtremelySecurePage.url).responseBodyAsString
then: 'The secure page is returned'
content.contains('<h1>VERY Secure Page</h1>')
}
def 'access secure page with ROLE_SUPERVISOR succeeds'() {
setup: 'Obtain pgt for user with ROLE_SUPERVISOR'
to LocalLogoutPage
casServerLogout.click()
driver.get(LoginPage.url+"?service="+service.serviceUrl())
at LoginPage
login 'rod'
when: 'User with ROLE_SUPERVISOR accesses the secure page'
def content = getSecured(getBaseUrl()+ExtremelySecurePage.url).responseBodyAsString
then: 'The secure page is returned'
content.contains('<h1>VERY Secure Page</h1>')
}
def 'access extremely secure page with ROLE_SUPERVISOR reusing pt succeeds (stateless mode works)'() {
when: 'User with ROLE_SUPERVISOR accesses extremely secure page with used pt'
def content = getSecured(getBaseUrl()+ExtremelySecurePage.url,pt).responseBodyAsString
then: 'The extremely secure page is returned'
content.contains('<h1>VERY Secure Page</h1>')
}
def 'access extremely secure page with ROLE_SUPERVISOR reusing pt succeeds (stateless mode works)'() {
when: 'User with ROLE_SUPERVISOR accesses extremely secure page with used pt'
def content = getSecured(getBaseUrl()+ExtremelySecurePage.url,pt).responseBodyAsString
then: 'The extremely secure page is returned'
content.contains('<h1>VERY Secure Page</h1>')
}
def 'access secure page with invalid proxy ticket fails'() {
when: 'Invalid ticket is used to access secure page'
GetMethod method = getSecured(getBaseUrl()+SecurePage.url,'invalidticket')
then: 'Authentication fails'
method.statusCode == 401
}
def 'access secure page with invalid proxy ticket fails'() {
when: 'Invalid ticket is used to access secure page'
GetMethod method = getSecured(getBaseUrl()+SecurePage.url,'invalidticket')
then: 'Authentication fails'
method.statusCode == 401
}
/**
* Gets the result of calling a url with a proxy ticket
* @param targetUrl the absolute url to attempt to access
* @param pt the proxy ticket to use. Defaults to {@link #getPt(String)} with targetUrl specified for the targetUrl.
* @return the GetMethod after calling a url with a specified proxy ticket
*/
GetMethod getSecured(String targetUrl,String pt=getPt(targetUrl)) {
assert pt != null
GetMethod method = new GetMethod(targetUrl+"?ticket="+pt)
int status = client.executeMethod(method)
method
}
/**
* Gets the result of calling a url with a proxy ticket
* @param targetUrl the absolute url to attempt to access
* @param pt the proxy ticket to use. Defaults to {@link #getPt(String)} with targetUrl specified for the targetUrl.
* @return the GetMethod after calling a url with a specified proxy ticket
*/
GetMethod getSecured(String targetUrl,String pt=getPt(targetUrl)) {
assert pt != null
GetMethod method = new GetMethod(targetUrl+"?ticket="+pt)
int status = client.executeMethod(method)
method
}
/**
* Obtains a proxy ticket using the pgt from the {@link #service}.
* @param targetService the targetService that the proxy ticket will be valid for
* @return a proxy ticket for targetService
*/
String getPt(String targetService) {
assert service.pgt != null
pt = retriever.getProxyTicketIdFor(service.pgt, targetService)
pt
}
/**
* Obtains a proxy ticket using the pgt from the {@link #service}.
* @param targetService the targetService that the proxy ticket will be valid for
* @return a proxy ticket for targetService
*/
String getPt(String targetService) {
assert service.pgt != null
pt = retriever.getProxyTicketIdFor(service.pgt, targetService)
pt
}
}
@@ -34,102 +34,102 @@ import spock.lang.Stepwise;
*/
@Stepwise
class CasSampleTests extends AbstractCasTests {
@Shared String casServerLogoutUrl = LoginPage.url.replaceFirst('/login','/logout')
@Shared String casServerLogoutUrl = LoginPage.url.replaceFirst('/login','/logout')
def 'access home page with unauthenticated user succeeds'() {
when: 'Unauthenticated user accesses the Home Page'
to HomePage
then: 'The home page succeeds'
at HomePage
}
def 'access home page with unauthenticated user succeeds'() {
when: 'Unauthenticated user accesses the Home Page'
to HomePage
then: 'The home page succeeds'
at HomePage
}
def 'access extremely secure page with unauthenitcated user requires login'() {
when: 'Unauthenticated user accesses the extremely secure page'
via ExtremelySecurePage
then: 'The login page is displayed'
at LoginPage
}
def 'access extremely secure page with unauthenitcated user requires login'() {
when: 'Unauthenticated user accesses the extremely secure page'
via ExtremelySecurePage
then: 'The login page is displayed'
at LoginPage
}
def 'authenticate attempt with invaid ticket fails'() {
when: 'present invalid ticket'
go "login/cas?ticket=invalid"
then: 'the login failed page is displayed'
$("h2").text() == 'Login to CAS failed!'
}
def 'authenticate attempt with invaid ticket fails'() {
when: 'present invalid ticket'
go "login/cas?ticket=invalid"
then: 'the login failed page is displayed'
$("h2").text() == 'Login to CAS failed!'
}
def 'access secure page with unauthenticated user requires login'() {
when: 'Unauthenticated user accesses the secure page'
via SecurePage
then: 'The login page is displayed'
at LoginPage
}
def 'access secure page with unauthenticated user requires login'() {
when: 'Unauthenticated user accesses the secure page'
via SecurePage
then: 'The login page is displayed'
at LoginPage
}
def 'saved request is used for secure page'() {
when: 'login with ROLE_USER after requesting the secure page'
login 'scott'
then: 'the secure page is displayed'
at SecurePage
}
def 'saved request is used for secure page'() {
when: 'login with ROLE_USER after requesting the secure page'
login 'scott'
then: 'the secure page is displayed'
at SecurePage
}
def 'access proxy ticket sample with ROLE_USER is allowed'() {
when: 'user with ROLE_USER requests the proxy ticket sample page'
to ProxyTicketSamplePage
then: 'the proxy ticket sample page is displayed'
at ProxyTicketSamplePage
}
def 'access proxy ticket sample with ROLE_USER is allowed'() {
when: 'user with ROLE_USER requests the proxy ticket sample page'
to ProxyTicketSamplePage
then: 'the proxy ticket sample page is displayed'
at ProxyTicketSamplePage
}
def 'access extremely secure page with ROLE_USER is denied'() {
when: 'User with ROLE_USER accesses extremely secure page'
via ExtremelySecurePage
then: 'the access denied page is displayed'
at AccessDeniedPage
}
def 'access extremely secure page with ROLE_USER is denied'() {
when: 'User with ROLE_USER accesses extremely secure page'
via ExtremelySecurePage
then: 'the access denied page is displayed'
at AccessDeniedPage
}
def 'clicking local logout link displays local logout page'() {
setup: 'Navigate to page with logout link'
to SecurePage
when: 'Local logout link is clicked'
navModule.logout.click()
then: 'the local logout page is displayed'
at LocalLogoutPage
}
def 'clicking local logout link displays local logout page'() {
setup: 'Navigate to page with logout link'
to SecurePage
when: 'Local logout link is clicked'
navModule.logout.click()
then: 'the local logout page is displayed'
at LocalLogoutPage
}
def 'clicking cas server logout link successfully performs logout'() {
when: 'the cas server logout link is clicked and the secure page is requested'
casServerLogout.click()
via SecurePage
then: 'the login page is displayed'
at LoginPage
}
def 'clicking cas server logout link successfully performs logout'() {
when: 'the cas server logout link is clicked and the secure page is requested'
casServerLogout.click()
via SecurePage
then: 'the login page is displayed'
at LoginPage
}
def 'access extremely secure page with ROLE_SUPERVISOR succeeds'() {
setup: 'login with ROLE_SUPERVISOR'
login 'rod'
when: 'access extremely secure page'
to ExtremelySecurePage
then: 'extremely secure page is displayed'
at ExtremelySecurePage
}
def 'access extremely secure page with ROLE_SUPERVISOR succeeds'() {
setup: 'login with ROLE_SUPERVISOR'
login 'rod'
when: 'access extremely secure page'
to ExtremelySecurePage
then: 'extremely secure page is displayed'
at ExtremelySecurePage
}
def 'after logout extremely secure page requires login'() {
when: 'logout and request extremely secure page'
navModule.logout.click()
casServerLogout.click()
via ExtremelySecurePage
then: 'login page is displayed'
at LoginPage
}
def 'after logout extremely secure page requires login'() {
when: 'logout and request extremely secure page'
navModule.logout.click()
casServerLogout.click()
via ExtremelySecurePage
then: 'login page is displayed'
at LoginPage
}
def 'logging out of the cas server successfully logs out of the cas sample application'() {
setup: 'login with ROLE_USER'
via SecurePage
at LoginPage
login 'rod'
at SecurePage
when: 'logout of the CAS Server'
go casServerLogoutUrl
via SecurePage
then: 'user is logged out of the CAS Service'
at LoginPage
}
def 'logging out of the cas server successfully logs out of the cas sample application'() {
setup: 'login with ROLE_USER'
via SecurePage
at LoginPage
login 'rod'
at SecurePage
when: 'logout of the CAS Server'
go casServerLogoutUrl
via SecurePage
then: 'user is logged out of the CAS Service'
at LoginPage
}
}
@@ -38,87 +38,87 @@ import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
* @author Rob Winch
*/
class JettyCasService extends Server {
private Cas20ProxyTicketValidator validator
private int port = availablePort()
private Cas20ProxyTicketValidator validator
private int port = availablePort()
/**
* The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter
* equal to {@link #serviceUrl()}.
*/
String pgt
/**
* The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter
* equal to {@link #serviceUrl()}.
*/
String pgt
/**
* Start the CAS Service which will be available at {@link #serviceUrl()}.
*
* @param casServerUrl
* @return
*/
def init(String casServerUrl) {
ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl()
validator = new Cas20ProxyTicketValidator(casServerUrl)
validator.setAcceptAnyProxy(true)
validator.setProxyGrantingTicketStorage(storage)
validator.setProxyCallbackUrl(absoluteUrl('callback'))
/**
* Start the CAS Service which will be available at {@link #serviceUrl()}.
*
* @param casServerUrl
* @return
*/
def init(String casServerUrl) {
ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl()
validator = new Cas20ProxyTicketValidator(casServerUrl)
validator.setAcceptAnyProxy(true)
validator.setProxyGrantingTicketStorage(storage)
validator.setProxyCallbackUrl(absoluteUrl('callback'))
String password = System.getProperty('javax.net.ssl.trustStorePassword','password')
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector()
ssl_connector.setPort(port)
ssl_connector.setKeystore(getTrustStore())
ssl_connector.setPassword(password)
ssl_connector.setKeyPassword(password)
addConnector(ssl_connector)
setHandler(new AbstractHandler() {
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
def st = request.getParameter('ticket')
if(st) {
JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl())
}
def pgt = request.getParameter('pgtId')
if(pgt) {
JettyCasService.this.pgt = pgt
}
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
}
})
start()
this
}
String password = System.getProperty('javax.net.ssl.trustStorePassword','password')
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector()
ssl_connector.setPort(port)
ssl_connector.setKeystore(getTrustStore())
ssl_connector.setPassword(password)
ssl_connector.setKeyPassword(password)
addConnector(ssl_connector)
setHandler(new AbstractHandler() {
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
def st = request.getParameter('ticket')
if(st) {
JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl())
}
def pgt = request.getParameter('pgtId')
if(pgt) {
JettyCasService.this.pgt = pgt
}
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
}
})
start()
this
}
/**
* Returns the absolute URL that this CAS service is available at.
* @return
*/
String serviceUrl() {
absoluteUrl('service')
}
/**
* Returns the absolute URL that this CAS service is available at.
* @return
*/
String serviceUrl() {
absoluteUrl('service')
}
/**
* Given a relative url, will provide an absolute url for this CAS Service.
* @param relativeUrl the relative url (i.e. service, callback, etc)
* @return
*/
private String absoluteUrl(String relativeUrl) {
"https://localhost:${port}/${relativeUrl}"
}
/**
* Given a relative url, will provide an absolute url for this CAS Service.
* @param relativeUrl the relative url (i.e. service, callback, etc)
* @return
*/
private String absoluteUrl(String relativeUrl) {
"https://localhost:${port}/${relativeUrl}"
}
private static String getTrustStore() {
String trustStoreLocation = System.getProperty('javax.net.ssl.trustStore')
if(trustStoreLocation == null || !new File(trustStoreLocation).isFile()) {
throw new IllegalStateException('Could not find the trust store at path "'+trustStoreLocation+'". Specify the location using the javax.net.ssl.trustStore system property.')
}
trustStoreLocation
}
/**
* Obtains a random available port (i.e. one that is not in use)
* @return
*/
private static int availablePort() {
ServerSocket server = new ServerSocket(0)
int port = server.localPort
server.close()
port
}
private static String getTrustStore() {
String trustStoreLocation = System.getProperty('javax.net.ssl.trustStore')
if(trustStoreLocation == null || !new File(trustStoreLocation).isFile()) {
throw new IllegalStateException('Could not find the trust store at path "'+trustStoreLocation+'". Specify the location using the javax.net.ssl.trustStore system property.')
}
trustStoreLocation
}
/**
* Obtains a random available port (i.e. one that is not in use)
* @return
*/
private static int availablePort() {
ServerSocket server = new ServerSocket(0)
int port = server.localPort
server.close()
port
}
}
@@ -24,8 +24,8 @@ import org.springframework.security.samples.cas.pages.*
* @author Rob Winch
*/
class NavModule extends Module {
static content = {
home(to: HomePage) { $("a", text: "Home") }
logout(to: LocalLogoutPage) { $("a", text: "Logout") }
}
static content = {
home(to: HomePage) { $("a", text: "Home") }
logout(to: LocalLogoutPage) { $("a", text: "Logout") }
}
}
@@ -23,5 +23,5 @@ import geb.*
* @author Rob Winch
*/
class AccessDeniedPage extends Page {
static at = { $("*",text: iContains(~/.*?403.*/)) }
static at = { $("*",text: iContains(~/.*?403.*/)) }
}
@@ -24,9 +24,9 @@ import org.springframework.security.samples.cas.modules.*
* @author Rob Winch
*/
class ExtremelySecurePage extends Page {
static url = "secure/extreme/"
static at = { assert $('h1').text() == 'VERY Secure Page'; true; }
static content = {
navModule { module NavModule }
}
static url = "secure/extreme/"
static at = { assert $('h1').text() == 'VERY Secure Page'; true; }
static content = {
navModule { module NavModule }
}
}
@@ -23,10 +23,10 @@ import geb.*
* @author Rob Winch
*/
class HomePage extends Page {
static at = { assert $('h1').text() == 'Home Page'; true}
static url = ''
static content = {
securePage { $('a',text: 'Secure page') }
extremelySecurePage { $('a',text: 'Extremely secure page') }
}
static at = { assert $('h1').text() == 'Home Page'; true}
static url = ''
static content = {
securePage { $('a',text: 'Secure page') }
extremelySecurePage { $('a',text: 'Extremely secure page') }
}
}
@@ -27,9 +27,9 @@ import geb.*
* @author Rob Winch
*/
class LocalLogoutPage extends Page {
static url = 'cas-logout.jsp'
static at = { assert driver.currentUrl.endsWith(url); true }
static content = {
casServerLogout { $('a',text: 'Logout of CAS') }
}
static url = 'cas-logout.jsp'
static at = { assert driver.currentUrl.endsWith(url); true }
static content = {
casServerLogout { $('a',text: 'Logout of CAS') }
}
}
@@ -23,24 +23,24 @@ import geb.*
* @author Rob Winch
*/
class LoginPage extends Page {
static url = loginUrl()
static at = { assert driver.currentUrl.startsWith(loginUrl()); true}
static content = {
login(required:false) { user, password=user ->
loginForm.username = user
loginForm.password = password
submit.click()
}
loginForm { $('#login') }
submit { $('input', type: 'submit') }
}
static url = loginUrl()
static at = { assert driver.currentUrl.startsWith(loginUrl()); true}
static content = {
login(required:false) { user, password=user ->
loginForm.username = user
loginForm.password = password
submit.click()
}
loginForm { $('#login') }
submit { $('input', type: 'submit') }
}
/**
* Gets the login page url which might change based upon the system properties. This is to support using a randomly available port for CI.
* @return
*/
private static String loginUrl() {
def host = System.getProperty('cas.server.host', 'localhost:9443')
"https://${host}/cas/login"
}
/**
* Gets the login page url which might change based upon the system properties. This is to support using a randomly available port for CI.
* @return
*/
private static String loginUrl() {
def host = System.getProperty('cas.server.host', 'localhost:9443')
"https://${host}/cas/login"
}
}
@@ -25,9 +25,9 @@ import org.springframework.security.samples.cas.modules.*
* @author Rob Winch
*/
class ProxyTicketSamplePage extends Page {
static url = "secure/ptSample"
static at = { assert $('h1').text() == 'Secure Page using a Proxy Ticket'; true}
static content = {
navModule { module NavModule }
}
static url = "secure/ptSample"
static at = { assert $('h1').text() == 'Secure Page using a Proxy Ticket'; true}
static content = {
navModule { module NavModule }
}
}
@@ -25,9 +25,9 @@ import org.springframework.security.samples.cas.modules.*
* @author Rob Winch
*/
class SecurePage extends Page {
static url = "secure/"
static at = { assert $('h1').text() == 'Secure Page'; true}
static content = {
navModule { module NavModule }
}
static url = "secure/"
static at = { assert $('h1').text() == 'Secure Page'; true}
static content = {
navModule { module NavModule }
}
}
@@ -1,11 +1,11 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="error">
<appender-ref ref="STDOUT" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -2,16 +2,16 @@
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c] - &lt;%m&gt;%n"/>
</layout>
</appender>
<logger name="org.jasig" additivity="true">
<level value="@logLevel@" />
</logger>
<root>
<level value="ERROR"/>
<appender-ref ref="console"/>
</root>
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c] - &lt;%m&gt;%n"/>
</layout>
</appender>
<logger name="org.jasig" additivity="true">
<level value="@logLevel@" />
</logger>
<root>
<level value="ERROR"/>
<appender-ref ref="console"/>
</root>
</log4j:configuration>

Some files were not shown because too many files have changed in this diff Show More