Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bcaad3a51c | |||
| 66f8a56b1b | |||
| 3e5b65f647 | |||
| c62789c976 | |||
| b02cae0a0c | |||
| af278b58b5 | |||
| ba81f6a06a | |||
| a39efaf883 | |||
| 7d5e032e25 | |||
| e21ef422e7 | |||
| 66f923dab7 | |||
| e8daeacd89 | |||
| 27f30b04cd | |||
| baa238e339 | |||
| cf5bd52121 | |||
| ef78626045 | |||
| 7f8efb7680 | |||
| 2c4d13ddef | |||
| ed2a646a69 | |||
| f8f4d960b5 | |||
| 76a4df0461 | |||
| 7eee6b102f | |||
| d69288e665 | |||
| 62bc17ea3f | |||
| fd2798ca95 | |||
| 173660c6ef | |||
| d6aa6a2246 |
+3
-4
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -131,10 +131,9 @@ public class AccessControlEntryImpl implements AccessControlEntry,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = this.acl.hashCode();
|
int result = this.permission.hashCode();
|
||||||
result = 31 * result + this.permission.hashCode();
|
|
||||||
result = 31 * result + (this.id != null ? this.id.hashCode() : 0);
|
result = 31 * result + (this.id != null ? this.id.hashCode() : 0);
|
||||||
result = 31 * result + this.sid.hashCode();
|
result = 31 * result + (this.sid.hashCode());
|
||||||
result = 31 * result + (this.auditFailure ? 1 : 0);
|
result = 31 * result + (this.auditFailure ? 1 : 0);
|
||||||
result = 31 * result + (this.auditSuccess ? 1 : 0);
|
result = 31 * result + (this.auditSuccess ? 1 : 0);
|
||||||
result = 31 * result + (this.granting ? 1 : 0);
|
result = 31 * result + (this.granting ? 1 : 0);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -560,6 +560,25 @@ public class AclImplTests {
|
|||||||
childAcl.setParent(changeParentAcl);
|
childAcl.setParent(changeParentAcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hashCodeWithoutStackOverFlow() throws Exception {
|
||||||
|
//given
|
||||||
|
Sid sid = new PrincipalSid("pSid");
|
||||||
|
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
|
||||||
|
AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role"));
|
||||||
|
PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
|
||||||
|
|
||||||
|
AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid);
|
||||||
|
AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true);
|
||||||
|
|
||||||
|
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
|
||||||
|
fieldAces.setAccessible(true);
|
||||||
|
List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(acl);
|
||||||
|
aces.add(ace);
|
||||||
|
//when - then none StackOverFlowError been raised
|
||||||
|
ace.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
// ~ Inner Classes
|
// ~ Inner Classes
|
||||||
// ==================================================================================================
|
// ==================================================================================================
|
||||||
|
|
||||||
|
|||||||
+4
@@ -16,8 +16,10 @@
|
|||||||
package org.springframework.security.config.annotation.configuration;
|
package org.springframework.security.config.annotation.configuration;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
@@ -34,9 +36,11 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public class ObjectPostProcessorConfiguration {
|
public class ObjectPostProcessorConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public ObjectPostProcessor<Object> objectPostProcessor(
|
public ObjectPostProcessor<Object> objectPostProcessor(
|
||||||
AutowireCapableBeanFactory beanFactory) {
|
AutowireCapableBeanFactory beanFactory) {
|
||||||
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
|
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
|
||||||
|
|||||||
+3
@@ -28,8 +28,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.AdviceMode;
|
import org.springframework.context.annotation.AdviceMode;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ImportAware;
|
import org.springframework.context.annotation.ImportAware;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
@@ -80,6 +82,7 @@ import org.springframework.util.Assert;
|
|||||||
* @see EnableGlobalMethodSecurity
|
* @see EnableGlobalMethodSecurity
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public class GlobalMethodSecurityConfiguration
|
public class GlobalMethodSecurityConfiguration
|
||||||
implements ImportAware, SmartInitializingSingleton {
|
implements ImportAware, SmartInitializingSingleton {
|
||||||
private static final Log logger = LogFactory
|
private static final Log logger = LogFactory
|
||||||
|
|||||||
+4
@@ -15,14 +15,18 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
class Jsr250MetadataSourceConfiguration {
|
class Jsr250MetadataSourceConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() {
|
public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() {
|
||||||
return new Jsr250MethodSecurityMetadataSource();
|
return new Jsr250MethodSecurityMetadataSource();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -49,6 +49,7 @@ class ReactiveMethodSecurityConfiguration implements ImportAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public DelegatingMethodSecurityMetadataSource methodMetadataSource() {
|
public DelegatingMethodSecurityMetadataSource methodMetadataSource() {
|
||||||
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(
|
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(
|
||||||
new DefaultMethodSecurityExpressionHandler());
|
new DefaultMethodSecurityExpressionHandler());
|
||||||
@@ -69,6 +70,7 @@ class ReactiveMethodSecurityConfiguration implements ImportAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
public DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler() {
|
public DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler() {
|
||||||
return new DefaultMethodSecurityExpressionHandler();
|
return new DefaultMethodSecurityExpressionHandler();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -584,6 +584,7 @@ public final class HttpSecurity extends
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows restricting access based upon the {@link HttpServletRequest} using
|
* Allows restricting access based upon the {@link HttpServletRequest} using
|
||||||
|
* {@link RequestMatcher} implementations (i.e. via URL patterns).
|
||||||
*
|
*
|
||||||
* <h2>Example Configurations</h2>
|
* <h2>Example Configurations</h2>
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -675,7 +675,7 @@ public class ServerHttpSecurity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Require a specific authority.
|
* Require a specific authority.
|
||||||
* @param authority the authority to require (i.e. "USER" woudl require authority of "USER").
|
* @param authority the authority to require (i.e. "USER" would require authority of "USER").
|
||||||
* @return the {@link AuthorizeExchangeSpec} to configure
|
* @return the {@link AuthorizeExchangeSpec} to configure
|
||||||
*/
|
*/
|
||||||
public AuthorizeExchangeSpec hasAuthority(String authority) {
|
public AuthorizeExchangeSpec hasAuthority(String authority) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ DigestAuthenticationFilter.usernameNotFound=Username {0} not found
|
|||||||
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
|
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
|
||||||
JdbcDaoImpl.notFound=User {0} not found
|
JdbcDaoImpl.notFound=User {0} not found
|
||||||
LdapAuthenticationProvider.badCredentials=Bad credentials
|
LdapAuthenticationProvider.badCredentials=Bad credentials
|
||||||
|
LdapAuthenticationProvider.badLdapConnection=Connection to LDAP server failed
|
||||||
LdapAuthenticationProvider.credentialsExpired=User credentials have expired
|
LdapAuthenticationProvider.credentialsExpired=User credentials have expired
|
||||||
LdapAuthenticationProvider.disabled=User is disabled
|
LdapAuthenticationProvider.disabled=User is disabled
|
||||||
LdapAuthenticationProvider.expired=User account has expired
|
LdapAuthenticationProvider.expired=User account has expired
|
||||||
|
|||||||
+8
@@ -65,6 +65,10 @@ public class BCryptPasswordEncoder implements PasswordEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String encode(CharSequence rawPassword) {
|
public String encode(CharSequence rawPassword) {
|
||||||
|
if (rawPassword == null) {
|
||||||
|
throw new IllegalArgumentException("rawPassword cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
String salt;
|
String salt;
|
||||||
if (strength > 0) {
|
if (strength > 0) {
|
||||||
if (random != null) {
|
if (random != null) {
|
||||||
@@ -81,6 +85,10 @@ public class BCryptPasswordEncoder implements PasswordEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||||
|
if (rawPassword == null) {
|
||||||
|
throw new IllegalArgumentException("rawPassword cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
if (encodedPassword == null || encodedPassword.length() == 0) {
|
if (encodedPassword == null || encodedPassword.length() == 0) {
|
||||||
logger.warn("Empty encoded password");
|
logger.warn("Empty encoded password");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -32,7 +32,7 @@ public class Encryptors {
|
|||||||
* (Password-Based Key Derivation Function #2). Salts the password to prevent
|
* (Password-Based Key Derivation Function #2). Salts the password to prevent
|
||||||
* dictionary attacks against the key. The provided salt is expected to be
|
* dictionary attacks against the key. The provided salt is expected to be
|
||||||
* hex-encoded; it should be random and at least 8 bytes in length. Also applies a
|
* hex-encoded; it should be random and at least 8 bytes in length. Also applies a
|
||||||
* random 16 byte initialization vector to ensure each encrypted message will be
|
* random 16-byte initialization vector to ensure each encrypted message will be
|
||||||
* unique. Requires Java 6.
|
* unique. Requires Java 6.
|
||||||
*
|
*
|
||||||
* @param password the password used to generate the encryptor's secret key; should
|
* @param password the password used to generate the encryptor's secret key; should
|
||||||
@@ -50,7 +50,7 @@ public class Encryptors {
|
|||||||
* Derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation
|
* Derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation
|
||||||
* Function #2). Salts the password to prevent dictionary attacks against the key. The
|
* Function #2). Salts the password to prevent dictionary attacks against the key. The
|
||||||
* provided salt is expected to be hex-encoded; it should be random and at least 8
|
* provided salt is expected to be hex-encoded; it should be random and at least 8
|
||||||
* bytes in length. Also applies a random 16 byte initialization vector to ensure each
|
* bytes in length. Also applies a random 16-byte initialization vector to ensure each
|
||||||
* encrypted message will be unique. Requires Java 6.
|
* encrypted message will be unique. Requires Java 6.
|
||||||
* NOTE: This mode is not
|
* NOTE: This mode is not
|
||||||
* <a href="https://en.wikipedia.org/wiki/Authenticated_encryption">authenticated</a>
|
* <a href="https://en.wikipedia.org/wiki/Authenticated_encryption">authenticated</a>
|
||||||
@@ -63,7 +63,7 @@ public class Encryptors {
|
|||||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||||
* key
|
* key
|
||||||
*
|
*
|
||||||
* @see #stronger(CharSequence, CharSequence) which uses the significatly more secure
|
* @see #stronger(CharSequence, CharSequence), which uses the significatly more secure
|
||||||
* GCM (instead of CBC)
|
* GCM (instead of CBC)
|
||||||
*/
|
*/
|
||||||
public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
|
public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
|
||||||
@@ -105,7 +105,10 @@ public class Encryptors {
|
|||||||
* not be shared
|
* not be shared
|
||||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||||
* secret key
|
* secret key
|
||||||
|
* @deprecated This encryptor is not secure. Instead, look to your data store for a
|
||||||
|
* mechanism to query encrypted data.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static TextEncryptor queryableText(CharSequence password, CharSequence salt) {
|
public static TextEncryptor queryableText(CharSequence password, CharSequence salt) {
|
||||||
return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(),
|
return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(),
|
||||||
salt));
|
salt));
|
||||||
|
|||||||
-2
@@ -83,8 +83,6 @@ public class Md4PasswordEncoder implements PasswordEncoder {
|
|||||||
private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
|
private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
|
||||||
private boolean encodeHashAsBase64;
|
private boolean encodeHashAsBase64;
|
||||||
|
|
||||||
private Digester digester;
|
|
||||||
|
|
||||||
|
|
||||||
public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
|
public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
|
||||||
this.encodeHashAsBase64 = encodeHashAsBase64;
|
this.encodeHashAsBase64 = encodeHashAsBase64;
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,8 @@ package org.springframework.security.crypto.password;
|
|||||||
* @deprecated This PasswordEncoder is not secure. Instead use an
|
* @deprecated This PasswordEncoder is not secure. Instead use an
|
||||||
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
|
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
|
||||||
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
|
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
|
||||||
* password upgrades.
|
* password upgrades. There are no plans to remove this support. It is deprecated to indicate that
|
||||||
|
* this is a legacy implementation and using it is considered insecure.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final class NoOpPasswordEncoder implements PasswordEncoder {
|
public final class NoOpPasswordEncoder implements PasswordEncoder {
|
||||||
|
|||||||
+11
@@ -92,4 +92,15 @@ public class BCryptPasswordEncoderTests {
|
|||||||
assertThat(encoder.matches("password", "012345678901234567890123456789")).isFalse();
|
assertThat(encoder.matches("password", "012345678901234567890123456789")).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void encodeNullRawPassword() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
encoder.encode(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void matchNullRawPassword() {
|
||||||
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||||
|
encoder.matches(null, "does-not-matter");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
gaeVersion=1.9.79
|
gaeVersion=1.9.80
|
||||||
springBootVersion=2.0.9.RELEASE
|
springBootVersion=2.0.9.RELEASE
|
||||||
version=5.0.15.RELEASE
|
version=5.0.17.RELEASE
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
dependencyManagement {
|
dependencyManagement {
|
||||||
imports {
|
imports {
|
||||||
mavenBom 'io.projectreactor:reactor-bom:Bismuth-SR17'
|
mavenBom 'io.projectreactor:reactor-bom:Bismuth-SR17'
|
||||||
mavenBom 'org.springframework:spring-framework-bom:5.0.16.RELEASE'
|
mavenBom 'org.springframework:spring-framework-bom:5.0.17.RELEASE'
|
||||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Kay-SR14'
|
mavenBom 'org.springframework.data:spring-data-releasetrain:Kay-SR14'
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
dependency 'cglib:cglib-nodep:3.2.12'
|
dependency 'cglib:cglib-nodep:3.2.12'
|
||||||
dependency 'com.squareup.okhttp3:mockwebserver:3.12.10'
|
dependency 'com.squareup.okhttp3:mockwebserver:3.12.12'
|
||||||
dependency 'opensymphony:sitemesh:2.4.2'
|
dependency 'opensymphony:sitemesh:2.4.2'
|
||||||
dependency 'org.gebish:geb-spock:0.10.0'
|
dependency 'org.gebish:geb-spock:0.10.0'
|
||||||
dependency 'org.jasig.cas:cas-server-webapp:4.2.7'
|
dependency 'org.jasig.cas:cas-server-webapp:4.2.7'
|
||||||
dependency 'org.powermock:powermock-api-mockito2:2.0.6'
|
dependency 'org.powermock:powermock-api-mockito2:2.0.7'
|
||||||
dependency 'org.powermock:powermock-api-support:2.0.6'
|
dependency 'org.powermock:powermock-api-support:2.0.7'
|
||||||
dependency 'org.powermock:powermock-core:2.0.6'
|
dependency 'org.powermock:powermock-core:2.0.7'
|
||||||
dependency 'org.powermock:powermock-module-junit4-common:2.0.6'
|
dependency 'org.powermock:powermock-module-junit4-common:2.0.7'
|
||||||
dependency 'org.powermock:powermock-module-junit4:2.0.6'
|
dependency 'org.powermock:powermock-module-junit4:2.0.7'
|
||||||
dependency 'org.powermock:powermock-reflect:2.0.6'
|
dependency 'org.powermock:powermock-reflect:2.0.7'
|
||||||
dependency 'org.python:jython:2.5.0'
|
dependency 'org.python:jython:2.5.3'
|
||||||
dependency 'org.spockframework:spock-core:1.0-groovy-2.4'
|
dependency 'org.spockframework:spock-core:1.0-groovy-2.4'
|
||||||
dependency 'org.spockframework:spock-spring:1.0-groovy-2.4'
|
dependency 'org.spockframework:spock-spring:1.0-groovy-2.4'
|
||||||
}
|
}
|
||||||
@@ -33,18 +33,18 @@ dependencyManagement {
|
|||||||
dependency 'com.fasterxml.jackson.core:jackson-databind:2.9.10.2'
|
dependency 'com.fasterxml.jackson.core:jackson-databind:2.9.10.2'
|
||||||
dependency 'com.fasterxml:classmate:1.3.4'
|
dependency 'com.fasterxml:classmate:1.3.4'
|
||||||
dependency 'com.github.stephenc.jcip:jcip-annotations:1.0-1'
|
dependency 'com.github.stephenc.jcip:jcip-annotations:1.0-1'
|
||||||
dependency 'com.google.appengine:appengine-api-1.0-sdk:1.9.76'
|
dependency 'com.google.appengine:appengine-api-1.0-sdk:1.9.80'
|
||||||
dependency 'com.google.appengine:appengine-api-labs:1.9.76'
|
dependency 'com.google.appengine:appengine-api-labs:1.9.80'
|
||||||
dependency 'com.google.appengine:appengine-api-stubs:1.9.76'
|
dependency 'com.google.appengine:appengine-api-stubs:1.9.80'
|
||||||
dependency 'com.google.appengine:appengine-testing:1.9.76'
|
dependency 'com.google.appengine:appengine-testing:1.9.80'
|
||||||
dependency 'com.google.appengine:appengine:1.9.76'
|
dependency 'com.google.appengine:appengine:1.9.80'
|
||||||
dependency 'com.google.code.gson:gson:2.8.2'
|
dependency 'com.google.code.gson:gson:2.8.2'
|
||||||
dependency 'com.google.guava:guava:20.0'
|
dependency 'com.google.guava:guava:20.0'
|
||||||
dependency 'com.google.inject:guice:3.0'
|
dependency 'com.google.inject:guice:3.0'
|
||||||
dependency 'com.nimbusds:lang-tag:1.4.3'
|
dependency 'com.nimbusds:lang-tag:1.4.3'
|
||||||
dependency 'com.nimbusds:nimbus-jose-jwt:5.14'
|
dependency 'com.nimbusds:nimbus-jose-jwt:5.14'
|
||||||
dependency 'com.nimbusds:oauth2-oidc-sdk:5.64.4'
|
dependency 'com.nimbusds:oauth2-oidc-sdk:5.64.4'
|
||||||
dependency 'com.squareup.okhttp3:okhttp:3.12.10'
|
dependency 'com.squareup.okhttp3:okhttp:3.12.12'
|
||||||
dependency 'com.squareup.okio:okio:1.13.0'
|
dependency 'com.squareup.okio:okio:1.13.0'
|
||||||
dependency 'com.sun.xml.bind:jaxb-core:2.3.0.1'
|
dependency 'com.sun.xml.bind:jaxb-core:2.3.0.1'
|
||||||
dependency 'com.sun.xml.bind:jaxb-impl:2.3.0.1'
|
dependency 'com.sun.xml.bind:jaxb-impl:2.3.0.1'
|
||||||
|
|||||||
+17
-4
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.security.ldap.authentication.ad;
|
package org.springframework.security.ldap.authentication.ad;
|
||||||
|
|
||||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||||
|
import org.springframework.ldap.CommunicationException;
|
||||||
import org.springframework.ldap.core.DirContextOperations;
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
import org.springframework.ldap.core.DistinguishedName;
|
import org.springframework.ldap.core.DistinguishedName;
|
||||||
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
||||||
@@ -24,6 +25,7 @@ import org.springframework.security.authentication.AccountExpiredException;
|
|||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
@@ -141,12 +143,15 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
UsernamePasswordAuthenticationToken auth) {
|
UsernamePasswordAuthenticationToken auth) {
|
||||||
String username = auth.getName();
|
String username = auth.getName();
|
||||||
String password = (String) auth.getCredentials();
|
String password = (String) auth.getCredentials();
|
||||||
|
DirContext ctx = null;
|
||||||
DirContext ctx = bindAsUser(username, password);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
ctx = bindAsUser(username, password);
|
||||||
return searchForUser(ctx, username);
|
return searchForUser(ctx, username);
|
||||||
}
|
}
|
||||||
|
catch (CommunicationException e) {
|
||||||
|
throw badLdapConnection(e);
|
||||||
|
}
|
||||||
catch (NamingException e) {
|
catch (NamingException e) {
|
||||||
logger.error("Failed to locate directory entry for authenticated user: "
|
logger.error("Failed to locate directory entry for authenticated user: "
|
||||||
+ username, e);
|
+ username, e);
|
||||||
@@ -208,8 +213,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
|| (e instanceof OperationNotSupportedException)) {
|
|| (e instanceof OperationNotSupportedException)) {
|
||||||
handleBindException(bindPrincipal, e);
|
handleBindException(bindPrincipal, e);
|
||||||
throw badCredentials(e);
|
throw badCredentials(e);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw LdapUtils.convertLdapException(e);
|
throw LdapUtils.convertLdapException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,6 +315,12 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
return (BadCredentialsException) badCredentials().initCause(cause);
|
return (BadCredentialsException) badCredentials().initCause(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InternalAuthenticationServiceException badLdapConnection(Throwable cause) {
|
||||||
|
return new InternalAuthenticationServiceException(messages.getMessage(
|
||||||
|
"LdapAuthenticationProvider.badLdapConnection",
|
||||||
|
"Connection to LDAP server failed."), cause);
|
||||||
|
}
|
||||||
|
|
||||||
private DirContextOperations searchForUser(DirContext context, String username)
|
private DirContextOperations searchForUser(DirContext context, String username)
|
||||||
throws NamingException {
|
throws NamingException {
|
||||||
SearchControls searchControls = new SearchControls();
|
SearchControls searchControls = new SearchControls();
|
||||||
@@ -325,6 +335,9 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends
|
|||||||
searchControls, searchRoot, searchFilter,
|
searchControls, searchRoot, searchFilter,
|
||||||
new Object[] { bindPrincipal, username });
|
new Object[] { bindPrincipal, username });
|
||||||
}
|
}
|
||||||
|
catch (CommunicationException ldapCommunicationException) {
|
||||||
|
throw badLdapConnection(ldapCommunicationException);
|
||||||
|
}
|
||||||
catch (IncorrectResultSizeDataAccessException incorrectResults) {
|
catch (IncorrectResultSizeDataAccessException incorrectResults) {
|
||||||
// Search should never return multiple results if properly configured - just
|
// Search should never return multiple results if properly configured - just
|
||||||
// rethrow
|
// rethrow
|
||||||
|
|||||||
+22
-6
@@ -32,6 +32,7 @@ import org.springframework.security.authentication.AccountExpiredException;
|
|||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@@ -58,6 +59,9 @@ import static org.springframework.security.ldap.authentication.ad.ActiveDirector
|
|||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*/
|
*/
|
||||||
public class ActiveDirectoryLdapAuthenticationProviderTests {
|
public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||||
|
public static final String EXISTING_LDAP_PROVIDER = "ldap://192.168.1.200/";
|
||||||
|
public static final String NON_EXISTING_LDAP_PROVIDER = "ldap://192.168.1.201/";
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public ExpectedException thrown = ExpectedException.none();
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
@@ -378,17 +382,29 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = org.springframework.ldap.CommunicationException.class)
|
@Test(expected = org.springframework.ldap.CommunicationException.class)
|
||||||
public void nonAuthenticationExceptionIsConvertedToSpringLdapException()
|
public void nonAuthenticationExceptionIsConvertedToSpringLdapException() throws Throwable {
|
||||||
throws Exception {
|
try {
|
||||||
provider.contextFactory = createContextFactoryThrowing(new CommunicationException(
|
provider.contextFactory = createContextFactoryThrowing(new CommunicationException(
|
||||||
msg));
|
msg));
|
||||||
provider.authenticate(joe);
|
provider.authenticate(joe);
|
||||||
|
} catch (InternalAuthenticationServiceException e) {
|
||||||
|
// Since GH-8418 ldap communication exception is wrapped into InternalAuthenticationServiceException.
|
||||||
|
// This test is about the wrapped exception, so we throw it.
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = org.springframework.security.authentication.InternalAuthenticationServiceException.class )
|
||||||
|
public void connectionExceptionIsWrappedInInternalException() throws Exception {
|
||||||
|
ActiveDirectoryLdapAuthenticationProvider noneReachableProvider = new ActiveDirectoryLdapAuthenticationProvider(
|
||||||
|
"mydomain.eu", NON_EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain");
|
||||||
|
noneReachableProvider.doAuthentication(joe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rootDnProvidedSeparatelyFromDomainAlsoWorks() throws Exception {
|
public void rootDnProvidedSeparatelyFromDomainAlsoWorks() throws Exception {
|
||||||
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
|
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
|
||||||
"mydomain.eu", "ldap://192.168.1.200/", "dc=ad,dc=eu,dc=mydomain");
|
"mydomain.eu", EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain");
|
||||||
checkAuthentication("dc=ad,dc=eu,dc=mydomain", provider);
|
checkAuthentication("dc=ad,dc=eu,dc=mydomain", provider);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ import java.util.*;
|
|||||||
* requests which match the pattern. An example configuration might look like this:
|
* requests which match the pattern. An example configuration might look like this:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* <bean id="myfilterChainProxy" class="org.springframework.security.util.FilterChainProxy">
|
* <bean id="myfilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||||
* <constructor-arg>
|
* <constructor-arg>
|
||||||
* <util:list>
|
* <util:list>
|
||||||
* <security:filter-chain pattern="/do/not/filter*" filters="none"/>
|
* <security:filter-chain pattern="/do/not/filter*" filters="none"/>
|
||||||
|
|||||||
@@ -228,10 +228,15 @@ class DummyRequest extends HttpServletRequestWrapper {
|
|||||||
public void setQueryString(String queryString) {
|
public void setQueryString(String queryString) {
|
||||||
this.queryString = queryString;
|
this.queryString = queryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
|
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
throw new UnsupportedOperationException(method + " is not supported");
|
throw new UnsupportedOperationException(method + " is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2017 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,15 @@
|
|||||||
|
|
||||||
package org.springframework.security.web.firewall;
|
package org.springframework.security.web.firewall;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -59,10 +60,15 @@ import java.util.Set;
|
|||||||
* Rejects URLs that contain a URL encoded percent. See
|
* Rejects URLs that contain a URL encoded percent. See
|
||||||
* {@link #setAllowUrlEncodedPercent(boolean)}
|
* {@link #setAllowUrlEncodedPercent(boolean)}
|
||||||
* </li>
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Rejects hosts that are not allowed. See
|
||||||
|
* {@link #setAllowedHostnames(Predicate)}
|
||||||
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @see DefaultHttpFirewall
|
* @see DefaultHttpFirewall
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Eddú Meléndez
|
||||||
* @since 5.0.1
|
* @since 5.0.1
|
||||||
*/
|
*/
|
||||||
public class StrictHttpFirewall implements HttpFirewall {
|
public class StrictHttpFirewall implements HttpFirewall {
|
||||||
@@ -82,6 +88,8 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
|
|
||||||
private Set<String> decodedUrlBlacklist = new HashSet<String>();
|
private Set<String> decodedUrlBlacklist = new HashSet<String>();
|
||||||
|
|
||||||
|
private Predicate<String> allowedHostnames = hostname -> true;
|
||||||
|
|
||||||
public StrictHttpFirewall() {
|
public StrictHttpFirewall() {
|
||||||
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
||||||
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
||||||
@@ -230,6 +238,21 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Determines which hostnames should be allowed. The default is to allow any hostname.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param allowedHostnames the predicate for testing hostnames
|
||||||
|
* @since 5.0.17
|
||||||
|
*/
|
||||||
|
public void setAllowedHostnames(Predicate<String> allowedHostnames) {
|
||||||
|
if (allowedHostnames == null) {
|
||||||
|
throw new IllegalArgumentException("allowedHostnames cannot be null");
|
||||||
|
}
|
||||||
|
this.allowedHostnames = allowedHostnames;
|
||||||
|
}
|
||||||
|
|
||||||
private void urlBlacklistsAddAll(Collection<String> values) {
|
private void urlBlacklistsAddAll(Collection<String> values) {
|
||||||
this.encodedUrlBlacklist.addAll(values);
|
this.encodedUrlBlacklist.addAll(values);
|
||||||
this.decodedUrlBlacklist.addAll(values);
|
this.decodedUrlBlacklist.addAll(values);
|
||||||
@@ -243,6 +266,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
@Override
|
@Override
|
||||||
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
|
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
|
||||||
rejectedBlacklistedUrls(request);
|
rejectedBlacklistedUrls(request);
|
||||||
|
rejectedUntrustedHosts(request);
|
||||||
|
|
||||||
if (!isNormalized(request)) {
|
if (!isNormalized(request)) {
|
||||||
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
|
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
|
||||||
@@ -272,6 +296,13 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void rejectedUntrustedHosts(HttpServletRequest request) {
|
||||||
|
String serverName = request.getServerName();
|
||||||
|
if (serverName != null && !this.allowedHostnames.test(serverName)) {
|
||||||
|
throw new RequestRejectedException("The request was rejected because the domain " + serverName + " is untrusted.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
|
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
|
||||||
return new FirewalledResponse(response);
|
return new FirewalledResponse(response);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -54,6 +54,7 @@ import java.util.Set;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Parikshit Dutta
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class CsrfWebFilter implements WebFilter {
|
public class CsrfWebFilter implements WebFilter {
|
||||||
@@ -133,7 +134,7 @@ public class CsrfWebFilter implements WebFilter {
|
|||||||
@Override
|
@Override
|
||||||
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
public Mono<MatchResult> matches(ServerWebExchange exchange) {
|
||||||
return Mono.just(exchange.getRequest())
|
return Mono.just(exchange.getRequest())
|
||||||
.map(r -> r.getMethod())
|
.flatMap(r -> Mono.justOrEmpty(r.getMethod()))
|
||||||
.filter(m -> ALLOWED_METHODS.contains(m))
|
.filter(m -> ALLOWED_METHODS.contains(m))
|
||||||
.flatMap(m -> MatchResult.notMatch())
|
.flatMap(m -> MatchResult.notMatch())
|
||||||
.switchIfEmpty(MatchResult.match());
|
.switchIfEmpty(MatchResult.match());
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ public final class AntPathRequestMatcher
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a matcher with the specific pattern which will match all HTTP methods in a
|
* Creates a matcher with the specific pattern which will match all HTTP methods in a
|
||||||
* case insensitive manner.
|
* case sensitive manner.
|
||||||
*
|
*
|
||||||
* @param pattern the ant pattern to use for matching
|
* @param pattern the ant pattern to use for matching
|
||||||
*/
|
*/
|
||||||
@@ -76,7 +76,7 @@ public final class AntPathRequestMatcher
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a matcher with the supplied pattern and HTTP method in a case insensitive
|
* Creates a matcher with the supplied pattern and HTTP method in a case sensitive
|
||||||
* manner.
|
* manner.
|
||||||
*
|
*
|
||||||
* @param pattern the ant pattern to use for matching
|
* @param pattern the ant pattern to use for matching
|
||||||
|
|||||||
+28
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2017 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.fail;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Eddú Meléndez
|
||||||
*/
|
*/
|
||||||
public class StrictHttpFirewallTests {
|
public class StrictHttpFirewallTests {
|
||||||
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.",
|
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.",
|
||||||
@@ -373,4 +374,30 @@ public class StrictHttpFirewallTests {
|
|||||||
|
|
||||||
this.firewall.getFirewalledRequest(request);
|
this.firewall.getFirewalledRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenTrustedDomainThenNoException() {
|
||||||
|
String host = "example.org";
|
||||||
|
this.request.addHeader("Host", host);
|
||||||
|
this.firewall.setAllowedHostnames(hostname -> hostname.equals("example.org"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.firewall.getFirewalledRequest(this.request);
|
||||||
|
} catch (RequestRejectedException fail) {
|
||||||
|
fail("Host " + host + " was rejected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenUntrustedDomainThenException() {
|
||||||
|
String host = "example.org";
|
||||||
|
this.request.addHeader("Host", host);
|
||||||
|
this.firewall.setAllowedHostnames(hostname -> hostname.equals("myexample.org"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.firewall.getFirewalledRequest(this.request);
|
||||||
|
fail("Host " + host + " was accepted");
|
||||||
|
} catch (RequestRejectedException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user