Compare commits
200 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4619705e37 | |||
| f09ce267b3 | |||
| 374aceed2b | |||
| df703e0189 | |||
| 8c580dc170 | |||
| 5205bf57c6 | |||
| 994117ad75 | |||
| b7041ed00e | |||
| 053c890a69 | |||
| 7838e3eeca | |||
| 2df5541905 | |||
| 04fac30d75 | |||
| 54ffa28bde | |||
| ca1080fb96 | |||
| 4708287ad3 | |||
| 0d12397662 | |||
| a34178bc40 | |||
| aaa7cec32e | |||
| 6f9085dd5d | |||
| 7f714ebb23 | |||
| 00d668dc5c | |||
| 035067caf4 | |||
| 0da9b6c64b | |||
| 418bb57323 | |||
| 4672c2a1f7 | |||
| 4460e84b29 | |||
| 548ed4e14a | |||
| 6be4de854a | |||
| feeb380b51 | |||
| ec524da6cb | |||
| fc6fc19eed | |||
| fa39ecd719 | |||
| 7e274ea5b6 | |||
| 8e8bdad8e6 | |||
| f2fdc9d1f5 | |||
| 74a6303b6f | |||
| be15213819 | |||
| 595b16d836 | |||
| 2a632a061e | |||
| 4308e72573 | |||
| b8cc42e3a3 | |||
| ab08d99a52 | |||
| 135df149a3 | |||
| c6a534cad8 | |||
| 0b996c669f | |||
| 13c5af5b91 | |||
| e97758dd3a | |||
| 209cf317d6 | |||
| 5641ab98c1 | |||
| c7b93e6cee | |||
| 59e13e7bbb | |||
| 5a59c74d02 | |||
| 5bc6f64b03 | |||
| bc6fc518d3 | |||
| 9dbe30c81d | |||
| 2d2f91484d | |||
| afddb5eb39 | |||
| 1745715865 | |||
| 6382b6341a | |||
| 85cd5627b6 | |||
| 4944e602cb | |||
| f1f3acdf75 | |||
| 2c8946c406 | |||
| 9c703a3051 | |||
| dc317b3602 | |||
| e657f89662 | |||
| cda23443ac | |||
| 2ef53234d0 | |||
| c135179029 | |||
| cf3e2f2c6a | |||
| 26be54653b | |||
| fa3d303f79 | |||
| 17b9f33351 | |||
| 5427da6b27 | |||
| 1a1f577a8b | |||
| 9e7fbf8067 | |||
| 78f85cc129 | |||
| 85ec2429d9 | |||
| e638f0a547 | |||
| 355f884d22 | |||
| 4a24c81147 | |||
| 5f290ba10f | |||
| a3009e303b | |||
| 6ea95cc3a3 | |||
| 04b091c385 | |||
| 15a63c58a7 | |||
| 604c26eb0d | |||
| 348e3a22b6 | |||
| db3c626ac9 | |||
| e3f58fd9d3 | |||
| bbefc62a87 | |||
| 730dcffe6d | |||
| bf3b5459cd | |||
| 1351c8bada | |||
| 0978c12c47 | |||
| e50b587d60 | |||
| 0b0e7dbea9 | |||
| 51171efa7a | |||
| 45ad74a0bd | |||
| 14b9050616 | |||
| f2b44e6beb | |||
| 4ef0460ef6 | |||
| 7d99436740 | |||
| 0ac1176152 | |||
| 76a8bbe98d | |||
| cffbefadd1 | |||
| 611a97023d | |||
| 5f10d84bf5 | |||
| d28058303b | |||
| dd1c2483b5 | |||
| 4b43cf3f50 | |||
| df5e034fc3 | |||
| 8087cde628 | |||
| 8fed90c26c | |||
| 3e95f1c12e | |||
| ee33a6deeb | |||
| 17efd25717 | |||
| 06a0ec1a9f | |||
| 9bb283044f | |||
| 614c94187e | |||
| e696890e8e | |||
| 61e6acb3f4 | |||
| e5f034bdef | |||
| a09756745f | |||
| fb0a8d19e8 | |||
| cea0cf9260 | |||
| 56ce7d284c | |||
| 1f3b812a66 | |||
| ef7cc40389 | |||
| d16106ef56 | |||
| b591881e95 | |||
| 88f41cdf62 | |||
| a888ddf8b3 | |||
| ddc0ef7ab3 | |||
| 28fb6ba14b | |||
| b16c17f70b | |||
| a3d112979f | |||
| f294480e6b | |||
| 788ba9a1fa | |||
| 7537dfc33a | |||
| 5082a04626 | |||
| 9133c33f1d | |||
| 8f8c6169e8 | |||
| c5c1419521 | |||
| d33b9e2854 | |||
| c156716be8 | |||
| 0114b457c0 | |||
| 05a7c58daa | |||
| e5804d323b | |||
| be8aad8306 | |||
| d9c9cd7f84 | |||
| b4cbcee7f0 | |||
| f6587c8697 | |||
| 32e9239fd2 | |||
| b22acd0768 | |||
| 53a0db6be1 | |||
| 662bb24370 | |||
| 3c82e63ded | |||
| 8e74407381 | |||
| e8ac11641b | |||
| 7203faf34f | |||
| 3d2f23602f | |||
| 43f4d01cf3 | |||
| 6e9fb7930b | |||
| 98fe2322cd | |||
| fc16450344 | |||
| 246c632f3a | |||
| 664220f304 | |||
| 86340b8016 | |||
| ae368829f4 | |||
| d89cf6db29 | |||
| 4761614c9f | |||
| 69aac09e1d | |||
| 9483226d02 | |||
| aca2e4ff3a | |||
| 086056f191 | |||
| 26166ef6e8 | |||
| 3f69847a4e | |||
| d60108eaf6 | |||
| 98bdd32ca0 | |||
| 33db440961 | |||
| 7d1d856729 | |||
| 18bd82e7d4 | |||
| cd7055f725 | |||
| 7f2308f46c | |||
| 534989c8ea | |||
| acb2b680d0 | |||
| f29505d657 | |||
| 48283ec004 | |||
| c131fb6379 | |||
| 03b235295e | |||
| efa9f4db93 | |||
| 379cbd2a8b | |||
| e8788f2657 | |||
| 17c2a18fee | |||
| 0247dd124f | |||
| a3a432f7b6 | |||
| 3b2156969d | |||
| f707101fdb | |||
| eb95c500f5 |
@@ -19,3 +19,4 @@ build/
|
||||
*.iws
|
||||
.gradle/
|
||||
atlassian-ide-plugin.xml
|
||||
/samples
|
||||
|
||||
+1
-1
@@ -14,5 +14,5 @@ dependencies {
|
||||
"org.springframework:spring-context-support:$springVersion",
|
||||
"org.springframework:spring-test:$springVersion"
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion"
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
|
||||
}
|
||||
+25
-31
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-acl</name>
|
||||
<description>spring-security-acl</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -88,13 +82,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -117,16 +111,10 @@
|
||||
<version>0.9.29</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.7</version>
|
||||
<version>4.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -135,10 +123,16 @@
|
||||
<version>1.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,19 +144,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -98,7 +98,7 @@ public abstract class AclFormattingUtils {
|
||||
}
|
||||
|
||||
private static String printBinary(int i, char on, char off) {
|
||||
String s = Integer.toString(i, 2);
|
||||
String s = Integer.toBinaryString(i);
|
||||
String pattern = Permission.THIRTY_TWO_RESERVED_OFF;
|
||||
String temp2 = pattern.substring(0, pattern.length() - s.length()) + s;
|
||||
|
||||
|
||||
@@ -119,6 +119,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
* @param acl containing the ACEs to insert
|
||||
*/
|
||||
protected void createEntries(final MutableAcl acl) {
|
||||
if(acl.getEntries().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
jdbcTemplate.batchUpdate(insertEntry,
|
||||
new BatchPreparedStatementSetter() {
|
||||
public int getBatchSize() {
|
||||
|
||||
@@ -124,4 +124,12 @@ public class AclFormattingUtilsTests extends TestCase {
|
||||
|
||||
Assert.assertEquals("............................xxxx", AclFormattingUtils.printBinary(15, 'x'));
|
||||
}
|
||||
|
||||
public void testPrintBinaryNegative() {
|
||||
Assert.assertEquals("*...............................", AclFormattingUtils.printBinary(0x80000000));
|
||||
}
|
||||
|
||||
public void testPrintBinaryMinusOne() {
|
||||
Assert.assertEquals("********************************", AclFormattingUtils.printBinary(0xffffffff));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class BasicLookupStrategyTests {
|
||||
//~ Methods ========================================================================================================
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = new CacheManager();
|
||||
cacheManager = CacheManager.create();
|
||||
cacheManager.addCache(new Cache("basiclookuptestcache", 500, false, false, 30, 30));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class EhCacheBasedAclCacheTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = new CacheManager();
|
||||
cacheManager = CacheManager.create();
|
||||
// Use disk caching immediately (to test for serialization issue reported in SEC-527)
|
||||
cacheManager.addCache(new Cache("ehcachebasedacltests", 0, true, false, 600, 300));
|
||||
}
|
||||
|
||||
+1
@@ -105,6 +105,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
||||
jdbcTemplate.execute("drop table acl_object_identity");
|
||||
jdbcTemplate.execute("drop table acl_class");
|
||||
jdbcTemplate.execute("drop table acl_sid");
|
||||
aclCache.clearCache();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+16
-22
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-aspects</name>
|
||||
<description>spring-security-aspects</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,35 +42,29 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -108,7 +102,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.7</version>
|
||||
<version>4.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -120,7 +114,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -132,13 +126,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
apply plugin: 'maven-bom'
|
||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||
|
||||
generatePom.enabled = false
|
||||
sonarRunner.skipProject = true
|
||||
|
||||
mavenBom {
|
||||
projects = coreModuleProjects
|
||||
}
|
||||
+34
-9
@@ -3,15 +3,14 @@ import groovy.text.SimpleTemplateEngine
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
maven { url "http://dl.bintray.com/content/aalmiray/asciidoctor" }
|
||||
maven { url "http://jcenter.bintray.com"}
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
|
||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.7")
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.5")
|
||||
classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2")
|
||||
classpath("org.gradle.api.plugins:gradle-tomcat-plugin:0.9.8")
|
||||
classpath("org.asciidoctor:asciidoctor-gradle-plugin:0.4.1")
|
||||
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
||||
classpath('org.asciidoctor:asciidoctor-gradle-plugin:0.7.0')
|
||||
classpath('org.asciidoctor:asciidoctor-java-integration:0.1.4.preview.1')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +25,15 @@ allprojects {
|
||||
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.springVersion = '3.2.6.RELEASE'
|
||||
ext.spring4Version = '4.0.0.RELEASE'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
|
||||
repositories {
|
||||
maven { url "http://repo.springsource.org/libs-release" }
|
||||
mavenCentral()
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
maven { url "http://repo.terracotta.org/maven2/" }
|
||||
}
|
||||
|
||||
eclipse.project.name = "${project.name}-3.2.x"
|
||||
@@ -52,7 +54,7 @@ sonarRunner {
|
||||
}
|
||||
|
||||
// Set up different subproject lists for individual configuration
|
||||
ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && project.name != 'faq' && project.name != 'manual' && project.name != 'guides' }
|
||||
ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && project.name != 'manual' && project.name != 'guides' && project.name != 'spring-security-bom' }
|
||||
ext.sampleProjects = subprojects.findAll { project -> project.name.startsWith('spring-security-samples') }
|
||||
ext.itestProjects = subprojects.findAll { project -> project.name.startsWith('itest') }
|
||||
ext.coreModuleProjects = javaProjects - sampleProjects - itestProjects
|
||||
@@ -77,7 +79,7 @@ configure(allprojects - javaProjects) {
|
||||
}
|
||||
}
|
||||
|
||||
configure(subprojects - coreModuleProjects) {
|
||||
configure(subprojects - coreModuleProjects - project(':spring-security-samples-messages-jc') - project(':spring-security-bom')) {
|
||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
sonarRunner {
|
||||
skipProject = true
|
||||
@@ -102,7 +104,22 @@ configure(coreModuleProjects) {
|
||||
}
|
||||
configurations {
|
||||
jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
|
||||
spring4TestRuntime.extendsFrom testRuntime
|
||||
}
|
||||
configurations.spring4TestRuntime {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.springframework') {
|
||||
details.useVersion spring4Version
|
||||
}
|
||||
if (details.requested.name == 'ehcache') {
|
||||
details.useVersion '2.6.5'
|
||||
}
|
||||
if (details.requested.name == 'ehcache-terracotta') {
|
||||
details.useVersion '2.1.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
jacoco "org.jacoco:org.jacoco.agent:0.6.2.201302030002:runtime"
|
||||
}
|
||||
@@ -112,6 +129,14 @@ configure(coreModuleProjects) {
|
||||
integrationTest {
|
||||
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
|
||||
}
|
||||
task spring4Test(type: Test) {
|
||||
jvmArgs = ['-ea', '-Xmx500m', '-XX:MaxPermSize=128M']
|
||||
exclude "**/EhCacheBasedAclCacheTests.class", "**/Issue55Tests.class"
|
||||
classpath = sourceSets.test.output + sourceSets.main.output + configurations.spring4TestRuntime
|
||||
testResultsDir = file("$buildDir/spring4-test-results/")
|
||||
testReportDir = file("$buildDir/reports/spring4-tests/")
|
||||
}
|
||||
check.dependsOn spring4Test
|
||||
}
|
||||
|
||||
configure (aspectjProjects) {
|
||||
@@ -163,5 +188,5 @@ artifacts {
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.7'
|
||||
gradleVersion = '1.10-rc-2'
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ repositories {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
}
|
||||
|
||||
// GAE
|
||||
dependencies {
|
||||
compile 'com.google.appengine:appengine-tools-sdk:1.4.2'
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.plugins.*
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
public class MavenBomPlugin implements Plugin<Project> {
|
||||
static String MAVEN_BOM_TASK_NAME = "mavenBom"
|
||||
|
||||
public void apply(Project project) {
|
||||
project.plugins.apply(JavaPlugin)
|
||||
project.plugins.apply(MavenPlugin)
|
||||
project.task(MAVEN_BOM_TASK_NAME, type: MavenBomTask, group: 'Generate', description: 'Configures the pom as a Maven Build of Materials (BOM)')
|
||||
project.install.dependsOn project.mavenBom
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import groovy.xml.MarkupBuilder
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
public class MavenBomTask extends DefaultTask {
|
||||
|
||||
Set<Project> projects
|
||||
|
||||
File bomFile
|
||||
|
||||
|
||||
public MavenBomTask() {
|
||||
this.group = "Generate"
|
||||
this.description = "Generates a Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies"
|
||||
this.projects = project.subprojects
|
||||
this.bomFile = project.file("${->project.buildDir}/maven-bom/${->project.name}-${->project.version}.txt")
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void configureBom() {
|
||||
project.configurations.archives.artifacts.clear()
|
||||
|
||||
bomFile.parentFile.mkdirs()
|
||||
bomFile.write("Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies")
|
||||
project.artifacts {
|
||||
// work around GRADLE-2406 by attaching text artifact
|
||||
archives(bomFile)
|
||||
}
|
||||
project.install {
|
||||
repositories.mavenInstaller {
|
||||
pom.whenConfigured {
|
||||
packaging = "pom"
|
||||
withXml {
|
||||
asNode().children().last() + {
|
||||
delegate.dependencyManagement {
|
||||
delegate.dependencies {
|
||||
projects.sort { dep -> "$dep.group:$dep.name" }.each { p ->
|
||||
|
||||
delegate.dependency {
|
||||
delegate.groupId(p.group)
|
||||
delegate.artifactId(p.name)
|
||||
delegate.version(p.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=MavenBomPlugin
|
||||
+17
-23
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-cas</name>
|
||||
<description>spring-security-cas</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -94,7 +88,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -126,7 +120,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.7</version>
|
||||
<version>4.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -138,7 +132,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ public class EhCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTe
|
||||
//~ Methods ========================================================================================================
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = new CacheManager();
|
||||
cacheManager = CacheManager.create();
|
||||
cacheManager.addCache(new Cache("castickets", 500, false, false, 30, 30));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ dependencies {
|
||||
project(':spring-security-openid'),
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.springframework:spring-webmvc:$springVersion",
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion"
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion"
|
||||
|
||||
provided "org.apache.tomcat:tomcat-servlet-api:$servletApiVersion"
|
||||
|
||||
@@ -50,7 +52,7 @@ dependencies {
|
||||
}
|
||||
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion",
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:2.2"
|
||||
}
|
||||
|
||||
@@ -58,10 +60,6 @@ test {
|
||||
inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
|
||||
}
|
||||
|
||||
integrationTest {
|
||||
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
|
||||
}
|
||||
|
||||
rncToXsd {
|
||||
rncDir = file('src/main/resources/org/springframework/security/config/')
|
||||
xsdDir = rncDir
|
||||
|
||||
+51
-55
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-config</name>
|
||||
<description>spring-security-config</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -108,35 +102,49 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -158,12 +166,6 @@
|
||||
<version>0.9.29</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
@@ -173,7 +175,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.7</version>
|
||||
<version>4.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -242,10 +244,16 @@
|
||||
<version>4.1.0.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -263,37 +271,37 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<version>1.5.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-support</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<version>1.5.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-core</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<version>1.5.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<version>1.5.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4-common</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<version>1.5.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-reflect</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<version>1.5.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -311,43 +319,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap-core</artifactId>
|
||||
<version>1.3.1.RELEASE</version>
|
||||
<version>1.3.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.0.RC1</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+5
-18
@@ -53,8 +53,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
|
||||
@Configuration
|
||||
static class DefaultLdapConfig extends BaseLdapProviderConfig {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
@@ -71,7 +70,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
|
||||
@Configuration
|
||||
static class GroupRolesConfig extends BaseLdapProviderConfig {
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
@@ -89,8 +88,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
|
||||
@Configuration
|
||||
static class GroupSearchConfig extends BaseLdapProviderConfig {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
@@ -108,8 +106,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
|
||||
@Configuration
|
||||
static class RolePrefixConfig extends BaseLdapProviderConfig {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
@@ -128,8 +125,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
|
||||
@Configuration
|
||||
static class BindAuthenticationConfig extends BaseLdapServerConfig {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
@@ -154,15 +150,6 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
|
||||
@Configuration
|
||||
static abstract class BaseLdapProviderConfig {
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() {
|
||||
AuthenticationManagerBuilder registry = new AuthenticationManagerBuilder();
|
||||
registerAuthentication(registry);
|
||||
return registry.build();
|
||||
}
|
||||
|
||||
protected abstract void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception;
|
||||
|
||||
@Bean
|
||||
public BaseLdapPathContextSource contextSource() throws Exception {
|
||||
|
||||
+3
-6
@@ -31,8 +31,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class LdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
@@ -43,8 +42,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class CustomLdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupRoleAttribute("cn") // ldap-authentication-provider@group-role-attribute
|
||||
@@ -70,8 +68,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
|
||||
+20
-4
@@ -12,7 +12,10 @@
|
||||
*/
|
||||
package org.springframework.security.config.ldap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
@@ -50,10 +53,11 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useOfUrlAttributeCreatesCorrectContextSource() {
|
||||
public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception {
|
||||
int port = getDefaultPort();
|
||||
// Create second "server" with a url pointing at embedded one
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='33388'/>" +
|
||||
"<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:33388/dc=springframework,dc=org' />");
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='" + port + "'/>" +
|
||||
"<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:" + port + "/dc=springframework,dc=org' />");
|
||||
|
||||
// Check the default context source is still there.
|
||||
appCtx.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
@@ -83,4 +87,16 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
|
||||
assertEquals("classpath*:*.ldif", ReflectionTestUtils.getField(dsContainer, "ldifResources"));
|
||||
}
|
||||
|
||||
private int getDefaultPort() throws IOException {
|
||||
ServerSocket server = null;
|
||||
try {
|
||||
server = new ServerSocket(0);
|
||||
return server.getLocalPort();
|
||||
} finally {
|
||||
try {
|
||||
server.close();
|
||||
} catch(IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-7
@@ -66,13 +66,6 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
||||
|
||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
/**
|
||||
* Creates a new instance without post processing
|
||||
*/
|
||||
protected AbstractConfiguredSecurityBuilder() {
|
||||
this(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a new instance with the provided {@link ObjectPostProcessor}.
|
||||
* This post processor must support Object since there are many types of
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
|
||||
object = doBuild();
|
||||
return object;
|
||||
}
|
||||
throw new IllegalStateException("This object has already been built");
|
||||
throw new AlreadyBuiltException("This object has already been built");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation;
|
||||
|
||||
/**
|
||||
* Thrown when {@link AbstractSecurityBuilder#build()} is two or more times.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public class AlreadyBuiltException extends IllegalStateException {
|
||||
|
||||
public AlreadyBuiltException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -5891004752785553015L;
|
||||
}
|
||||
+1
-10
@@ -39,13 +39,4 @@ public interface ObjectPostProcessor<T> {
|
||||
* @return the initialized version of the object
|
||||
*/
|
||||
<O extends T> O postProcess(O object);
|
||||
|
||||
/**
|
||||
* A do nothing implementation of the {@link ObjectPostProcessor}
|
||||
*/
|
||||
ObjectPostProcessor<Object> QUIESCENT_POSTPROCESSOR = new ObjectPostProcessor<Object>() {
|
||||
public <T> T postProcess(T object) {
|
||||
return object;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ public interface SecurityBuilder<O> {
|
||||
* Builds the object and returns it or null.
|
||||
*
|
||||
* @return the Object to be built or null if the implementation allows it.
|
||||
* @throws Exception if an error occured when building the Object
|
||||
* @throws Exception if an error occurred when building the Object
|
||||
*/
|
||||
O build() throws Exception;
|
||||
}
|
||||
|
||||
+7
@@ -18,6 +18,8 @@ package org.springframework.security.config.annotation.authentication.builders;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
@@ -45,6 +47,7 @@ import org.springframework.util.Assert;
|
||||
* @since 3.2
|
||||
*/
|
||||
public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder> implements ProviderManagerBuilder<AuthenticationManagerBuilder> {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private AuthenticationManager parentAuthenticationManager;
|
||||
private List<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>();
|
||||
@@ -218,6 +221,10 @@ public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuil
|
||||
|
||||
@Override
|
||||
protected ProviderManager performBuild() throws Exception {
|
||||
if(authenticationProviders.isEmpty() && parentAuthenticationManager == null) {
|
||||
logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
|
||||
return null;
|
||||
}
|
||||
ProviderManager providerManager = new ProviderManager(authenticationProviders, parentAuthenticationManager);
|
||||
if(eraseCredentials != null) {
|
||||
providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
|
||||
|
||||
+10
-1
@@ -52,7 +52,16 @@ final class AutowireBeanFactoryObjectPostProcessor implements ObjectPostProcesso
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T postProcess(T object) {
|
||||
T result = (T) autowireBeanFactory.initializeBean(object, null);
|
||||
if(object == null) {
|
||||
return null;
|
||||
}
|
||||
T result = null;
|
||||
try {
|
||||
result = (T) autowireBeanFactory.initializeBean(object, object.toString());
|
||||
} catch (RuntimeException e) {
|
||||
Class<?> type = object.getClass();
|
||||
throw new RuntimeException("Could not postProcess " + object + " of type " + type, e);
|
||||
}
|
||||
if(result instanceof DisposableBean) {
|
||||
disposableBeans.add((DisposableBean) result);
|
||||
}
|
||||
|
||||
+44
-28
@@ -39,7 +39,9 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.security.access.AccessDecisionManager;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.AfterInvocationProvider;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.annotation.Jsr250Voter;
|
||||
import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
|
||||
@@ -61,6 +63,7 @@ import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.access.vote.AuthenticatedVoter;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
@@ -84,8 +87,9 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
throw new IllegalStateException(ObjectPostProcessor.class.getName()+ " is a required bean. Ensure you have used @"+EnableGlobalMethodSecurity.class.getName());
|
||||
}
|
||||
};
|
||||
private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
private AuthenticationManager authenticationManager;
|
||||
private AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR);
|
||||
private AuthenticationManagerBuilder auth;
|
||||
private boolean disableAuthenticationRegistry;
|
||||
private AnnotationAttributes enableMethodSecurity;
|
||||
private MethodSecurityExpressionHandler expressionHandler;
|
||||
@@ -178,25 +182,33 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
|
||||
ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
|
||||
expressionAdvice.setExpressionHandler(getExpressionHandler());
|
||||
|
||||
decisionVoters.add(new PreInvocationAuthorizationAdviceVoter(
|
||||
if(prePostEnabled()) {
|
||||
decisionVoters.add(new PreInvocationAuthorizationAdviceVoter(
|
||||
expressionAdvice));
|
||||
}
|
||||
if(jsr250Enabled()) {
|
||||
decisionVoters.add(new Jsr250Voter());
|
||||
}
|
||||
decisionVoters.add(new RoleVoter());
|
||||
decisionVoters.add(new AuthenticatedVoter());
|
||||
return new AffirmativeBased(decisionVoters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@link MethodSecurityExpressionHandler} that is
|
||||
* registered with the {@link ExpressionBasedPreInvocationAdvice}. The default is
|
||||
* {@link DefaultMethodSecurityExpressionHandler}
|
||||
* Provide a {@link MethodSecurityExpressionHandler} that is registered with
|
||||
* the {@link ExpressionBasedPreInvocationAdvice}. The default is
|
||||
* {@link DefaultMethodSecurityExpressionHandler} which optionally will
|
||||
* Autowire an {@link AuthenticationTrustResolver}.
|
||||
*
|
||||
* <p>Subclasses may override this method to provide a custom {@link MethodSecurityExpressionHandler}</p>
|
||||
* <p>
|
||||
* Subclasses may override this method to provide a custom
|
||||
* {@link MethodSecurityExpressionHandler}
|
||||
* </p>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected MethodSecurityExpressionHandler expressionHandler() {
|
||||
return new DefaultMethodSecurityExpressionHandler();
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
return defaultMethodExpressionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,7 +218,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
*/
|
||||
protected final MethodSecurityExpressionHandler getExpressionHandler() {
|
||||
if(expressionHandler == null) {
|
||||
expressionHandler = expressionHandler();
|
||||
expressionHandler = createExpressionHandler();
|
||||
}
|
||||
return expressionHandler;
|
||||
}
|
||||
@@ -224,8 +236,8 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
|
||||
/**
|
||||
* Allows providing a custom {@link AuthenticationManager}. The default is
|
||||
* to use any authentication mechanisms registered by {@link #registerAuthentication(AuthenticationManagerBuilder)}. If
|
||||
* {@link #registerAuthentication(AuthenticationManagerBuilder)} was not overriden, then an {@link AuthenticationManager}
|
||||
* to use any authentication mechanisms registered by {@link #configure(AuthenticationManagerBuilder)}. If
|
||||
* {@link #configure(AuthenticationManagerBuilder)} was not overridden, then an {@link AuthenticationManager}
|
||||
* is attempted to be autowired by type.
|
||||
*
|
||||
* @return
|
||||
@@ -233,9 +245,9 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
if(authenticationManager == null) {
|
||||
DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
|
||||
auth = new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
auth.authenticationEventPublisher(eventPublisher);
|
||||
auth.objectPostProcessor(objectPostProcessor);
|
||||
registerAuthentication(auth);
|
||||
configure(auth);
|
||||
if(!disableAuthenticationRegistry) {
|
||||
authenticationManager = auth.build();
|
||||
}
|
||||
@@ -255,13 +267,13 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
|
||||
/**
|
||||
* Sub classes can override this method to register different types of authentication. If not overridden,
|
||||
* {@link #registerAuthentication(AuthenticationManagerBuilder)} will attempt to autowire by type.
|
||||
* {@link #configure(AuthenticationManagerBuilder)} will attempt to autowire by type.
|
||||
*
|
||||
* @param auth the {@link AuthenticationManagerBuilder} used to register different authentication mechanisms for the
|
||||
* global method security.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
this.disableAuthenticationRegistry = true;
|
||||
}
|
||||
|
||||
@@ -277,7 +289,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
|
||||
List<MethodSecurityMetadataSource> sources = new ArrayList<MethodSecurityMetadataSource>();
|
||||
ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory(
|
||||
methodExpressionHandler());
|
||||
getExpressionHandler());
|
||||
MethodSecurityMetadataSource customMethodSecurityMetadataSource = customMethodSecurityMetadataSource();
|
||||
if (customMethodSecurityMetadataSource != null) {
|
||||
sources.add(customMethodSecurityMetadataSource);
|
||||
@@ -295,16 +307,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
return new DelegatingMethodSecurityMetadataSource(sources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link MethodSecurityExpressionHandler} to be used.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public MethodSecurityExpressionHandler methodExpressionHandler() {
|
||||
return new DefaultMethodSecurityExpressionHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link PreInvocationAuthorizationAdvice} to be used. The
|
||||
* default is {@link ExpressionBasedPreInvocationAdvice}.
|
||||
@@ -314,7 +316,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
@Bean
|
||||
public PreInvocationAuthorizationAdvice preInvocationAuthorizationAdvice() {
|
||||
ExpressionBasedPreInvocationAdvice preInvocationAdvice = new ExpressionBasedPreInvocationAdvice();
|
||||
preInvocationAdvice.setExpressionHandler(methodExpressionHandler());
|
||||
preInvocationAdvice.setExpressionHandler(getExpressionHandler());
|
||||
return preInvocationAdvice;
|
||||
}
|
||||
|
||||
@@ -344,6 +346,11 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
.fromMap(annotationAttributes);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setAuthenticationTrustResolver(AuthenticationTrustResolver trustResolver) {
|
||||
this.defaultMethodExpressionHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
this.context = context;
|
||||
@@ -352,6 +359,15 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
@Autowired(required=false)
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
this.defaultMethodExpressionHandler = objectPostProcessor.postProcess(defaultMethodExpressionHandler);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setPermissionEvaluator(List<PermissionEvaluator> permissionEvaluators) {
|
||||
if(permissionEvaluators.size() != 1) {
|
||||
logger.debug("Not autwiring PermissionEvaluator since size != 1. Got " + permissionEvaluators);
|
||||
}
|
||||
this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluators.get(0));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
+17
-21
@@ -20,33 +20,29 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractRequestMatcherMappingConfigurer;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for specifying which
|
||||
* {@link RequestMatcher} require a certain level of authorization.
|
||||
*
|
||||
*
|
||||
* @param <B> The Builder that is building Object O and is configured by this {@link AbstractRequestMatcherMappingConfigurer}
|
||||
* @param <C> The object that is returned or Chained after creating the RequestMatcher
|
||||
* @param <O> The Object being built by Builder B
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public abstract class AbstractRequestMatcherConfigurer<B extends SecurityBuilder<O>,C,O> extends SecurityConfigurerAdapter<O,B> {
|
||||
private static final RequestMatcher ANY_REQUEST = new AnyRequestMatcher();
|
||||
public abstract class AbstractRequestMatcherRegistry<C> {
|
||||
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
|
||||
/**
|
||||
* Maps any request.
|
||||
*
|
||||
* @param method the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}.
|
||||
* @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.AntPathRequestMatcher}
|
||||
* @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher}
|
||||
* from
|
||||
*
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}
|
||||
@@ -56,10 +52,10 @@ public abstract class AbstractRequestMatcherConfigurer<B extends SecurityBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a {@link List} of {@link org.springframework.security.web.util.AntPathRequestMatcher} instances.
|
||||
* Maps a {@link List} of {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} instances.
|
||||
*
|
||||
* @param method the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}.
|
||||
* @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.AntPathRequestMatcher}
|
||||
* @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher}
|
||||
* from
|
||||
*
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}
|
||||
@@ -69,10 +65,10 @@ public abstract class AbstractRequestMatcherConfigurer<B extends SecurityBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a {@link List} of {@link org.springframework.security.web.util.AntPathRequestMatcher} instances that do
|
||||
* Maps a {@link List} of {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} instances that do
|
||||
* not care which {@link HttpMethod} is used.
|
||||
*
|
||||
* @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.AntPathRequestMatcher}
|
||||
* @param antPatterns the ant patterns to create {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher}
|
||||
* from
|
||||
*
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}
|
||||
@@ -82,11 +78,11 @@ public abstract class AbstractRequestMatcherConfigurer<B extends SecurityBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a {@link List} of {@link org.springframework.security.web.util.RegexRequestMatcher} instances.
|
||||
* Maps a {@link List} of {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} instances.
|
||||
*
|
||||
* @param method the {@link HttpMethod} to use or {@code null} for any {@link HttpMethod}.
|
||||
* @param regexPatterns the regular expressions to create
|
||||
* {@link org.springframework.security.web.util.RegexRequestMatcher} from
|
||||
* {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from
|
||||
*
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}
|
||||
*/
|
||||
@@ -96,11 +92,11 @@ public abstract class AbstractRequestMatcherConfigurer<B extends SecurityBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link List} of {@link org.springframework.security.web.util.RegexRequestMatcher} instances that do not
|
||||
* Create a {@link List} of {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} instances that do not
|
||||
* specify an {@link HttpMethod}.
|
||||
*
|
||||
* @param regexPatterns the regular expressions to create
|
||||
* {@link org.springframework.security.web.util.RegexRequestMatcher} from
|
||||
* {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from
|
||||
*
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}
|
||||
*/
|
||||
@@ -109,7 +105,7 @@ public abstract class AbstractRequestMatcherConfigurer<B extends SecurityBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a list of {@link RequestMatcher} instances with the {@link AbstractRequestMatcherMappingConfigurer}
|
||||
* Associates a list of {@link RequestMatcher} instances with the {@link AbstractConfigAttributeRequestMatcherRegistry}
|
||||
*
|
||||
* @param requestMatchers the {@link RequestMatcher} instances
|
||||
*
|
||||
+1
-1
@@ -152,7 +152,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends S
|
||||
* <li>{@link UsernamePasswordAuthenticationFilter}</li>
|
||||
* <li>{@link ConcurrentSessionFilter}</li>
|
||||
* <li>{@link OpenIDAuthenticationFilter}</li>
|
||||
* <li>{@link DefaultLoginPageViewFilter}</li>
|
||||
* <li>{@link DefaultLoginPageGeneratingFilter}</li>
|
||||
* <li>{@link ConcurrentSessionFilter}</li>
|
||||
* <li>{@link DigestAuthenticationFilter}</li>
|
||||
* <li>{@link BasicAuthenticationFilter}</li>
|
||||
|
||||
-191
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.builders;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
|
||||
/**
|
||||
* Spring Security debugging filter.
|
||||
* <p>
|
||||
* Logs information (such as session creation) to help the user understand how requests are being handled
|
||||
* by Spring Security and provide them with other relevant information (such as when sessions are being created).
|
||||
*
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Rob Winch
|
||||
* @since 3.1
|
||||
*/
|
||||
class DebugFilter implements Filter {
|
||||
private static final String ALREADY_FILTERED_ATTR_NAME = DebugFilter.class.getName().concat(".FILTERED");
|
||||
|
||||
private final FilterChainProxy fcp;
|
||||
private final Logger logger = new Logger();
|
||||
|
||||
public DebugFilter(FilterChainProxy fcp) {
|
||||
this.fcp = fcp;
|
||||
}
|
||||
|
||||
public final void doFilter(ServletRequest srvltRequest, ServletResponse srvltResponse, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
if (!(srvltRequest instanceof HttpServletRequest) || !(srvltResponse instanceof HttpServletResponse)) {
|
||||
throw new ServletException("DebugFilter just supports HTTP requests");
|
||||
}
|
||||
HttpServletRequest request = (HttpServletRequest) srvltRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) srvltResponse;
|
||||
|
||||
List<Filter> filters = getFilters(request);
|
||||
logger.log("Request received for '" + UrlUtils.buildRequestUrl(request) + "':\n\n" +
|
||||
request + "\n\n" +
|
||||
"servletPath:" + request.getServletPath() + "\n" +
|
||||
"pathInfo:" + request.getPathInfo() + "\n\n" +
|
||||
formatFilters(filters));
|
||||
|
||||
if (request.getAttribute(ALREADY_FILTERED_ATTR_NAME) == null) {
|
||||
invokeWithWrappedRequest(request, response, filterChain);
|
||||
} else {
|
||||
fcp.doFilter(request, response, filterChain);
|
||||
}
|
||||
}
|
||||
|
||||
private void invokeWithWrappedRequest(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
|
||||
request.setAttribute(ALREADY_FILTERED_ATTR_NAME, Boolean.TRUE);
|
||||
request = new DebugRequestWrapper(request);
|
||||
try {
|
||||
fcp.doFilter(request, response, filterChain);
|
||||
}
|
||||
finally {
|
||||
request.removeAttribute(ALREADY_FILTERED_ATTR_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
String formatFilters(List<Filter> filters) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Security filter chain: ");
|
||||
if (filters == null) {
|
||||
sb.append("no match");
|
||||
} else if (filters.isEmpty()) {
|
||||
sb.append("[] empty (bypassed by security='none') ");
|
||||
} else {
|
||||
sb.append("[\n");
|
||||
for (Filter f : filters) {
|
||||
sb.append(" ").append(f.getClass().getSimpleName()).append("\n");
|
||||
}
|
||||
sb.append("]");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private List<Filter> getFilters(HttpServletRequest request) {
|
||||
for (SecurityFilterChain chain : fcp.getFilterChains()) {
|
||||
if (chain.matches(request)) {
|
||||
return chain.getFilters();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
|
||||
class DebugRequestWrapper extends HttpServletRequestWrapper {
|
||||
private static final Logger logger = new Logger();
|
||||
|
||||
public DebugRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession() {
|
||||
boolean sessionExists = super.getSession(false) != null;
|
||||
HttpSession session = super.getSession();
|
||||
|
||||
if (!sessionExists) {
|
||||
logger.log("New HTTP session created: " + session.getId(), true);
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession(boolean create) {
|
||||
if (!create) {
|
||||
return super.getSession(create);
|
||||
}
|
||||
return getSession();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls output for the Spring Security debug feature.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
*/
|
||||
final class Logger {
|
||||
final static Log logger = LogFactory.getLog("Spring Security Debugger");
|
||||
|
||||
void log(String message) {
|
||||
log(message, false);
|
||||
}
|
||||
|
||||
void log(String message, boolean dumpStack) {
|
||||
StringBuilder output = new StringBuilder(256);
|
||||
output.append("\n\n************************************************************\n\n");
|
||||
output.append(message).append("\n");
|
||||
|
||||
if (dumpStack) {
|
||||
StringWriter os = new StringWriter();
|
||||
new Exception().printStackTrace(new PrintWriter(os));
|
||||
StringBuffer buffer = os.getBuffer();
|
||||
// Remove the exception in case it scares people.
|
||||
int start = buffer.indexOf("java.lang.Exception");
|
||||
buffer.replace(start, start + 19, "");
|
||||
output.append("\nCall stack: \n").append(os.toString());
|
||||
}
|
||||
|
||||
output.append("\n\n************************************************************\n\n");
|
||||
|
||||
logger.info(output.toString());
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -32,7 +32,7 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
|
||||
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.switchuser.SwitchUserFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
||||
@@ -86,7 +86,7 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
|
||||
order += STEP;
|
||||
filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order);
|
||||
order += STEP;
|
||||
put(DefaultLoginPageViewFilter.class, order);
|
||||
put(DefaultLoginPageGeneratingFilter.class, order);
|
||||
order += STEP;
|
||||
put(ConcurrentSessionFilter.class, order);
|
||||
order += STEP;
|
||||
|
||||
+115
-54
@@ -31,7 +31,7 @@ import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherConfigurer;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
||||
@@ -63,10 +63,11 @@ import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.PortMapperImpl;
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -97,7 +98,7 @@ import org.springframework.util.Assert;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("user")
|
||||
@@ -114,7 +115,7 @@ import org.springframework.util.Assert;
|
||||
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain,HttpSecurity> implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
|
||||
private final RequestMatcherConfigurer requestMatcherConfigurer = new RequestMatcherConfigurer();
|
||||
private List<Filter> filters = new ArrayList<Filter>();
|
||||
private RequestMatcher requestMatcher = new AnyRequestMatcher();
|
||||
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
|
||||
private FilterComparator comparitor = new FilterComparator();
|
||||
|
||||
/**
|
||||
@@ -156,7 +157,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* // the username must match the OpenID of the user you are
|
||||
@@ -239,6 +240,75 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
return getOrApply(new OpenIDLoginConfigurer<HttpSecurity>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Security headers to the response. This is activated by default
|
||||
* when using {@link WebSecurityConfigurerAdapter}'s default constructor.
|
||||
* Only invoking the {@link #headers()} without invoking additional methods
|
||||
* on it, or accepting the default provided by
|
||||
* {@link WebSecurityConfigurerAdapter}, is the equivalent of:
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .headers()
|
||||
* .contentTypeOptions();
|
||||
* .xssProtection()
|
||||
* .cacheControl()
|
||||
* .httpStrictTransportSecurity()
|
||||
* .frameOptions()
|
||||
* .and()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* You can disable the headers using the following:
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .headers().disable()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* You can enable only a few of the headers by invoking the appropriate
|
||||
* methods on {@link #headers()} result. For example, the following will
|
||||
* enable {@link HeadersConfigurer#cacheControl()} and
|
||||
* {@link HeadersConfigurer#frameOptions()} only.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .headers()
|
||||
* .cacheControl()
|
||||
* .frameOptions()
|
||||
* .and()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
* @see {@link HeadersConfigurer}
|
||||
*/
|
||||
public HeadersConfigurer<HttpSecurity> headers() throws Exception {
|
||||
return getOrApply(new HeadersConfigurer<HttpSecurity>());
|
||||
}
|
||||
@@ -275,7 +345,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth.
|
||||
* inMemoryAuthentication()
|
||||
@@ -347,7 +417,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("user")
|
||||
@@ -489,7 +559,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -545,7 +615,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -580,7 +650,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -610,8 +680,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<HttpSecurity> authorizeRequests() throws Exception {
|
||||
return getOrApply(new ExpressionUrlAuthorizationConfigurer<HttpSecurity>());
|
||||
public ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests() throws Exception {
|
||||
return getOrApply(new ExpressionUrlAuthorizationConfigurer<HttpSecurity>()).getRegistry();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,7 +734,23 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
|
||||
|
||||
/**
|
||||
* Adds CSRF support
|
||||
* Adds CSRF support. This is activated by default when using
|
||||
* {@link WebSecurityConfigurerAdapter}'s default constructor. You can
|
||||
* disable it using:
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .csrf().disable()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return the {@link ServletApiConfigurer} for further customizations
|
||||
* @throws Exception
|
||||
@@ -711,7 +797,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -759,7 +845,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -792,7 +878,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -837,7 +923,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -870,7 +956,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -919,7 +1005,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -934,8 +1020,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* @return the {@link ChannelSecurityConfigurer} for further customizations
|
||||
* @throws Exception
|
||||
*/
|
||||
public ChannelSecurityConfigurer<HttpSecurity> requiresChannel() throws Exception {
|
||||
return getOrApply(new ChannelSecurityConfigurer<HttpSecurity>());
|
||||
public ChannelSecurityConfigurer<HttpSecurity>.ChannelRequestMatcherRegistry requiresChannel() throws Exception {
|
||||
return getOrApply(new ChannelSecurityConfigurer<HttpSecurity>()).getRegistry();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -962,7 +1048,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -1077,7 +1163,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -1108,7 +1194,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -1141,7 +1227,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
* protected void configure(AuthenticationManagerBuilder auth)
|
||||
* throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -1226,7 +1312,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class RequestMatcherConfigurer extends AbstractRequestMatcherConfigurer<HttpSecurity,RequestMatcherConfigurer,DefaultSecurityFilterChain> {
|
||||
public final class RequestMatcherConfigurer extends AbstractRequestMatcherRegistry<RequestMatcherConfigurer> {
|
||||
|
||||
protected RequestMatcherConfigurer chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
||||
requestMatcher(new OrRequestMatcher(requestMatchers));
|
||||
@@ -1261,29 +1347,4 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
}
|
||||
return apply(configurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal {@link RequestMatcher} instance used by {@link RequestMatcher}
|
||||
* that will match if any of the passed in {@link RequestMatcher} instances
|
||||
* match.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
private static final class OrRequestMatcher implements RequestMatcher {
|
||||
private final List<RequestMatcher> requestMatchers;
|
||||
|
||||
private OrRequestMatcher(List<RequestMatcher> requestMatchers) {
|
||||
this.requestMatchers = requestMatchers;
|
||||
}
|
||||
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
for(RequestMatcher matcher : requestMatchers) {
|
||||
if(matcher.matches(request)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
-8
@@ -23,10 +23,14 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherConfigurer;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
||||
@@ -40,9 +44,10 @@ import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEval
|
||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.debug.DebugFilter;
|
||||
import org.springframework.security.web.firewall.DefaultHttpFirewall;
|
||||
import org.springframework.security.web.firewall.HttpFirewall;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
||||
@@ -67,7 +72,7 @@ import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class WebSecurity extends
|
||||
AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter> {
|
||||
AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter>, ApplicationContextAware {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final List<RequestMatcher> ignoredRequests = new ArrayList<RequestMatcher>();
|
||||
@@ -86,7 +91,10 @@ public final class WebSecurity extends
|
||||
|
||||
private WebInvocationPrivilegeEvaluator privilegeEvaluator;
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
|
||||
private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler = defaultWebSecurityExpressionHandler;
|
||||
|
||||
|
||||
private Runnable postBuildAction = new Runnable() {
|
||||
public void run() {}
|
||||
@@ -94,9 +102,11 @@ public final class WebSecurity extends
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} to use
|
||||
* @see WebSecurityConfiguration
|
||||
*/
|
||||
public WebSecurity() {
|
||||
public WebSecurity(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
super(objectPostProcessor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,7 +280,10 @@ public final class WebSecurity extends
|
||||
|
||||
@Override
|
||||
protected Filter performBuild() throws Exception {
|
||||
Assert.state(!securityFilterChainBuilders.isEmpty(), "At least one SecurityFilterBuilder needs to be specified. Invoke FilterChainProxyBuilder.securityFilterChains");
|
||||
Assert.state(!securityFilterChainBuilders.isEmpty(),
|
||||
"At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke "
|
||||
+ WebSecurity.class.getSimpleName()
|
||||
+ ".addSecurityFilterChainBuilder directly");
|
||||
int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
|
||||
List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(chainSize);
|
||||
for(RequestMatcher ignoredRequest : ignoredRequests) {
|
||||
@@ -306,7 +319,7 @@ public final class WebSecurity extends
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class IgnoredRequestConfigurer extends AbstractRequestMatcherConfigurer<WebSecurity,IgnoredRequestConfigurer,Filter> {
|
||||
public final class IgnoredRequestConfigurer extends AbstractRequestMatcherRegistry<IgnoredRequestConfigurer> {
|
||||
|
||||
@Override
|
||||
protected IgnoredRequestConfigurer chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
||||
@@ -317,11 +330,15 @@ public final class WebSecurity extends
|
||||
/**
|
||||
* Returns the {@link WebSecurity} to be returned for chaining.
|
||||
*/
|
||||
@Override
|
||||
public WebSecurity and() {
|
||||
return WebSecurity.this;
|
||||
}
|
||||
|
||||
private IgnoredRequestConfigurer(){}
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -56,7 +56,7 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth) {
|
||||
* protected void configure(AuthenticationManagerBuilder auth) {
|
||||
* auth
|
||||
* // enable in memory based authentication with a user named "user" and "admin"
|
||||
* .inMemoryAuthentication()
|
||||
@@ -77,7 +77,7 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value={java.lang.annotation.ElementType.TYPE})
|
||||
@Documented
|
||||
@Import({WebSecurityConfiguration.class,ObjectPostProcessorConfiguration.class,AuthenticationConfiguration.class, SpringWebMvcImportSelector.class})
|
||||
@Import({WebSecurityConfiguration.class,ObjectPostProcessorConfiguration.class,AuthenticationConfiguration.class})
|
||||
public @interface EnableWebSecurity {
|
||||
|
||||
/**
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Used by {@link EnableWebSecurity} to conditionaly import
|
||||
* {@link CsrfWebMvcConfiguration} when the DispatcherServlet is present on the
|
||||
* classpath.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
class SpringWebMvcImportSelector implements ImportSelector {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.annotation.ImportSelector#selectImports(org.springframework.core.type.AnnotationMetadata)
|
||||
*/
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader());
|
||||
return webmvcPresent ? new String[] {"org.springframework.security.config.annotation.web.configuration.CsrfWebMvcConfiguration"} : new String[] {};
|
||||
}
|
||||
}
|
||||
+21
-5
@@ -34,6 +34,8 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.config.annotation.AlreadyBuiltException;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
@@ -61,7 +63,9 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
|
||||
private final WebSecurity webSecurity = new WebSecurity();
|
||||
private WebSecurity webSecurity;
|
||||
|
||||
private Boolean debugEnabled;
|
||||
|
||||
private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
|
||||
|
||||
@@ -84,7 +88,11 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
if(!hasConfigurers) {
|
||||
throw new IllegalStateException("At least one non-null instance of "+ WebSecurityConfigurer.class.getSimpleName()+" must be exposed as a @Bean when using @EnableWebSecurity. Hint try extending "+ WebSecurityConfigurerAdapter.class.getSimpleName());
|
||||
}
|
||||
return webSecurity.build();
|
||||
try {
|
||||
return webSecurity.build();
|
||||
} catch (AlreadyBuiltException e) {
|
||||
return webSecurity.getObject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,12 +109,18 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
/**
|
||||
* Sets the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>} instances used to create the web configuration.
|
||||
*
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} used to create a {@link WebSecurity} instance
|
||||
* @param webSecurityConfigurers the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>} instances used to create the web configuration
|
||||
* @throws Exception
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setFilterChainProxySecurityConfigurer(
|
||||
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
|
||||
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
|
||||
webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
|
||||
if(debugEnabled != null) {
|
||||
webSecurity.debug(debugEnabled);
|
||||
}
|
||||
|
||||
Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);
|
||||
|
||||
Integer previousOrder = null;
|
||||
@@ -174,8 +188,10 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap);
|
||||
}
|
||||
}
|
||||
boolean debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
|
||||
this.webSecurity.debug(debugEnabled);
|
||||
debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
|
||||
if(webSecurity != null) {
|
||||
webSecurity.debug(debugEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
+88
-41
@@ -16,17 +16,20 @@
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -51,7 +54,8 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer<Filter,WebSecurity> {
|
||||
@Order(100)
|
||||
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {
|
||||
private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class);
|
||||
|
||||
private ApplicationContext context;
|
||||
@@ -64,18 +68,12 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
}
|
||||
};
|
||||
|
||||
private final AuthenticationManagerBuilder authenticationBuilder = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR);
|
||||
private final AuthenticationManagerBuilder parentAuthenticationBuilder = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR) {
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
return super.eraseCredentials(eraseCredentials);
|
||||
}
|
||||
|
||||
};
|
||||
private AuthenticationManagerBuilder authenticationBuilder;
|
||||
private AuthenticationManagerBuilder parentAuthenticationBuilder;
|
||||
private boolean disableAuthenticationRegistration;
|
||||
private boolean authenticationManagerInitialized;
|
||||
private AuthenticationManager authenticationManager;
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
private HttpSecurity http;
|
||||
private boolean disableDefaults;
|
||||
|
||||
@@ -101,32 +99,53 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the default implementation of {@link #authenticationManager()} to attempt to obtain an
|
||||
* {@link AuthenticationManager}. If overridden, the {@link AuthenticationManagerBuilder} should be used to specify
|
||||
* the {@link AuthenticationManager}. The resulting {@link AuthenticationManager}
|
||||
* will be exposed as a Bean as will the last populated {@link UserDetailsService} that is created with the
|
||||
* {@link AuthenticationManagerBuilder}. The {@link UserDetailsService} will also automatically be populated on
|
||||
* {@link HttpSecurity#getSharedObject(Class)} for use with other {@link SecurityContextConfigurer}
|
||||
* (i.e. RememberMeConfigurer )
|
||||
* Used by the default implementation of {@link #authenticationManager()} to
|
||||
* attempt to obtain an {@link AuthenticationManager}. If overridden, the
|
||||
* {@link AuthenticationManagerBuilder} should be used to specify the
|
||||
* {@link AuthenticationManager}.
|
||||
*
|
||||
* <p>For example, the following configuration could be used to register
|
||||
* in memory authentication that exposes an in memory {@link UserDetailsService}:</p>
|
||||
* <p>
|
||||
* The {@link #authenticationManagerBean()} method can be used to expose the
|
||||
* resulting {@link AuthenticationManager} as a Bean. The
|
||||
* {@link #userDetailsServiceBean()} can be used to expose the last
|
||||
* populated {@link UserDetailsService} that is created with the
|
||||
* {@link AuthenticationManagerBuilder} as a Bean. The
|
||||
* {@link UserDetailsService} will also automatically be populated on
|
||||
* {@link HttpSecurity#getSharedObject(Class)} for use with other
|
||||
* {@link SecurityContextConfigurer} (i.e. RememberMeConfigurer )
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* For example, the following configuration could be used to register in
|
||||
* memory authentication that exposes an in memory
|
||||
* {@link UserDetailsService}:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* @Override
|
||||
* protected void registerAuthentication(AuthenticationManagerBuilder auth) {
|
||||
* protected void configure(AuthenticationManagerBuilder auth) {
|
||||
* auth
|
||||
* // enable in memory based authentication with a user named "user" and "admin"
|
||||
* // enable in memory based authentication with a user named
|
||||
* // "user" and "admin"
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("user").password("password").roles("USER").and()
|
||||
* .withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* .withUser("user").password("password").roles("USER").and()
|
||||
* .withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* }
|
||||
*
|
||||
* // Expose the UserDetailsService as a Bean
|
||||
* @Bean
|
||||
* @Override
|
||||
* public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
* return super.userDetailsServiceBean();
|
||||
* }
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param auth the {@link AuthenticationManagerBuilder} to use
|
||||
* @param auth
|
||||
* the {@link AuthenticationManagerBuilder} to use
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
this.disableAuthenticationRegistration = true;
|
||||
}
|
||||
|
||||
@@ -141,9 +160,6 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
return http;
|
||||
}
|
||||
|
||||
authenticationBuilder.objectPostProcessor(objectPostProcessor);
|
||||
parentAuthenticationBuilder.objectPostProcessor(objectPostProcessor);
|
||||
|
||||
DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
|
||||
parentAuthenticationBuilder.authenticationEventPublisher(eventPublisher);
|
||||
|
||||
@@ -151,7 +167,9 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
authenticationBuilder.parentAuthenticationManager(authenticationManager);
|
||||
http = new HttpSecurity(objectPostProcessor,authenticationBuilder, parentAuthenticationBuilder.getSharedObjects());
|
||||
http.setSharedObject(UserDetailsService.class, userDetailsService());
|
||||
http.setSharedObject(ApplicationContext.class, context);
|
||||
http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy);
|
||||
http.setSharedObject(AuthenticationTrustResolver.class, trustResolver);
|
||||
if(!disableDefaults) {
|
||||
http
|
||||
.csrf().and()
|
||||
@@ -172,7 +190,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
|
||||
/**
|
||||
* Override this method to expose the {@link AuthenticationManager} from
|
||||
* {@link #registerAuthentication(AuthenticationManagerBuilder)} to be exposed as
|
||||
* {@link #configure(AuthenticationManagerBuilder)} to be exposed as
|
||||
* a Bean. For example:
|
||||
*
|
||||
* <pre>
|
||||
@@ -192,7 +210,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
|
||||
/**
|
||||
* Gets the {@link AuthenticationManager} to use. The default strategy is if
|
||||
* {@link #registerAuthentication(AuthenticationManagerBuilder)} method is
|
||||
* {@link #configure(AuthenticationManagerBuilder)} method is
|
||||
* overridden to use the {@link AuthenticationManagerBuilder} that was passed in.
|
||||
* Otherwise, autowire the {@link AuthenticationManager} by type.
|
||||
*
|
||||
@@ -201,7 +219,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
*/
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
if(!authenticationManagerInitialized) {
|
||||
registerAuthentication(parentAuthenticationBuilder);
|
||||
configure(parentAuthenticationBuilder);
|
||||
if(disableAuthenticationRegistration) {
|
||||
try {
|
||||
authenticationManager = context.getBean(AuthenticationManagerBuilder.class).getOrBuild();
|
||||
@@ -225,7 +243,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
|
||||
/**
|
||||
* Override this method to expose a {@link UserDetailsService} created from
|
||||
* {@link #registerAuthentication(AuthenticationManagerBuilder)} as a bean. In
|
||||
* {@link #configure(AuthenticationManagerBuilder)} as a bean. In
|
||||
* general only the following override should be done of this method:
|
||||
*
|
||||
* <pre>
|
||||
@@ -243,7 +261,8 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
* @see {@link #userDetailsService()}
|
||||
*/
|
||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
return new UserDetailsServiceDelegator(parentAuthenticationBuilder);
|
||||
AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class);
|
||||
return new UserDetailsServiceDelegator(Arrays.asList(parentAuthenticationBuilder, globalAuthBuilder));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,7 +274,8 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
* @return
|
||||
*/
|
||||
protected UserDetailsService userDetailsService() {
|
||||
return parentAuthenticationBuilder.getDefaultUserDetailsService();
|
||||
AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class);
|
||||
return new UserDetailsServiceDelegator(Arrays.asList(parentAuthenticationBuilder, globalAuthBuilder));
|
||||
}
|
||||
|
||||
public void init(final WebSecurity web) throws Exception {
|
||||
@@ -311,6 +331,11 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Autowired(required=false)
|
||||
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
|
||||
this.trustResolver = trustResolver;
|
||||
}
|
||||
|
||||
@Autowired(required=false)
|
||||
public void setContentNegotationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) {
|
||||
this.contentNegotiationStrategy = contentNegotiationStrategy;
|
||||
@@ -319,6 +344,16 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
@Autowired(required=false)
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
|
||||
authenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
parentAuthenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor) {
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
return super.eraseCredentials(eraseCredentials);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -331,12 +366,15 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
* @since 3.2
|
||||
*/
|
||||
static final class UserDetailsServiceDelegator implements UserDetailsService {
|
||||
private AuthenticationManagerBuilder delegateBuilder;
|
||||
private List<AuthenticationManagerBuilder> delegateBuilders;
|
||||
private UserDetailsService delegate;
|
||||
private final Object delegateMonitor = new Object();
|
||||
|
||||
UserDetailsServiceDelegator(AuthenticationManagerBuilder authentication) {
|
||||
this.delegateBuilder = authentication;
|
||||
UserDetailsServiceDelegator(List<AuthenticationManagerBuilder> delegateBuilders) {
|
||||
if(delegateBuilders.contains(null)) {
|
||||
throw new IllegalArgumentException("delegateBuilders cannot contain null values. Got " + delegateBuilders);
|
||||
}
|
||||
this.delegateBuilders = delegateBuilders;
|
||||
}
|
||||
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
@@ -346,8 +384,17 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
|
||||
|
||||
synchronized(delegateMonitor) {
|
||||
if (delegate == null) {
|
||||
delegate = this.delegateBuilder.getDefaultUserDetailsService();
|
||||
this.delegateBuilder = null;
|
||||
for(AuthenticationManagerBuilder delegateBuilder : delegateBuilders) {
|
||||
delegate = delegateBuilder.getDefaultUserDetailsService();
|
||||
if(delegate != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(delegate == null) {
|
||||
throw new IllegalStateException("UserDetailsService is required.");
|
||||
}
|
||||
this.delegateBuilders = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-3
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -34,8 +36,8 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.util.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
@@ -235,7 +237,8 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecu
|
||||
if(contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
RequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_XHTML_XML, new MediaType("image","*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN);
|
||||
MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_XHTML_XML, new MediaType("image","*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN);
|
||||
preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher);
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -21,9 +21,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherConfigurer;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for specifying which
|
||||
@@ -32,15 +31,13 @@ import org.springframework.security.web.util.RequestMatcher;
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*
|
||||
* @param <B> The Builder that is building Object O and is configured by this {@link AbstractRequestMatcherMappingConfigurer}
|
||||
* @param <C> The object that is returned or Chained after creating the RequestMatcher
|
||||
* @param <O> The Object being built by Builder B
|
||||
*
|
||||
* @see ChannelSecurityConfigurer
|
||||
* @see UrlAuthorizationConfigurer
|
||||
* @see ExpressionUrlAuthorizationConfigurer
|
||||
*/
|
||||
public abstract class AbstractRequestMatcherMappingConfigurer<B extends SecurityBuilder<O>,C,O> extends AbstractRequestMatcherConfigurer<B,C,O> {
|
||||
public abstract class AbstractConfigAttributeRequestMatcherRegistry<C> extends AbstractRequestMatcherRegistry<C> {
|
||||
private List<UrlMapping> urlMappings = new ArrayList<UrlMapping>();
|
||||
private List<RequestMatcher> unmappedMatchers;
|
||||
|
||||
+62
-54
@@ -23,7 +23,6 @@ import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
|
||||
@@ -53,56 +52,28 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
|
||||
* <li>{@link org.springframework.security.config.annotation.web.builders.HttpSecurity#getAuthenticationManager()}</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* @param <C> the AbstractInterceptUrlConfigurer
|
||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured
|
||||
* @param <C> the type of object that is changed
|
||||
* @param <R> the type of object that is changed for the {@link AbstractRequestMatcherMappingConfigurer}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @see ExpressionUrlAuthorizationConfigurer
|
||||
* @see UrlAuthorizationConfigurer
|
||||
*/
|
||||
abstract class AbstractInterceptUrlConfigurer<H extends HttpSecurityBuilder<H>,C,R> extends
|
||||
AbstractRequestMatcherMappingConfigurer<H,R,DefaultSecurityFilterChain> implements
|
||||
SecurityConfigurer<DefaultSecurityFilterChain,H> {
|
||||
abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C,H>, H extends HttpSecurityBuilder<H>> extends
|
||||
AbstractHttpConfigurer<C, H>{
|
||||
private Boolean filterSecurityInterceptorOncePerRequest;
|
||||
|
||||
private AccessDecisionManager accessDecisionManager;
|
||||
|
||||
/**
|
||||
* Allows setting the {@link AccessDecisionManager}. If none is provided, a default {@l AccessDecisionManager} is
|
||||
* created.
|
||||
*
|
||||
* @param accessDecisionManager the {@link AccessDecisionManager} to use
|
||||
* @return the {@link AbstractInterceptUrlConfigurer} for further customization
|
||||
*/
|
||||
public C accessDecisionManager(
|
||||
AccessDecisionManager accessDecisionManager) {
|
||||
this.accessDecisionManager = accessDecisionManager;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting if the {@link FilterSecurityInterceptor} should be only applied once per request (i.e. if the
|
||||
* filter intercepts on a forward, should it be applied again).
|
||||
*
|
||||
* @param filterSecurityInterceptorOncePerRequest if the {@link FilterSecurityInterceptor} should be only applied
|
||||
* once per request
|
||||
* @return the {@link AbstractInterceptUrlConfigurer} for further customization
|
||||
*/
|
||||
public C filterSecurityInterceptorOncePerRequest(
|
||||
boolean filterSecurityInterceptorOncePerRequest) {
|
||||
this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource();
|
||||
FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
|
||||
if(metadataSource == null) {
|
||||
return;
|
||||
}
|
||||
FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(metadataSource, http.getSharedObject(AuthenticationManager.class));
|
||||
FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(http, metadataSource, http.getSharedObject(AuthenticationManager.class));
|
||||
if(filterSecurityInterceptorOncePerRequest != null) {
|
||||
securityInterceptor.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest);
|
||||
}
|
||||
@@ -115,38 +86,85 @@ abstract class AbstractInterceptUrlConfigurer<H extends HttpSecurityBuilder<H>,C
|
||||
* Subclasses should implement this method to provide a {@link FilterInvocationSecurityMetadataSource} for the
|
||||
* {@link FilterSecurityInterceptor}.
|
||||
*
|
||||
* @param http the builder to use
|
||||
*
|
||||
* @return the {@link FilterInvocationSecurityMetadataSource} to set on the {@link FilterSecurityInterceptor}.
|
||||
* Cannot be null.
|
||||
*/
|
||||
abstract FilterInvocationSecurityMetadataSource createMetadataSource();
|
||||
abstract FilterInvocationSecurityMetadataSource createMetadataSource(H http);
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method to provide the {@link AccessDecisionVoter} instances used to create the
|
||||
* default {@link AccessDecisionManager}
|
||||
*
|
||||
* @param http the builder to use
|
||||
*
|
||||
* @return the {@link AccessDecisionVoter} instances used to create the
|
||||
* default {@link AccessDecisionManager}
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
abstract List<AccessDecisionVoter> getDecisionVoters();
|
||||
abstract List<AccessDecisionVoter> getDecisionVoters(H http);
|
||||
|
||||
abstract class AbstractInterceptUrlRegistry<R extends AbstractInterceptUrlRegistry<R,T>,T> extends AbstractConfigAttributeRequestMatcherRegistry<T> {
|
||||
|
||||
/**
|
||||
* Allows setting the {@link AccessDecisionManager}. If none is provided, a default {@l AccessDecisionManager} is
|
||||
* created.
|
||||
*
|
||||
* @param accessDecisionManager the {@link AccessDecisionManager} to use
|
||||
* @return the {@link AbstractInterceptUrlConfigurer} for further customization
|
||||
*/
|
||||
public R accessDecisionManager(
|
||||
AccessDecisionManager accessDecisionManager) {
|
||||
AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting if the {@link FilterSecurityInterceptor} should be only applied once per request (i.e. if the
|
||||
* filter intercepts on a forward, should it be applied again).
|
||||
*
|
||||
* @param filterSecurityInterceptorOncePerRequest if the {@link FilterSecurityInterceptor} should be only applied
|
||||
* once per request
|
||||
* @return the {@link AbstractInterceptUrlConfigurer} for further customization
|
||||
*/
|
||||
public R filterSecurityInterceptorOncePerRequest(
|
||||
boolean filterSecurityInterceptorOncePerRequest) {
|
||||
AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the current object with a single suppression of
|
||||
* the type
|
||||
*
|
||||
* @return a reference to the current object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private R getSelf() {
|
||||
return (R) this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the default {@code AccessDecisionManager}
|
||||
* @return the default {@code AccessDecisionManager}
|
||||
*/
|
||||
private AccessDecisionManager createDefaultAccessDecisionManager() {
|
||||
return new AffirmativeBased(getDecisionVoters());
|
||||
private AccessDecisionManager createDefaultAccessDecisionManager(H http) {
|
||||
return new AffirmativeBased(getDecisionVoters(http));
|
||||
}
|
||||
|
||||
/**
|
||||
* If currently null, creates a default {@link AccessDecisionManager} using
|
||||
* {@link #createDefaultAccessDecisionManager()}. Otherwise returns the {@link AccessDecisionManager}.
|
||||
*
|
||||
* @param http the builder to use
|
||||
*
|
||||
* @return the {@link AccessDecisionManager} to use
|
||||
*/
|
||||
private AccessDecisionManager getAccessDecisionManager() {
|
||||
private AccessDecisionManager getAccessDecisionManager(H http) {
|
||||
if (accessDecisionManager == null) {
|
||||
accessDecisionManager = createDefaultAccessDecisionManager();
|
||||
accessDecisionManager = createDefaultAccessDecisionManager(http);
|
||||
}
|
||||
return accessDecisionManager;
|
||||
}
|
||||
@@ -154,29 +172,19 @@ abstract class AbstractInterceptUrlConfigurer<H extends HttpSecurityBuilder<H>,C
|
||||
/**
|
||||
* Creates the {@link FilterSecurityInterceptor}
|
||||
*
|
||||
* @param http the builder to use
|
||||
* @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use
|
||||
* @param authenticationManager the {@link AuthenticationManager} to use
|
||||
* @return the {@link FilterSecurityInterceptor}
|
||||
* @throws Exception
|
||||
*/
|
||||
private FilterSecurityInterceptor createFilterSecurityInterceptor(FilterInvocationSecurityMetadataSource metadataSource,
|
||||
private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, FilterInvocationSecurityMetadataSource metadataSource,
|
||||
AuthenticationManager authenticationManager) throws Exception {
|
||||
FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
|
||||
securityInterceptor.setSecurityMetadataSource(metadataSource);
|
||||
securityInterceptor.setAccessDecisionManager(getAccessDecisionManager());
|
||||
securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http));
|
||||
securityInterceptor.setAuthenticationManager(authenticationManager);
|
||||
securityInterceptor.afterPropertiesSet();
|
||||
return securityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the current object with a single suppression of
|
||||
* the type
|
||||
*
|
||||
* @return a reference to the current object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private C getSelf() {
|
||||
return (C) this;
|
||||
}
|
||||
}
|
||||
+54
-32
@@ -23,9 +23,10 @@ import java.util.List;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
|
||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||
@@ -35,7 +36,7 @@ import org.springframework.security.web.access.channel.RetryWithHttpEntryPoint;
|
||||
import org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint;
|
||||
import org.springframework.security.web.access.channel.SecureChannelProcessor;
|
||||
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds channel security (i.e. requires HTTPS or HTTP) to an application. In order for
|
||||
@@ -72,11 +73,13 @@ import org.springframework.security.web.util.RequestMatcher;
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
AbstractRequestMatcherMappingConfigurer<H,ChannelSecurityConfigurer<H>.RequiresChannelUrl,DefaultSecurityFilterChain> {
|
||||
AbstractHttpConfigurer<ChannelSecurityConfigurer<H>, H> {
|
||||
private ChannelProcessingFilter channelFilter = new ChannelProcessingFilter();
|
||||
private LinkedHashMap<RequestMatcher,Collection<ConfigAttribute>> requestMap = new LinkedHashMap<RequestMatcher,Collection<ConfigAttribute>>();
|
||||
private List<ChannelProcessor> channelProcessors;
|
||||
|
||||
private final ChannelRequestMatcherRegistry REGISTRY = new ChannelRequestMatcherRegistry();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @see HttpSecurity#requiresChannel()
|
||||
@@ -84,6 +87,10 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>> e
|
||||
public ChannelSecurityConfigurer() {
|
||||
}
|
||||
|
||||
public ChannelRequestMatcherRegistry getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
ChannelDecisionManagerImpl channelDecisionManager = new ChannelDecisionManagerImpl();
|
||||
@@ -100,27 +107,6 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>> e
|
||||
http.addFilter(channelFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
*
|
||||
* @param objectPostProcessor
|
||||
* @return the {@link ChannelSecurityConfigurer} for further customizations
|
||||
*/
|
||||
public ChannelSecurityConfigurer<H> withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
addObjectPostProcessor(objectPostProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ChannelProcessor} instances to use in {@link ChannelDecisionManagerImpl}
|
||||
* @param channelProcessors
|
||||
* @return
|
||||
*/
|
||||
public ChannelSecurityConfigurer<H> channelProcessors(List<ChannelProcessor> channelProcessors) {
|
||||
this.channelProcessors = channelProcessors;
|
||||
return this;
|
||||
}
|
||||
|
||||
private List<ChannelProcessor> getChannelProcessors(H http) {
|
||||
if(channelProcessors != null) {
|
||||
return channelProcessors;
|
||||
@@ -145,17 +131,53 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>> e
|
||||
}
|
||||
|
||||
|
||||
private ChannelSecurityConfigurer<H> addAttribute(String attribute, List<RequestMatcher> matchers) {
|
||||
private ChannelRequestMatcherRegistry addAttribute(String attribute, List<RequestMatcher> matchers) {
|
||||
for(RequestMatcher matcher : matchers) {
|
||||
Collection<ConfigAttribute> attrs = Arrays.<ConfigAttribute>asList(new SecurityConfig(attribute));
|
||||
requestMap.put(matcher, attrs);
|
||||
}
|
||||
return this;
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RequiresChannelUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
||||
return new RequiresChannelUrl(requestMatchers);
|
||||
public final class ChannelRequestMatcherRegistry extends AbstractConfigAttributeRequestMatcherRegistry<RequiresChannelUrl> {
|
||||
|
||||
@Override
|
||||
protected RequiresChannelUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
||||
return new RequiresChannelUrl(requestMatchers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
*
|
||||
* @param objectPostProcessor
|
||||
* @return the {@link ChannelSecurityConfigurer} for further customizations
|
||||
*/
|
||||
public ChannelRequestMatcherRegistry withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
addObjectPostProcessor(objectPostProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ChannelProcessor} instances to use in {@link ChannelDecisionManagerImpl}
|
||||
* @param channelProcessors
|
||||
* @return
|
||||
*/
|
||||
public ChannelRequestMatcherRegistry channelProcessors(List<ChannelProcessor> channelProcessors) {
|
||||
ChannelSecurityConfigurer.this.channelProcessors = channelProcessors;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link SecurityBuilder} when done using the
|
||||
* {@link SecurityConfigurer}. This is useful for method chaining.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public H and() {
|
||||
return ChannelSecurityConfigurer.this.and();
|
||||
}
|
||||
|
||||
private ChannelRequestMatcherRegistry() {}
|
||||
}
|
||||
|
||||
public final class RequiresChannelUrl {
|
||||
@@ -165,15 +187,15 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>> e
|
||||
this.requestMatchers = requestMatchers;
|
||||
}
|
||||
|
||||
public ChannelSecurityConfigurer<H> requiresSecure() {
|
||||
public ChannelRequestMatcherRegistry requiresSecure() {
|
||||
return requires("REQUIRES_SECURE_CHANNEL");
|
||||
}
|
||||
|
||||
public ChannelSecurityConfigurer<H> requiresInsecure() {
|
||||
public ChannelRequestMatcherRegistry requiresInsecure() {
|
||||
return requires("REQUIRES_INSECURE_CHANNEL");
|
||||
}
|
||||
|
||||
public ChannelSecurityConfigurer<H> requires(String attribute) {
|
||||
public ChannelRequestMatcherRegistry requires(String attribute) {
|
||||
return addAttribute(attribute, requestMatchers);
|
||||
}
|
||||
}
|
||||
|
||||
+79
-7
@@ -15,15 +15,23 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
|
||||
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfLogoutHandler;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -50,6 +58,7 @@ import org.springframework.util.Assert;
|
||||
* <li>
|
||||
* {@link ExceptionHandlingConfigurer#accessDeniedHandler(AccessDeniedHandler)}
|
||||
* is used to determine how to handle CSRF attempts</li>
|
||||
* <li>{@link InvalidSessionStrategy}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -100,12 +109,9 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>> extends Abst
|
||||
if(requireCsrfProtectionMatcher != null) {
|
||||
filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher);
|
||||
}
|
||||
ExceptionHandlingConfigurer<H> exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
if(exceptionConfig != null) {
|
||||
AccessDeniedHandler accessDeniedHandler = exceptionConfig.getAccessDeniedHandler();
|
||||
if(accessDeniedHandler != null) {
|
||||
filter.setAccessDeniedHandler(accessDeniedHandler);
|
||||
}
|
||||
AccessDeniedHandler accessDeniedHandler = createAccessDeniedHandler(http);
|
||||
if(accessDeniedHandler != null) {
|
||||
filter.setAccessDeniedHandler(accessDeniedHandler);
|
||||
}
|
||||
LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);
|
||||
if(logoutConfigurer != null) {
|
||||
@@ -118,4 +124,70 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>> extends Abst
|
||||
filter = postProcess(filter);
|
||||
http.addFilter(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default {@link AccessDeniedHandler} from the
|
||||
* {@link ExceptionHandlingConfigurer#getAccessDeniedHandler()} or create a
|
||||
* {@link AccessDeniedHandlerImpl} if not available.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder}
|
||||
* @return the {@link AccessDeniedHandler}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private AccessDeniedHandler getDefaultAccessDeniedHandler(H http) {
|
||||
ExceptionHandlingConfigurer<H> exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
AccessDeniedHandler handler = null;
|
||||
if(exceptionConfig != null) {
|
||||
handler = exceptionConfig.getAccessDeniedHandler();
|
||||
}
|
||||
if(handler == null) {
|
||||
handler = new AccessDeniedHandlerImpl();
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default {@link InvalidSessionStrategy} from the
|
||||
* {@link SessionManagementConfigurer#getInvalidSessionStrategy()} or null
|
||||
* if not available.
|
||||
*
|
||||
* @param http
|
||||
* the {@link HttpSecurityBuilder}
|
||||
* @return the {@link InvalidSessionStrategy}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private InvalidSessionStrategy getInvalidSessionStrategy(H http) {
|
||||
SessionManagementConfigurer<H> sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
|
||||
if(sessionManagement == null) {
|
||||
return null;
|
||||
}
|
||||
return sessionManagement.getInvalidSessionStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link AccessDeniedHandler} from the result of
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} and
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)}. If
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)} is non-null, then
|
||||
* a {@link DelegatingAccessDeniedHandler} is used in combination with
|
||||
* {@link InvalidSessionAccessDeniedHandler} and the
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise,
|
||||
* only {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder}
|
||||
* @return the {@link AccessDeniedHandler}
|
||||
*/
|
||||
private AccessDeniedHandler createAccessDeniedHandler(H http) {
|
||||
InvalidSessionStrategy invalidSessionStrategy = getInvalidSessionStrategy(http);
|
||||
AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(http);
|
||||
if(invalidSessionStrategy == null) {
|
||||
return defaultAccessDeniedHandler;
|
||||
}
|
||||
|
||||
InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler(invalidSessionStrategy);
|
||||
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers =
|
||||
new LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler>();
|
||||
handlers.put(MissingCsrfTokenException.class, invalidSessionDeniedHandler);
|
||||
return new DelegatingAccessDeniedHandler(handlers, defaultAccessDeniedHandler);
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -18,7 +18,7 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
|
||||
/**
|
||||
* Adds a Filter that will generate a login page if one is not specified otherwise when using {@link WebSecurityConfigurerAdapter}.
|
||||
@@ -32,7 +32,7 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFi
|
||||
* The following Filters are conditionally populated
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link DefaultLoginPageViewFilter} if the {@link FormLoginConfigurer} did not have a login page specified</li>
|
||||
* <li>{@link DefaultLoginPageGeneratingFilter} if the {@link FormLoginConfigurer} did not have a login page specified</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Created</h2>
|
||||
@@ -56,11 +56,11 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFi
|
||||
public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
AbstractHttpConfigurer<DefaultLoginPageConfigurer<H>,H> {
|
||||
|
||||
private DefaultLoginPageViewFilter loginPageGeneratingFilter = new DefaultLoginPageViewFilter();
|
||||
private DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = new DefaultLoginPageGeneratingFilter();
|
||||
|
||||
@Override
|
||||
public void init(H http) throws Exception {
|
||||
http.setSharedObject(DefaultLoginPageViewFilter.class, loginPageGeneratingFilter);
|
||||
http.setSharedObject(DefaultLoginPageGeneratingFilter.class, loginPageGeneratingFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ import org.springframework.security.web.authentication.DelegatingAuthenticationE
|
||||
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds exception handling for Spring Security related exceptions to an application. All properties have reasonable
|
||||
|
||||
+111
-58
@@ -24,6 +24,7 @@ import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -31,7 +32,7 @@ import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.access.expression.WebExpressionVoter;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -56,7 +57,9 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* <h2>Shared Objects Used</h2>
|
||||
*
|
||||
* No shared objects are used.
|
||||
* <ul>
|
||||
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the {@link DefaultWebSecurityExpressionHandler}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured
|
||||
*
|
||||
@@ -64,7 +67,7 @@ import org.springframework.util.StringUtils;
|
||||
* @since 3.2
|
||||
* @see {@link org.springframework.security.config.annotation.web.builders.HttpSecurity#authorizeRequests()}
|
||||
*/
|
||||
public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractInterceptUrlConfigurer<H,ExpressionUrlAuthorizationConfigurer<H>,ExpressionUrlAuthorizationConfigurer<H>.AuthorizedUrl> {
|
||||
public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractInterceptUrlConfigurer<ExpressionUrlAuthorizationConfigurer<H>,H> {
|
||||
static final String permitAll = "permitAll";
|
||||
private static final String denyAll = "denyAll";
|
||||
private static final String anonymous = "anonymous";
|
||||
@@ -72,7 +75,9 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
private static final String fullyAuthenticated = "fullyAuthenticated";
|
||||
private static final String rememberMe = "rememberMe";
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
|
||||
private final ExpressionInterceptUrlRegistry REGISTRY = new ExpressionInterceptUrlRegistry();
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
@@ -81,52 +86,47 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
public ExpressionUrlAuthorizationConfigurer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows customization of the {@link SecurityExpressionHandler} to be used. The default is {@link DefaultWebSecurityExpressionHandler}
|
||||
*
|
||||
* @param expressionHandler the {@link SecurityExpressionHandler} to be used
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization.
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> expressionHandler(SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
this.expressionHandler = expressionHandler;
|
||||
return this;
|
||||
public ExpressionInterceptUrlRegistry getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
*
|
||||
* @param objectPostProcessor
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
addObjectPostProcessor(objectPostProcessor);
|
||||
return this;
|
||||
}
|
||||
public class ExpressionInterceptUrlRegistry extends ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<ExpressionInterceptUrlRegistry,AuthorizedUrl> {
|
||||
|
||||
@Override
|
||||
protected final AuthorizedUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
||||
return new AuthorizedUrl(requestMatchers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List<AccessDecisionVoter> getDecisionVoters() {
|
||||
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
|
||||
WebExpressionVoter expressionVoter = new WebExpressionVoter();
|
||||
expressionVoter.setExpressionHandler(expressionHandler);
|
||||
decisionVoters.add(expressionVoter);
|
||||
return decisionVoters;
|
||||
}
|
||||
|
||||
@Override
|
||||
final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource() {
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = createRequestMap();
|
||||
if(requestMap.isEmpty()) {
|
||||
throw new IllegalStateException("At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())");
|
||||
@Override
|
||||
protected final AuthorizedUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
||||
return new AuthorizedUrl(requestMatchers);
|
||||
}
|
||||
return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, expressionHandler);
|
||||
|
||||
|
||||
/**
|
||||
* Allows customization of the {@link SecurityExpressionHandler} to be used. The default is {@link DefaultWebSecurityExpressionHandler}
|
||||
*
|
||||
* @param expressionHandler the {@link SecurityExpressionHandler} to be used
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization.
|
||||
*/
|
||||
public ExpressionInterceptUrlRegistry expressionHandler(SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
ExpressionUrlAuthorizationConfigurer.this.expressionHandler = expressionHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
*
|
||||
* @param objectPostProcessor
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations
|
||||
*/
|
||||
public ExpressionInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
addObjectPostProcessor(objectPostProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public H and() {
|
||||
return ExpressionUrlAuthorizationConfigurer.this.and();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allows registering multiple {@link RequestMatcher} instances to a collection of {@link ConfigAttribute} instances
|
||||
*
|
||||
@@ -136,9 +136,46 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
*/
|
||||
private ExpressionUrlAuthorizationConfigurer<H> interceptUrl(Iterable<? extends RequestMatcher> requestMatchers, Collection<ConfigAttribute> configAttributes) {
|
||||
for(RequestMatcher requestMatcher : requestMatchers) {
|
||||
addMapping(new UrlMapping(requestMatcher, configAttributes));
|
||||
REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes));
|
||||
}
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List<AccessDecisionVoter> getDecisionVoters(H http) {
|
||||
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
|
||||
WebExpressionVoter expressionVoter = new WebExpressionVoter();
|
||||
expressionVoter.setExpressionHandler(getExpressionHandler(http));
|
||||
decisionVoters.add(expressionVoter);
|
||||
return decisionVoters;
|
||||
}
|
||||
|
||||
@Override
|
||||
final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) {
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = REGISTRY.createRequestMap();
|
||||
if(requestMap.isEmpty()) {
|
||||
throw new IllegalStateException("At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())");
|
||||
}
|
||||
return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http));
|
||||
}
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> getExpressionHandler(H http) {
|
||||
if(expressionHandler == null) {
|
||||
DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler();
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if(trustResolver != null) {
|
||||
defaultHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
expressionHandler = postProcess(defaultHandler);
|
||||
}
|
||||
|
||||
return expressionHandler;
|
||||
}
|
||||
|
||||
private static String hasAnyRole(String... authorities) {
|
||||
String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','ROLE_");
|
||||
return "hasAnyRole('ROLE_" + anyAuthorities + "')";
|
||||
}
|
||||
|
||||
private static String hasRole(String role) {
|
||||
@@ -195,17 +232,33 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
* this is automatically inserted.
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> hasRole(String role) {
|
||||
public ExpressionInterceptUrlRegistry hasRole(String role) {
|
||||
return access(ExpressionUrlAuthorizationConfigurer.hasRole(role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for specifying URLs require any of a number of roles. If you
|
||||
* do not want to have "ROLE_" automatically inserted see
|
||||
* {@link #hasAnyAuthority(String...)}
|
||||
*
|
||||
* @param roles
|
||||
* the roles to require (i.e. USER, ADMIN, etc). Note, it
|
||||
* should not start with "ROLE_" as this is automatically
|
||||
* inserted.
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
||||
* customization
|
||||
*/
|
||||
public ExpressionInterceptUrlRegistry hasAnyRole(String... roles) {
|
||||
return access(ExpressionUrlAuthorizationConfigurer.hasAnyRole(roles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs require a particular authority.
|
||||
*
|
||||
* @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> hasAuthority(String authority) {
|
||||
public ExpressionInterceptUrlRegistry hasAuthority(String authority) {
|
||||
return access(ExpressionUrlAuthorizationConfigurer.hasAuthority(authority));
|
||||
}
|
||||
|
||||
@@ -216,7 +269,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
* mean either "ROLE_USER" or "ROLE_ADMIN" is required).
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> hasAnyAuthority(String... authorities) {
|
||||
public ExpressionInterceptUrlRegistry hasAnyAuthority(String... authorities) {
|
||||
return access(ExpressionUrlAuthorizationConfigurer.hasAnyAuthority(authorities));
|
||||
}
|
||||
|
||||
@@ -227,7 +280,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
* @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet (i.e. 192.168.0/24)
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> hasIpAddress(String ipaddressExpression) {
|
||||
public ExpressionInterceptUrlRegistry hasIpAddress(String ipaddressExpression) {
|
||||
return access(ExpressionUrlAuthorizationConfigurer.hasIpAddress(ipaddressExpression));
|
||||
}
|
||||
|
||||
@@ -236,7 +289,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
*
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> permitAll() {
|
||||
public ExpressionInterceptUrlRegistry permitAll() {
|
||||
return access(permitAll);
|
||||
}
|
||||
|
||||
@@ -245,7 +298,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
*
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> anonymous() {
|
||||
public ExpressionInterceptUrlRegistry anonymous() {
|
||||
return access(anonymous);
|
||||
}
|
||||
|
||||
@@ -255,7 +308,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
* @see {@link RememberMeConfigurer}
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> rememberMe() {
|
||||
public ExpressionInterceptUrlRegistry rememberMe() {
|
||||
return access(rememberMe);
|
||||
}
|
||||
|
||||
@@ -264,7 +317,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
*
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> denyAll() {
|
||||
public ExpressionInterceptUrlRegistry denyAll() {
|
||||
return access(denyAll);
|
||||
}
|
||||
|
||||
@@ -273,7 +326,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
*
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> authenticated() {
|
||||
public ExpressionInterceptUrlRegistry authenticated() {
|
||||
return access(authenticated);
|
||||
}
|
||||
|
||||
@@ -283,7 +336,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
* @see {@link RememberMeConfigurer}
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> fullyAuthenticated() {
|
||||
public ExpressionInterceptUrlRegistry fullyAuthenticated() {
|
||||
return access(fullyAuthenticated);
|
||||
}
|
||||
|
||||
@@ -293,12 +346,12 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
* @param attribute the expression to secure the URLs (i.e. "hasRole('ROLE_USER') and hasRole('ROLE_SUPER')")
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public ExpressionUrlAuthorizationConfigurer<H> access(String attribute) {
|
||||
public ExpressionInterceptUrlRegistry access(String attribute) {
|
||||
if(not) {
|
||||
attribute = "!" + attribute;
|
||||
}
|
||||
interceptUrl(requestMatchers, SecurityConfig.createList(attribute));
|
||||
return ExpressionUrlAuthorizationConfigurer.this;
|
||||
return ExpressionUrlAuthorizationConfigurer.this.REGISTRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -22,9 +22,9 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds form based authentication. All attributes have reasonable defaults
|
||||
@@ -57,7 +57,7 @@ import org.springframework.security.web.util.RequestMatcher;
|
||||
* <li>{@link AuthenticationManager}</li>
|
||||
* <li>{@link RememberMeServices} - is optionally used. See {@link RememberMeConfigurer}</li>
|
||||
* <li>{@link SessionAuthenticationStrategy} - is optionally used. See {@link SessionManagementConfigurer}</li>
|
||||
* <li>{@link DefaultLoginPageViewFilter} - if present will be populated with information from the configuration</li>
|
||||
* <li>{@link DefaultLoginPageGeneratingFilter} - if present will be populated with information from the configuration</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -245,12 +245,12 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
}
|
||||
|
||||
/**
|
||||
* If available, initializes the {@link DefaultLoginPageViewFilter} shared object.
|
||||
* If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder} to use
|
||||
*/
|
||||
private void initDefaultLoginFilter(H http) {
|
||||
DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if(loginPageGeneratingFilter != null && !isCustomLoginPage()) {
|
||||
loginPageGeneratingFilter.setFormLoginEnabled(true);
|
||||
loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter());
|
||||
|
||||
+110
-12
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.header.HeaderWriter;
|
||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
||||
@@ -30,15 +31,80 @@ import org.springframework.security.web.header.writers.frameoptions.XFrameOption
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adds the Security headers to the response. This is activated by default when
|
||||
* using {@link WebSecurityConfigurerAdapter}'s default constructor. Only
|
||||
* invoking the {@link #headers()} without invoking additional methods on it, or
|
||||
* accepting the default provided by {@link WebSecurityConfigurerAdapter}, is
|
||||
* the equivalent of:
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .headers()
|
||||
* .contentTypeOptions();
|
||||
* .xssProtection()
|
||||
* .cacheControl()
|
||||
* .httpStrictTransportSecurity()
|
||||
* .frameOptions()
|
||||
* .and()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* You can disable the headers using the following:
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .headers().disable()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* You can enable only a few of the headers by invoking the appropriate methods
|
||||
* on {@link #headers()} result. For example, the following will enable
|
||||
* {@link HeadersConfigurer#cacheControl()} and
|
||||
* {@link HeadersConfigurer#frameOptions()} only.
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class CsrfSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .headers()
|
||||
* .cacheControl()
|
||||
* .frameOptions()
|
||||
* .and()
|
||||
* ...;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @see RememberMeConfigurer
|
||||
*/
|
||||
public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<HeadersConfigurer<H>,H> {
|
||||
public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
AbstractHttpConfigurer<HeadersConfigurer<H>, H> {
|
||||
private List<HeaderWriter> headerWriters = new ArrayList<HeaderWriter>();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @see HttpSecurity#headers()
|
||||
*/
|
||||
public HeadersConfigurer() {
|
||||
@@ -46,7 +112,9 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
|
||||
/**
|
||||
* Adds a {@link HeaderWriter} instance
|
||||
* @param headerWriter the {@link HeaderWriter} instance to add
|
||||
*
|
||||
* @param headerWriter
|
||||
* the {@link HeaderWriter} instance to add
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
*/
|
||||
public HeadersConfigurer<H> addHeaderWriter(HeaderWriter headerWriter) {
|
||||
@@ -56,7 +124,13 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link XContentTypeOptionsHeaderWriter}
|
||||
* Adds {@link XContentTypeOptionsHeaderWriter} which inserts the <a href=
|
||||
* "http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx"
|
||||
* >X-Content-Type-Options</a>:
|
||||
*
|
||||
* <pre>
|
||||
* X-Content-Type-Options: nosniff
|
||||
* </pre>
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
*/
|
||||
@@ -65,8 +139,11 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link XXssProtectionHeaderWriter}. Note this is not comprehensive
|
||||
* XSS protection!
|
||||
* <strong>Note this is not comprehensive XSS protection!</strong>
|
||||
*
|
||||
* <para>Adds {@link XXssProtectionHeaderWriter} which adds the <a href=
|
||||
* "http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
|
||||
* >X-XSS-Protection header</a>
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
*/
|
||||
@@ -75,7 +152,13 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link CacheControlHeadersWriter}.
|
||||
* Adds {@link CacheControlHeadersWriter}. Specifically it adds the
|
||||
* following headers:
|
||||
* <ul>
|
||||
* <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
|
||||
* <li>Pragma: no-cache</li>
|
||||
* <li>Expires: 0</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
*/
|
||||
@@ -84,7 +167,15 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link HstsHeaderWriter}.
|
||||
* Adds {@link HstsHeaderWriter} which provides support for <a
|
||||
* href="http://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
|
||||
* (HSTS)</a>.
|
||||
*
|
||||
* <p>
|
||||
* For additional configuration options, use
|
||||
* {@link #addHeaderWriter(HeaderWriter)} and {@link HstsHeaderWriter}
|
||||
* directly.
|
||||
* </p>
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
*/
|
||||
@@ -93,7 +184,10 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link XFrameOptionsHeaderWriter} with all the default settings.
|
||||
* Adds {@link XFrameOptionsHeaderWriter} with all the default settings. For
|
||||
* additional configuration options, use
|
||||
* {@link #addHeaderWriter(HeaderWriter)} and
|
||||
* {@link XFrameOptionsHeaderWriter} directly.
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
*/
|
||||
@@ -109,20 +203,24 @@ public final class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends A
|
||||
|
||||
/**
|
||||
* Creates the {@link HeaderWriter}
|
||||
*
|
||||
* @return the {@link HeaderWriter}
|
||||
*/
|
||||
private HeaderWriterFilter createHeaderWriterFilter() {
|
||||
HeaderWriterFilter headersFilter = new HeaderWriterFilter(getHeaderWriters());
|
||||
HeaderWriterFilter headersFilter = new HeaderWriterFilter(
|
||||
getHeaderWriters());
|
||||
headersFilter = postProcess(headersFilter);
|
||||
return headersFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link HeaderWriter} instances and possibly initializes with the defaults.
|
||||
* Gets the {@link HeaderWriter} instances and possibly initializes with the
|
||||
* defaults.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<HeaderWriter> getHeaderWriters() {
|
||||
if(headerWriters.isEmpty()) {
|
||||
if (headerWriters.isEmpty()) {
|
||||
addDefaultHeaderWriters();
|
||||
}
|
||||
return headerWriters;
|
||||
|
||||
+44
-11
@@ -15,21 +15,29 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.util.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
@@ -66,10 +74,11 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends AbstractHttpConfigurer<HttpBasicConfigurer<B>,B> {
|
||||
private static final String DEFAULT_REALM = "Spring Security Application";
|
||||
private static final String DEFAULT_REALM = "Realm";
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint = new BasicAuthenticationEntryPoint();
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
|
||||
private BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
@@ -78,12 +87,19 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
*/
|
||||
public HttpBasicConfigurer() throws Exception {
|
||||
realmName(DEFAULT_REALM);
|
||||
|
||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<RequestMatcher, AuthenticationEntryPoint>();
|
||||
entryPoints.put(new RequestHeaderRequestMatcher("X-Requested-With","XMLHttpRequest"), new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
||||
|
||||
DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
|
||||
defaultEntryPoint.setDefaultEntryPoint(basicAuthEntryPoint);
|
||||
authenticationEntryPoint = defaultEntryPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for {@link #authenticationEntryPoint(AuthenticationEntryPoint)}
|
||||
* specifying a {@link BasicAuthenticationEntryPoint} with the specified
|
||||
* realm name.
|
||||
* Allows easily changing the realm, but leaving the remaining defaults in
|
||||
* place. If {@link #authenticationEntryPoint(AuthenticationEntryPoint)} has
|
||||
* been invoked, invoking this method will result in an error.
|
||||
*
|
||||
* @param realmName
|
||||
* the HTTP Basic realm to use
|
||||
@@ -91,14 +107,13 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
* @throws Exception
|
||||
*/
|
||||
public HttpBasicConfigurer<B> realmName(String realmName) throws Exception {
|
||||
BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
|
||||
basicAuthEntryPoint.setRealmName(realmName);
|
||||
basicAuthEntryPoint.afterPropertiesSet();
|
||||
return authenticationEntryPoint(basicAuthEntryPoint);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link AuthenticationEntryPoint} to be po pulated on
|
||||
* The {@link AuthenticationEntryPoint} to be populated on
|
||||
* {@link BasicAuthenticationFilter} in the event that authentication fails.
|
||||
* The default to use {@link BasicAuthenticationEntryPoint} with the realm
|
||||
* "Spring Security Application".
|
||||
@@ -141,6 +156,8 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML);
|
||||
preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), preferredMatcher);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,4 +170,20 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
basicAuthenticationFilter = postProcess(basicAuthenticationFilter);
|
||||
http.addFilter(basicAuthenticationFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private static class HttpStatusEntryPoint implements AuthenticationEntryPoint {
|
||||
private final HttpStatus httpStatus;
|
||||
|
||||
public HttpStatusEntryPoint(HttpStatus httpStatus) {
|
||||
super();
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public void commence(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException,
|
||||
ServletException {
|
||||
response.setStatus(httpStatus.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
-15
@@ -29,9 +29,9 @@ import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds logout support. Other {@link SecurityConfigurer} instances may invoke
|
||||
@@ -64,7 +64,8 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
|
||||
private SecurityContextLogoutHandler contextLogoutHandler = new SecurityContextLogoutHandler();
|
||||
private String logoutSuccessUrl = "/login?logout";
|
||||
private LogoutSuccessHandler logoutSuccessHandler;
|
||||
private RequestMatcher logoutRequestMatcher = new AntPathRequestMatcher("/logout", "POST");
|
||||
private String logoutUrl = "/logout";
|
||||
private RequestMatcher logoutRequestMatcher;
|
||||
private boolean permitAll;
|
||||
private boolean customLogoutSuccess;
|
||||
|
||||
@@ -98,18 +99,41 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL that triggers logout to occur on HTTP POST. The default is "/logout"
|
||||
* @param logoutUrl the URL that will invoke logout.
|
||||
* The URL that triggers log out to occur (default is "/logout"). If CSRF
|
||||
* protection is enabled (default), then the request must also be a POST.
|
||||
* This means that by default POST "/logout" is required to trigger a log
|
||||
* out. If CSRF protection is disabled, then any HTTP method is allowed.
|
||||
*
|
||||
* <p>
|
||||
* It is considered best practice to use an HTTP POST on any action that
|
||||
* changes state (i.e. log out) to protect against <a
|
||||
* href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF
|
||||
* attacks</a>. If you really want to use an HTTP GET, you can use
|
||||
* <code>logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "GET"));</code>
|
||||
* </p>
|
||||
*
|
||||
* @see #logoutRequestMatcher(RequestMatcher)
|
||||
* @see HttpSecurity#csrf()
|
||||
*
|
||||
* @param logoutUrl
|
||||
* the URL that will invoke logout.
|
||||
* @return the {@link LogoutConfigurer} for further customization
|
||||
*/
|
||||
public LogoutConfigurer<H> logoutUrl(String logoutUrl) {
|
||||
return logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "POST"));
|
||||
this.logoutRequestMatcher = null;
|
||||
this.logoutUrl = logoutUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The RequestMatcher that triggers logout to occur on HTTP POST. The default is "/logout"
|
||||
* @param logoutRequestMatcher the RequestMatcher used to determine if logout should occur.
|
||||
* The RequestMatcher that triggers log out to occur. In most circumstances
|
||||
* users will use {@link #logoutUrl(String)} which helps enforce good
|
||||
* practices.
|
||||
*
|
||||
* @see #logoutUrl(String)
|
||||
*
|
||||
* @param logoutRequestMatcher
|
||||
* the RequestMatcher used to determine if logout should occur.
|
||||
* @return the {@link LogoutConfigurer} for further customization
|
||||
*/
|
||||
public LogoutConfigurer<H> logoutRequestMatcher(RequestMatcher logoutRequestMatcher) {
|
||||
@@ -201,10 +225,10 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
|
||||
public void init(H http) throws Exception {
|
||||
if(permitAll) {
|
||||
PermitAllSupport.permitAll(http, this.logoutSuccessUrl);
|
||||
PermitAllSupport.permitAll(http, this.logoutRequestMatcher);
|
||||
PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http));
|
||||
}
|
||||
|
||||
DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if(loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) {
|
||||
loginPageGeneratingFilter.setLogoutSuccessUrl(getLogoutSuccessUrl());
|
||||
}
|
||||
@@ -212,7 +236,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
LogoutFilter logoutFilter = createLogoutFilter();
|
||||
LogoutFilter logoutFilter = createLogoutFilter(http);
|
||||
http.addFilter(logoutFilter);
|
||||
}
|
||||
|
||||
@@ -250,15 +274,27 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
|
||||
* instances, the {@link #logoutSuccessHandler(LogoutSuccessHandler)} and
|
||||
* the {@link #logoutUrl(String)}.
|
||||
*
|
||||
* @param http the builder to use
|
||||
* @return the {@link LogoutFilter} to use.
|
||||
* @throws Exception
|
||||
*/
|
||||
private LogoutFilter createLogoutFilter() throws Exception {
|
||||
private LogoutFilter createLogoutFilter(H http) throws Exception {
|
||||
logoutHandlers.add(contextLogoutHandler);
|
||||
LogoutHandler[] handlers = logoutHandlers.toArray(new LogoutHandler[logoutHandlers.size()]);
|
||||
LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers);
|
||||
result.setLogoutRequestMatcher(logoutRequestMatcher);
|
||||
result.setLogoutRequestMatcher(getLogoutRequestMatcher(http));
|
||||
result = postProcess(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RequestMatcher getLogoutRequestMatcher(H http) {
|
||||
if(logoutRequestMatcher != null) {
|
||||
return logoutRequestMatcher;
|
||||
}
|
||||
if(http.getConfigurer(CsrfConfigurer.class) != null) {
|
||||
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
|
||||
}
|
||||
return new AntPathRequestMatcher(this.logoutUrl);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -20,8 +20,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractRequestMatcherMappingConfigurer.UrlMapping;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry.UrlMapping;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ final class PermitAllSupport {
|
||||
|
||||
for(RequestMatcher matcher : requestMatchers) {
|
||||
if(matcher != null) {
|
||||
configurer.addMapping(0, new UrlMapping(matcher, SecurityConfig.createList(ExpressionUrlAuthorizationConfigurer.permitAll)));
|
||||
configurer.getRegistry().addMapping(0, new UrlMapping(matcher, SecurityConfig.createList(ExpressionUrlAuthorizationConfigurer.permitAll)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -32,7 +32,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
|
||||
/**
|
||||
* Configures Remember Me authentication. This typically involves the user
|
||||
@@ -67,7 +67,7 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFi
|
||||
* <ul>
|
||||
* <li>{@link AuthenticationManager}</li>
|
||||
* <li>{@link UserDetailsService} if no {@link #userDetailsService(UserDetailsService)} was specified.</li>
|
||||
* <li> {@link DefaultLoginPageViewFilter} - if present will be populated with information from the configuration</li>
|
||||
* <li> {@link DefaultLoginPageGeneratingFilter} - if present will be populated with information from the configuration</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -124,7 +124,7 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>> extend
|
||||
* {@link UserDetails} when a remember me token is valid. The default is to
|
||||
* use the {@link UserDetailsService} found by invoking
|
||||
* {@link HttpSecurity#getSharedObject(Class)} which is set when using
|
||||
* {@link WebSecurityConfigurerAdapter#registerAuthentication(org.springframework.security.config.annotation.authentication.AuthenticationManagerBuilder)}.
|
||||
* {@link WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder)}.
|
||||
* Alternatively, one can populate {@link #rememberMeServices(RememberMeServices)}.
|
||||
*
|
||||
* @param userDetailsService
|
||||
@@ -229,12 +229,12 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>> extend
|
||||
}
|
||||
|
||||
/**
|
||||
* If available, initializes the {@link DefaultLoginPageViewFilter} shared object.
|
||||
* If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder} to use
|
||||
*/
|
||||
private void initDefaultLoginFilter(H http) {
|
||||
DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if(loginPageGeneratingFilter != null) {
|
||||
loginPageGeneratingFilter.setRememberMeParameter(getRememberMeParameter());
|
||||
}
|
||||
|
||||
+29
-3
@@ -15,12 +15,22 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
/**
|
||||
* Adds request cache for Spring Security. Specifically this ensures that
|
||||
@@ -100,7 +110,23 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>> exte
|
||||
return result;
|
||||
}
|
||||
HttpSessionRequestCache defaultCache = new HttpSessionRequestCache();
|
||||
defaultCache.setRequestMatcher(new AntPathRequestMatcher("/**", "GET"));
|
||||
defaultCache.setRequestMatcher(createDefaultSavedRequestMatcher(http));
|
||||
return defaultCache;
|
||||
}
|
||||
}
|
||||
|
||||
private RequestMatcher createDefaultSavedRequestMatcher(H http) {
|
||||
ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
|
||||
if(contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
|
||||
RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.ico"));
|
||||
|
||||
MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_JSON);
|
||||
jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||
RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest);
|
||||
|
||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(new RequestHeaderRequestMatcher("X-Requested-With","XMLHttpRequest"));
|
||||
return new AndRequestMatcher(getRequests, notFavIcon, notJson, notXRequestedWith);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
@@ -45,7 +46,9 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
|
||||
*
|
||||
* <h2>Shared Objects Used</h2>
|
||||
*
|
||||
* No shared Objects are used.
|
||||
* <ul>
|
||||
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the {@link SecurityContextHolderAwareRequestFilter}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
@@ -75,6 +78,10 @@ public final class ServletApiConfigurer<H extends HttpSecurityBuilder<H>> extend
|
||||
LogoutConfigurer<H> logoutConf = http.getConfigurer(LogoutConfigurer.class);
|
||||
List<LogoutHandler> logoutHandlers = logoutConf == null ? null : logoutConf.getLogoutHandlers();
|
||||
securityContextRequestFilter.setLogoutHandlers(logoutHandlers);
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if(trustResolver != null) {
|
||||
securityContextRequestFilter.setTrustResolver(trustResolver);
|
||||
}
|
||||
securityContextRequestFilter = postProcess(securityContextRequestFilter);
|
||||
http.addFilter(securityContextRequestFilter);
|
||||
}
|
||||
|
||||
+48
-14
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
@@ -41,6 +42,7 @@ import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -65,12 +67,14 @@ import org.springframework.util.Assert;
|
||||
* <li>{@link RequestCache}</li>
|
||||
* <li>{@link SecurityContextRepository}</li>
|
||||
* <li>{@link SessionManagementConfigurer}</li>
|
||||
* <li>{@link InvalidSessionStrategy}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Used</h2>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link SecurityContextRepository}</li>
|
||||
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the {@link HttpSessionSecurityContextRepository} and {@link SessionManagementFilter}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -81,6 +85,7 @@ import org.springframework.util.Assert;
|
||||
public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<SessionManagementConfigurer<H>,H> {
|
||||
private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy();
|
||||
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
|
||||
private InvalidSessionStrategy invalidSessionStrategy;
|
||||
private List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<SessionAuthenticationStrategy>();
|
||||
private SessionRegistry sessionRegistry = new SessionRegistryImpl();
|
||||
private Integer maximumSessions;
|
||||
@@ -242,14 +247,17 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that no session fixation protection should be enabled. This
|
||||
* may be useful when utilizing other mechanisms for protecting against
|
||||
* session fixation. For example, if application container session
|
||||
* fixation protection is already in use. Otherwise, this option is not
|
||||
* recommended.
|
||||
* Specifies that the Servlet container-provided session fixation
|
||||
* protection should be used. When a session authenticates, the
|
||||
* Servlet 3.1 method {@code HttpServletRequest#changeSessionId()} is
|
||||
* called to change the session ID and retain all session attributes.
|
||||
* Using this option in a Servlet 3.0 or older container results in an
|
||||
* {@link IllegalStateException}.
|
||||
*
|
||||
* @return the {@link SessionManagementConfigurer} for further
|
||||
* customizations
|
||||
* @throws IllegalStateException if the container is not Servlet 3.1 or
|
||||
* newer.
|
||||
*/
|
||||
public SessionManagementConfigurer<H> changeSessionId() {
|
||||
setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy());
|
||||
@@ -334,28 +342,33 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(H builder) throws Exception {
|
||||
SecurityContextRepository securityContextRepository = builder.getSharedObject(SecurityContextRepository.class);
|
||||
public void init(H http) throws Exception {
|
||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
||||
boolean stateless = isStateless();
|
||||
|
||||
if(securityContextRepository == null) {
|
||||
if(stateless) {
|
||||
builder.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository());
|
||||
http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository());
|
||||
} else {
|
||||
HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository();
|
||||
httpSecurityRepository.setDisableUrlRewriting(!enableSessionUrlRewriting);
|
||||
httpSecurityRepository.setAllowSessionCreation(isAllowSessionCreation());
|
||||
builder.setSharedObject(SecurityContextRepository.class, httpSecurityRepository);
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if(trustResolver != null) {
|
||||
httpSecurityRepository.setTrustResolver(trustResolver);
|
||||
}
|
||||
http.setSharedObject(SecurityContextRepository.class, httpSecurityRepository);
|
||||
}
|
||||
}
|
||||
|
||||
RequestCache requestCache = builder.getSharedObject(RequestCache.class);
|
||||
RequestCache requestCache = http.getSharedObject(RequestCache.class);
|
||||
if(requestCache == null) {
|
||||
if(stateless) {
|
||||
builder.setSharedObject(RequestCache.class, new NullRequestCache());
|
||||
http.setSharedObject(RequestCache.class, new NullRequestCache());
|
||||
}
|
||||
}
|
||||
builder.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy());
|
||||
http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy());
|
||||
http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -366,7 +379,11 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
sessionManagementFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(sessionAuthenticationErrorUrl));
|
||||
}
|
||||
if(invalidSessionUrl != null) {
|
||||
sessionManagementFilter.setInvalidSessionStrategy(new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl));
|
||||
sessionManagementFilter.setInvalidSessionStrategy(getInvalidSessionStrategy());
|
||||
}
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if(trustResolver != null) {
|
||||
sessionManagementFilter.setTrustResolver(trustResolver);
|
||||
}
|
||||
sessionManagementFilter = postProcess(sessionManagementFilter);
|
||||
|
||||
@@ -378,6 +395,23 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link InvalidSessionStrategy} to use. If
|
||||
* {@link #invalidSessionUrl} is null, returns null otherwise
|
||||
* {@link SimpleRedirectInvalidSessionStrategy} is used.
|
||||
*
|
||||
* @return the {@link InvalidSessionStrategy} to use
|
||||
*/
|
||||
InvalidSessionStrategy getInvalidSessionStrategy() {
|
||||
if(invalidSessionUrl == null) {
|
||||
return null;
|
||||
}
|
||||
if(invalidSessionStrategy == null) {
|
||||
invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl);
|
||||
}
|
||||
return invalidSessionStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link SessionCreationPolicy}. Can not be null.
|
||||
* @return the {@link SessionCreationPolicy}
|
||||
@@ -451,4 +485,4 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
return new SessionFixationProtectionStrategy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+93
-36
@@ -27,29 +27,52 @@ import org.springframework.security.access.vote.AuthenticatedVoter;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Adds URL based authorization using {@link DefaultFilterInvocationSecurityMetadataSource}. At least one
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping} needs to be mapped to {@link ConfigAttribute}'s for
|
||||
* this {@link SecurityContextConfigurer} to have meaning.
|
||||
* <h2>Security Filters</h2>
|
||||
* Adds URL based authorization using
|
||||
* {@link DefaultFilterInvocationSecurityMetadataSource}. At least one
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping} needs to be
|
||||
* mapped to {@link ConfigAttribute}'s for this
|
||||
* {@link SecurityContextConfigurer} to have meaning. <h2>Security Filters</h2>
|
||||
*
|
||||
* <p>
|
||||
* Usage includes applying the {@link UrlAuthorizationConfigurer} and then
|
||||
* modifying the StandardInterceptUrlRegistry. For example:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .apply(new UrlAuthorizationConfigurer<HttpSecurity>()).getRegistry()
|
||||
* .antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
* .antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
* .anyRequest().hasRole("USER");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* The following Filters are populated
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}</li>
|
||||
* <li>
|
||||
* {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Created</h2>
|
||||
*
|
||||
* The following shared objects are populated to allow other {@link org.springframework.security.config.annotation.SecurityConfigurer}'s to customize:
|
||||
* The following shared objects are populated to allow other
|
||||
* {@link org.springframework.security.config.annotation.SecurityConfigurer}'s
|
||||
* to customize:
|
||||
* <ul>
|
||||
* <li>{@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}</li>
|
||||
* <li>
|
||||
* {@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Used</h2>
|
||||
@@ -57,17 +80,32 @@ import org.springframework.util.Assert;
|
||||
* The following shared objects are used:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link org.springframework.security.config.annotation.web.builders.HttpSecurity#getAuthenticationManager()}</li>
|
||||
* <li>
|
||||
* {@link org.springframework.security.config.annotation.web.builders.HttpSecurity#getAuthenticationManager()}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured
|
||||
* @param <C> the type of object that is being chained
|
||||
* @param <H>
|
||||
* the type of {@link HttpSecurityBuilder} that is being configured
|
||||
* @param <C>
|
||||
* the type of object that is being chained
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @see ExpressionUrlAuthorizationConfigurer
|
||||
*/
|
||||
public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>, C> extends AbstractInterceptUrlConfigurer<H,C,UrlAuthorizationConfigurer<H,C>.AuthorizedUrl> {
|
||||
public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractInterceptUrlConfigurer<UrlAuthorizationConfigurer<H>,H> {
|
||||
private final StandardInterceptUrlRegistry REGISTRY = new StandardInterceptUrlRegistry();
|
||||
|
||||
/**
|
||||
* The StandardInterceptUrlRegistry is what users will interact with after
|
||||
* applying the {@link UrlAuthorizationConfigurer}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public StandardInterceptUrlRegistry getRegistry() {
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
@@ -75,19 +113,45 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* @param objectPostProcessor
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customizations
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
public UrlAuthorizationConfigurer<H> withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
addObjectPostProcessor(objectPostProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public class StandardInterceptUrlRegistry extends ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<StandardInterceptUrlRegistry,AuthorizedUrl> {
|
||||
|
||||
@Override
|
||||
protected final AuthorizedUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
||||
return new AuthorizedUrl(requestMatchers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
*
|
||||
* @param objectPostProcessor
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations
|
||||
*/
|
||||
public StandardInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
||||
addObjectPostProcessor(objectPostProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public H and() {
|
||||
return UrlAuthorizationConfigurer.this.and();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the default {@link AccessDecisionVoter} instances used if an
|
||||
* {@link AccessDecisionManager} was not specified using
|
||||
* {@link #accessDecisionManager(AccessDecisionManager)}.
|
||||
*
|
||||
* @param http the builder to use
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List<AccessDecisionVoter> getDecisionVoters() {
|
||||
final List<AccessDecisionVoter> getDecisionVoters(H http) {
|
||||
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
|
||||
decisionVoters.add(new RoleVoter());
|
||||
decisionVoters.add(new AuthenticatedVoter());
|
||||
@@ -96,20 +160,13 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
|
||||
/**
|
||||
* Creates the {@link FilterInvocationSecurityMetadataSource} to use. The
|
||||
* implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}
|
||||
* .
|
||||
* implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}.
|
||||
*
|
||||
* @param http the builder to use
|
||||
*/
|
||||
@Override
|
||||
FilterInvocationSecurityMetadataSource createMetadataSource() {
|
||||
return new DefaultFilterInvocationSecurityMetadataSource(createRequestMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Chains the {@link RequestMatcher} creation to the {@link AuthorizedUrl} class.
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizedUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
||||
return new AuthorizedUrl(requestMatchers);
|
||||
FilterInvocationSecurityMetadataSource createMetadataSource(H http) {
|
||||
return new DefaultFilterInvocationSecurityMetadataSource(REGISTRY.createRequestMap());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,11 +175,11 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* @param configAttributes the {@link ConfigAttribute} instances that should be mapped by the {@link RequestMatcher} instances
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customizations
|
||||
*/
|
||||
private UrlAuthorizationConfigurer<H,C> addMapping(Iterable<? extends RequestMatcher> requestMatchers, Collection<ConfigAttribute> configAttributes) {
|
||||
private StandardInterceptUrlRegistry addMapping(Iterable<? extends RequestMatcher> requestMatchers, Collection<ConfigAttribute> configAttributes) {
|
||||
for(RequestMatcher requestMatcher : requestMatchers) {
|
||||
addMapping(new UrlMapping(requestMatcher, configAttributes));
|
||||
REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes));
|
||||
}
|
||||
return this;
|
||||
return REGISTRY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +252,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* with ROLE_
|
||||
* the {@link UrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> hasRole(String role) {
|
||||
public StandardInterceptUrlRegistry hasRole(String role) {
|
||||
return access(UrlAuthorizationConfigurer.hasRole(role));
|
||||
}
|
||||
|
||||
@@ -208,7 +265,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* it is automatically prepended already.
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> hasAnyRole(String... roles) {
|
||||
public StandardInterceptUrlRegistry hasAnyRole(String... roles) {
|
||||
return access(UrlAuthorizationConfigurer.hasAnyRole(roles));
|
||||
}
|
||||
|
||||
@@ -219,7 +276,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* the authority that should be required
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> hasAuthority(String authority) {
|
||||
public StandardInterceptUrlRegistry hasAuthority(String authority) {
|
||||
return access(authority);
|
||||
}
|
||||
|
||||
@@ -228,7 +285,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* @param authorities the authorities that the user should have at least one of (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> hasAnyAuthority(String... authorities) {
|
||||
public StandardInterceptUrlRegistry hasAnyAuthority(String... authorities) {
|
||||
return access(UrlAuthorizationConfigurer.hasAnyAuthority(authorities));
|
||||
}
|
||||
|
||||
@@ -236,7 +293,7 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* Specifies that an anonymous user is allowed access
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> anonymous() {
|
||||
public StandardInterceptUrlRegistry anonymous() {
|
||||
return hasRole("ROLE_ANONYMOUS");
|
||||
}
|
||||
|
||||
@@ -245,9 +302,9 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
|
||||
* @param attributes the {@link ConfigAttribute}'s that restrict access to a URL
|
||||
* @return the {@link UrlAuthorizationConfigurer} for further customization
|
||||
*/
|
||||
public UrlAuthorizationConfigurer<H,C> access(String... attributes) {
|
||||
public StandardInterceptUrlRegistry access(String... attributes) {
|
||||
addMapping(requestMatchers, SecurityConfig.createList(attributes));
|
||||
return UrlAuthorizationConfigurer.this;
|
||||
return UrlAuthorizationConfigurer.this.REGISTRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -49,9 +49,9 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds support for OpenID based authentication.
|
||||
@@ -75,7 +75,7 @@ import org.springframework.security.web.util.RequestMatcher;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void registerAuthentication(
|
||||
* protected void configure(AuthenticationManagerBuilder auth)(
|
||||
* AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
@@ -340,12 +340,12 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||
}
|
||||
|
||||
/**
|
||||
* If available, initializes the {@link DefaultLoginPageViewFilter} shared object.
|
||||
* If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder} to use
|
||||
*/
|
||||
private void initDefaultLoginFilter(H http) {
|
||||
DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if(loginPageGeneratingFilter != null && !isCustomLoginPage()) {
|
||||
loginPageGeneratingFilter.setOpenIdEnabled(true);
|
||||
loginPageGeneratingFilter.setOpenIDauthenticationUrl(getLoginProcessingUrl());
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.servlet.configuration;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
|
||||
/**
|
||||
* Add this annotation to an {@code @Configuration} class to have the Spring Security
|
||||
* configuration integrate with Spring MVC.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value={java.lang.annotation.ElementType.TYPE})
|
||||
@Documented
|
||||
@Import(WebMvcSecurityConfiguration.class)
|
||||
public @interface EnableWebMvcSecurity {
|
||||
}
|
||||
+18
-3
@@ -13,25 +13,40 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
package org.springframework.security.config.annotation.web.servlet.configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
/**
|
||||
* Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring
|
||||
* Security CSRF integration. This configuration is added whenever
|
||||
* {@link EnableWebMvc} is added by {@link SpringWebMvcImportSelector} and the
|
||||
* DispatcherServlet is present on the classpath.
|
||||
* DispatcherServlet is present on the classpath. It also adds the
|
||||
* {@link AuthenticationPrincipalArgumentResolver} as a
|
||||
* {@link HandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
@Configuration
|
||||
class CsrfWebMvcConfiguration {
|
||||
@EnableWebSecurity
|
||||
public class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(
|
||||
List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RequestDataValueProcessor requestDataValueProcessor() {
|
||||
+5
-1
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.security.config.debug;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
@@ -22,15 +24,17 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.web.debug.DebugFilter;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class SecurityDebugBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
||||
Logger.logger.warn("\n\n" +
|
||||
logger.warn("\n\n" +
|
||||
"********************************************************************\n" +
|
||||
"********** Security debugging is enabled. *************\n" +
|
||||
"********** This may include sensitive information. *************\n" +
|
||||
|
||||
+56
-3
@@ -15,17 +15,26 @@
|
||||
*/
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
|
||||
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfLogoutHandler;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
@@ -44,6 +53,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private static final String ATT_REPOSITORY = "token-repository-ref";
|
||||
|
||||
private String csrfRepositoryRef;
|
||||
private BeanDefinition csrfFilter;
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
boolean webmvcPresent = ClassUtils.isPresent(DISPATCHER_SERVLET_CLASS_NAME, getClass().getClassLoader());
|
||||
@@ -57,21 +67,64 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
||||
csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
|
||||
String matcherRef = element.getAttribute(ATT_MATCHER);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class);
|
||||
|
||||
if(!StringUtils.hasText(csrfRepositoryRef)) {
|
||||
RootBeanDefinition csrfTokenRepository = new RootBeanDefinition(HttpSessionCsrfTokenRepository.class);
|
||||
csrfRepositoryRef = pc.getReaderContext().generateBeanName(csrfTokenRepository);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(csrfTokenRepository, csrfRepositoryRef));
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class);
|
||||
builder.addConstructorArgReference(csrfRepositoryRef);
|
||||
|
||||
if(StringUtils.hasText(matcherRef)) {
|
||||
builder.addPropertyReference("requireCsrfProtectionMatcher", matcherRef);
|
||||
}
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
csrfFilter = builder.getBeanDefinition();
|
||||
return csrfFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the AccessDeniedHandler on the {@link CsrfFilter}
|
||||
*
|
||||
* @param invalidSessionStrategy the {@link InvalidSessionStrategy} to use
|
||||
* @param defaultDeniedHandler the {@link AccessDeniedHandler} to use
|
||||
*/
|
||||
void initAccessDeniedHandler(BeanDefinition invalidSessionStrategy, BeanMetadataElement defaultDeniedHandler) {
|
||||
BeanMetadataElement accessDeniedHandler = createAccessDeniedHandler(invalidSessionStrategy, defaultDeniedHandler);
|
||||
csrfFilter.getPropertyValues().addPropertyValue("accessDeniedHandler", accessDeniedHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link AccessDeniedHandler} from the result of
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} and
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)}. If
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)} is non-null, then
|
||||
* a {@link DelegatingAccessDeniedHandler} is used in combination with
|
||||
* {@link InvalidSessionAccessDeniedHandler} and the
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise,
|
||||
* only {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used.
|
||||
*
|
||||
* @param invalidSessionStrategy the {@link InvalidSessionStrategy} to use
|
||||
* @param defaultDeniedHandler the {@link AccessDeniedHandler} to use
|
||||
*
|
||||
* @return the {@link BeanMetadataElement} that is the {@link AccessDeniedHandler} to populate on the {@link CsrfFilter}
|
||||
*/
|
||||
private BeanMetadataElement createAccessDeniedHandler(BeanDefinition invalidSessionStrategy, BeanMetadataElement defaultDeniedHandler) {
|
||||
if(invalidSessionStrategy == null) {
|
||||
return defaultDeniedHandler;
|
||||
}
|
||||
ManagedMap<Class<? extends AccessDeniedException>,BeanDefinition> handlers =
|
||||
new ManagedMap<Class<? extends AccessDeniedException>, BeanDefinition>();
|
||||
BeanDefinitionBuilder invalidSessionHandlerBldr = BeanDefinitionBuilder.rootBeanDefinition(InvalidSessionAccessDeniedHandler.class);
|
||||
invalidSessionHandlerBldr.addConstructorArgValue(invalidSessionStrategy);
|
||||
handlers.put(MissingCsrfTokenException.class, invalidSessionHandlerBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder deniedBldr = BeanDefinitionBuilder.rootBeanDefinition(DelegatingAccessDeniedHandler.class);
|
||||
deniedBldr.addConstructorArgValue(handlers);
|
||||
deniedBldr.addConstructorArgValue(defaultDeniedHandler);
|
||||
|
||||
return deniedBldr.getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanDefinition getCsrfAuthenticationStrategy() {
|
||||
|
||||
+4
-2
@@ -25,7 +25,8 @@ import org.springframework.security.web.context.SecurityContextPersistenceFilter
|
||||
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
|
||||
public class DefaultFilterChainValidator implements FilterChainProxy.FilterChainValidator {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
@@ -45,7 +46,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
||||
Iterator<SecurityFilterChain> chains = filterChains.iterator();
|
||||
|
||||
while (chains.hasNext()) {
|
||||
if (((DefaultSecurityFilterChain)chains.next()).getRequestMatcher() instanceof AnyRequestMatcher && chains.hasNext()) {
|
||||
RequestMatcher matcher = ((DefaultSecurityFilterChain)chains.next()).getRequestMatcher();
|
||||
if (AnyRequestMatcher.INSTANCE.equals(matcher) && chains.hasNext()) {
|
||||
throw new IllegalArgumentException("A universal match pattern ('/**') is defined " +
|
||||
" before other patterns in the filter chain, causing them to be ignored. Please check the " +
|
||||
"ordering in your <security:http> namespace or FilterChainProxy bean configuration");
|
||||
|
||||
+16
-7
@@ -70,7 +70,7 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -130,6 +130,10 @@ class HttpConfigurationBuilder {
|
||||
private BeanMetadataElement csrfLogoutHandler;
|
||||
private BeanMetadataElement csrfAuthStrategy;
|
||||
|
||||
private CsrfBeanDefinitionParser csrfParser;
|
||||
|
||||
private BeanDefinition invalidSession;
|
||||
|
||||
public HttpConfigurationBuilder(Element element, ParserContext pc,
|
||||
BeanReference portMapper, BeanReference portResolver, BeanReference authenticationManager) {
|
||||
this.httpElt = element;
|
||||
@@ -200,8 +204,8 @@ class HttpConfigurationBuilder {
|
||||
}
|
||||
|
||||
void setAccessDeniedHandler(BeanMetadataElement accessDeniedHandler) {
|
||||
if(csrfFilter != null) {
|
||||
csrfFilter.getPropertyValues().add("accessDeniedHandler", accessDeniedHandler);
|
||||
if(csrfParser != null ) {
|
||||
csrfParser.initAccessDeniedHandler(this.invalidSession, accessDeniedHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +385,10 @@ class HttpConfigurationBuilder {
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(invalidSessionUrl)) {
|
||||
sessionMgmtFilter.addPropertyValue("invalidSessionStrategy", new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl));
|
||||
BeanDefinitionBuilder invalidSessionBldr = BeanDefinitionBuilder.rootBeanDefinition(SimpleRedirectInvalidSessionStrategy.class);
|
||||
invalidSessionBldr.addConstructorArgValue(invalidSessionUrl);
|
||||
invalidSession = invalidSessionBldr.getBeanDefinition();
|
||||
sessionMgmtFilter.addPropertyValue("invalidSessionStrategy", invalidSession);
|
||||
}
|
||||
|
||||
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
|
||||
@@ -637,14 +644,16 @@ class HttpConfigurationBuilder {
|
||||
|
||||
}
|
||||
|
||||
private void createCsrfFilter() {
|
||||
private CsrfBeanDefinitionParser createCsrfFilter() {
|
||||
Element elmt = DomUtils.getChildElementByTagName(httpElt, Elements.CSRF);
|
||||
if (elmt != null) {
|
||||
CsrfBeanDefinitionParser csrfParser = new CsrfBeanDefinitionParser();
|
||||
this.csrfFilter = csrfParser.parse(elmt, pc);
|
||||
csrfParser = new CsrfBeanDefinitionParser();
|
||||
csrfFilter = csrfParser.parse(elmt, pc);
|
||||
this.csrfAuthStrategy = csrfParser.getCsrfAuthenticationStrategy();
|
||||
this.csrfLogoutHandler = csrfParser.getCsrfLogoutHandler();
|
||||
return csrfParser;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
BeanMetadataElement getCsrfLogoutHandler() {
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ import org.springframework.security.config.authentication.AuthenticationManagerF
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.PortResolverImpl;
|
||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -5,10 +5,10 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
+3
-3
@@ -132,12 +132,12 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
if (tokenValiditySet) {
|
||||
int tokenValidity = Integer.parseInt(tokenValiditySeconds);
|
||||
if (tokenValidity < 0 && isPersistent) {
|
||||
boolean isTokenValidityNegative = tokenValiditySeconds.startsWith("-");
|
||||
if (isTokenValidityNegative && isPersistent) {
|
||||
pc.getReaderContext().error(ATT_TOKEN_VALIDITY + " cannot be negative if using" +
|
||||
" a persistent remember-me token repository", source);
|
||||
}
|
||||
services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValidity);
|
||||
services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValiditySeconds);
|
||||
}
|
||||
|
||||
if (remembermeParameterSet) {
|
||||
|
||||
+32
-2
@@ -1,5 +1,8 @@
|
||||
package org.springframework.security.config.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -9,6 +12,7 @@ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -40,7 +44,8 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
/** Defines the port the LDAP_PROVIDER server should run on */
|
||||
public static final String ATT_PORT = "port";
|
||||
public static final String OPT_DEFAULT_PORT = "33389";
|
||||
private static final int DEFAULT_PORT = 33389;
|
||||
public static final String OPT_DEFAULT_PORT = String.valueOf(DEFAULT_PORT);
|
||||
|
||||
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||
@@ -101,7 +106,10 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String port = element.getAttribute(ATT_PORT);
|
||||
|
||||
if (!StringUtils.hasText(port)) {
|
||||
port = OPT_DEFAULT_PORT;
|
||||
port = getDefaultPort();
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Using default port of " + port);
|
||||
}
|
||||
}
|
||||
|
||||
String url = "ldap://127.0.0.1:" + port + "/" + suffix;
|
||||
@@ -134,4 +142,26 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
return (RootBeanDefinition) contextSource.getBeanDefinition();
|
||||
}
|
||||
|
||||
private String getDefaultPort() {
|
||||
ServerSocket serverSocket = null;
|
||||
try {
|
||||
try {
|
||||
serverSocket = new ServerSocket(DEFAULT_PORT);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
serverSocket = new ServerSocket(0);
|
||||
} catch(IOException e2) {
|
||||
return String.valueOf(DEFAULT_PORT);
|
||||
}
|
||||
}
|
||||
return String.valueOf(serverSocket.getLocalPort());
|
||||
} finally {
|
||||
if(serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -280,7 +280,7 @@ http-firewall =
|
||||
element http-firewall {ref}
|
||||
|
||||
http =
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "secured" attribute to "false".
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "security" attribute to "none".
|
||||
element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & openid-login? & x509? & jee? & http-basic? & logout? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler?) }
|
||||
http.attlist &=
|
||||
## The request URL pattern which will be mapped to the filter chain created by this <http> element. If omitted, the filter chain will match all requests.
|
||||
@@ -524,7 +524,7 @@ session-management.attlist &=
|
||||
## Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter
|
||||
attribute session-authentication-strategy-ref {xsd:token}?
|
||||
session-management.attlist &=
|
||||
## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
|
||||
## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
|
||||
attribute session-authentication-error-url {xsd:token}?
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ remember-me =
|
||||
## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.
|
||||
element remember-me {remember-me.attlist}
|
||||
remember-me.attlist &=
|
||||
## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application. If unset, it will default to a random value generated by SecureRandom.
|
||||
## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.
|
||||
attribute key {xsd:token}?
|
||||
|
||||
remember-me.attlist &=
|
||||
@@ -593,7 +593,7 @@ anonymous =
|
||||
## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.
|
||||
element anonymous {anonymous.attlist}
|
||||
anonymous.attlist &=
|
||||
## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to a random value generated by SecureRandom.
|
||||
## The key shared between the provider and filter. This generally does not need to be set. If unset, it will default to "doesNotMatter".
|
||||
attribute key {xsd:token}?
|
||||
anonymous.attlist &=
|
||||
## The username that should be assigned to the anonymous request. This allows the principal to be identified, which may be important for logging and auditing. if unset, defaults to "anonymousUser".
|
||||
@@ -739,4 +739,4 @@ position =
|
||||
## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
|
||||
attribute position {named-security-filter}
|
||||
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SECURITY_CONTEXT_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" |"BASIC_AUTH_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "SESSION_MANAGEMENT_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" | "LOGIN_PAGE_FILTER" | "DIGEST_AUTH_FILTER" |"BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
+10
-7
@@ -868,7 +868,7 @@
|
||||
<xs:documentation>Container element for HTTP security configuration. Multiple elements can now be defined,
|
||||
each with a specific pattern to which the enclosed security configuration applies. A
|
||||
pattern can also be configured to bypass Spring Security's filters completely by setting
|
||||
the "secured" attribute to "false".
|
||||
the "security" attribute to "none".
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
@@ -1695,7 +1695,7 @@
|
||||
<xs:attribute name="session-authentication-error-url" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines the URL of the error page which should be shown when the
|
||||
SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error
|
||||
SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error
|
||||
code will be returned to the client. Note that this attribute doesn't apply if the error
|
||||
occurs during a form-based login, where the URL for authentication failure will take
|
||||
precedence.
|
||||
@@ -1748,8 +1748,7 @@
|
||||
<xs:attribute name="key" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The "key" used to identify cookies from a specific token-based remember-me application.
|
||||
You should set this to a unique value for your application. If unset, it will default to a
|
||||
random value generated by SecureRandom.
|
||||
You should set this to a unique value for your application.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
@@ -1832,7 +1831,7 @@
|
||||
<xs:attribute name="key" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The key shared between the provider and filter. This generally does not need to be set. If
|
||||
unset, it will default to a random value generated by SecureRandom.
|
||||
unset, it will default to "doesNotMatter".
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
@@ -2293,20 +2292,24 @@
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="FIRST"/>
|
||||
<xs:enumeration value="CHANNEL_FILTER"/>
|
||||
<xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
|
||||
<xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
|
||||
<xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
|
||||
<xs:enumeration value="LOGOUT_FILTER"/>
|
||||
<xs:enumeration value="X509_FILTER"/>
|
||||
<xs:enumeration value="PRE_AUTH_FILTER"/>
|
||||
<xs:enumeration value="CAS_FILTER"/>
|
||||
<xs:enumeration value="FORM_LOGIN_FILTER"/>
|
||||
<xs:enumeration value="OPENID_FILTER"/>
|
||||
<xs:enumeration value="LOGIN_PAGE_FILTER"/>
|
||||
<xs:enumeration value="DIGEST_AUTH_FILTER"/>
|
||||
<xs:enumeration value="BASIC_AUTH_FILTER"/>
|
||||
<xs:enumeration value="REQUEST_CACHE_FILTER"/>
|
||||
<xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
|
||||
<xs:enumeration value="JAAS_API_SUPPORT_FILTER"/>
|
||||
<xs:enumeration value="REMEMBER_ME_FILTER"/>
|
||||
<xs:enumeration value="ANONYMOUS_FILTER"/>
|
||||
<xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
|
||||
<xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
|
||||
<xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
|
||||
<xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
|
||||
<xs:enumeration value="SWITCH_USER_FILTER"/>
|
||||
<xs:enumeration value="LAST"/>
|
||||
|
||||
+6
-6
@@ -280,7 +280,7 @@ http-firewall =
|
||||
element http-firewall {ref}
|
||||
|
||||
http =
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "secured" attribute to "false".
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "security" attribute to "none".
|
||||
element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & openid-login? & x509? & jee? & http-basic? & logout? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler? & headers? & csrf?) }
|
||||
http.attlist &=
|
||||
## The request URL pattern which will be mapped to the filter chain created by this <http> element. If omitted, the filter chain will match all requests.
|
||||
@@ -357,7 +357,7 @@ intercept-url.attlist &=
|
||||
attribute access {xsd:token}?
|
||||
intercept-url.attlist &=
|
||||
## The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.
|
||||
attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "TRACE"}?
|
||||
attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "PATCH" | "TRACE"}?
|
||||
|
||||
intercept-url.attlist &=
|
||||
## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.
|
||||
@@ -524,7 +524,7 @@ session-management.attlist &=
|
||||
## Allows injection of the SessionAuthenticationStrategy instance used by the SessionManagementFilter
|
||||
attribute session-authentication-strategy-ref {xsd:token}?
|
||||
session-management.attlist &=
|
||||
## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
|
||||
## Defines the URL of the error page which should be shown when the SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error code will be returned to the client. Note that this attribute doesn't apply if the error occurs during a form-based login, where the URL for authentication failure will take precedence.
|
||||
attribute session-authentication-error-url {xsd:token}?
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ remember-me.attlist &=
|
||||
|
||||
remember-me.attlist &=
|
||||
## The period (in seconds) for which the remember-me cookie should be valid.
|
||||
attribute token-validity-seconds {xsd:integer}?
|
||||
attribute token-validity-seconds {xsd:string}?
|
||||
|
||||
remember-me.attlist &=
|
||||
## Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful remember-me authentication.
|
||||
@@ -746,7 +746,7 @@ hsts-options.attlist &=
|
||||
attribute request-matcher-ref { xsd:token }?
|
||||
|
||||
cache-control =
|
||||
## Adds Cache-Control no-cache, no-store, must-revalidate and Pragma no-cache every URL
|
||||
## Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for every request
|
||||
element cache-control {empty}
|
||||
|
||||
frame-options =
|
||||
@@ -818,4 +818,4 @@ position =
|
||||
## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
|
||||
attribute position {named-security-filter}
|
||||
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "HEADERS_FILTER" | "CSRF_FILTER" | "SECURITY_CONTEXT_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" |"BASIC_AUTH_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "SESSION_MANAGEMENT_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "WEB_ASYNC_MANAGER_FILTER" | "HEADERS_FILTER" | "CSRF_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" | "LOGIN_PAGE_FILTER" | "DIGEST_AUTH_FILTER" | "BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
|
||||
+13
-6
@@ -868,7 +868,7 @@
|
||||
<xs:documentation>Container element for HTTP security configuration. Multiple elements can now be defined,
|
||||
each with a specific pattern to which the enclosed security configuration applies. A
|
||||
pattern can also be configured to bypass Spring Security's filters completely by setting
|
||||
the "secured" attribute to "false".
|
||||
the "security" attribute to "none".
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
@@ -1248,6 +1248,7 @@
|
||||
<xs:enumeration value="OPTIONS"/>
|
||||
<xs:enumeration value="POST"/>
|
||||
<xs:enumeration value="PUT"/>
|
||||
<xs:enumeration value="PATCH"/>
|
||||
<xs:enumeration value="TRACE"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
@@ -1702,7 +1703,7 @@
|
||||
<xs:attribute name="session-authentication-error-url" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines the URL of the error page which should be shown when the
|
||||
SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (402) error
|
||||
SessionAuthenticationStrategy raises an exception. If not set, an unauthorized (401) error
|
||||
code will be returned to the client. Note that this attribute doesn't apply if the error
|
||||
occurs during a form-based login, where the URL for authentication failure will take
|
||||
precedence.
|
||||
@@ -1795,7 +1796,7 @@
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="token-validity-seconds" type="xs:integer">
|
||||
<xs:attribute name="token-validity-seconds" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.
|
||||
</xs:documentation>
|
||||
@@ -2314,7 +2315,8 @@
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="cache-control">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds Cache-Control no-cache, no-store, must-revalidate and Pragma no-cache every URL
|
||||
<xs:documentation>Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for
|
||||
every request
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType/>
|
||||
@@ -2504,22 +2506,27 @@
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="FIRST"/>
|
||||
<xs:enumeration value="CHANNEL_FILTER"/>
|
||||
<xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
|
||||
<xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
|
||||
<xs:enumeration value="WEB_ASYNC_MANAGER_FILTER"/>
|
||||
<xs:enumeration value="HEADERS_FILTER"/>
|
||||
<xs:enumeration value="CSRF_FILTER"/>
|
||||
<xs:enumeration value="SECURITY_CONTEXT_FILTER"/>
|
||||
<xs:enumeration value="LOGOUT_FILTER"/>
|
||||
<xs:enumeration value="X509_FILTER"/>
|
||||
<xs:enumeration value="PRE_AUTH_FILTER"/>
|
||||
<xs:enumeration value="CAS_FILTER"/>
|
||||
<xs:enumeration value="FORM_LOGIN_FILTER"/>
|
||||
<xs:enumeration value="OPENID_FILTER"/>
|
||||
<xs:enumeration value="LOGIN_PAGE_FILTER"/>
|
||||
<xs:enumeration value="DIGEST_AUTH_FILTER"/>
|
||||
<xs:enumeration value="BASIC_AUTH_FILTER"/>
|
||||
<xs:enumeration value="REQUEST_CACHE_FILTER"/>
|
||||
<xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
|
||||
<xs:enumeration value="JAAS_API_SUPPORT_FILTER"/>
|
||||
<xs:enumeration value="REMEMBER_ME_FILTER"/>
|
||||
<xs:enumeration value="ANONYMOUS_FILTER"/>
|
||||
<xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
|
||||
<xs:enumeration value="SESSION_MANAGEMENT_FILTER"/>
|
||||
<xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
|
||||
<xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
|
||||
<xs:enumeration value="SWITCH_USER_FILTER"/>
|
||||
<xs:enumeration value="LAST"/>
|
||||
|
||||
+1
@@ -42,6 +42,7 @@ abstract class AbstractXmlConfigTests extends Specification {
|
||||
def mockBean(Class clazz, String id = clazz.simpleName) {
|
||||
xml.'b:bean'(id: id, 'class': Mockito.class.name, 'factory-method':'mock') {
|
||||
'b:constructor-arg'(value : clazz.name)
|
||||
'b:constructor-arg'(value : id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-7
@@ -20,6 +20,7 @@ import javax.servlet.Filter
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException
|
||||
import org.springframework.context.ConfigurableApplicationContext
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockFilterChain
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
@@ -27,6 +28,9 @@ import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.authority.AuthorityUtils
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
@@ -36,6 +40,7 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
|
||||
import org.springframework.security.web.context.HttpRequestResponseHolder
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository
|
||||
import org.springframework.security.web.csrf.CsrfToken
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
|
||||
|
||||
import spock.lang.AutoCleanup
|
||||
@@ -48,13 +53,17 @@ import spock.lang.Specification
|
||||
abstract class BaseSpringSpec extends Specification {
|
||||
@AutoCleanup
|
||||
ConfigurableApplicationContext context
|
||||
@AutoCleanup
|
||||
ConfigurableApplicationContext oppContext
|
||||
|
||||
MockHttpServletRequest request
|
||||
MockHttpServletResponse response
|
||||
MockFilterChain chain
|
||||
CsrfToken csrfToken
|
||||
AuthenticationManagerBuilder authenticationBldr
|
||||
|
||||
def setup() {
|
||||
authenticationBldr = createAuthenticationManagerBuilder()
|
||||
setupWeb(null)
|
||||
}
|
||||
|
||||
@@ -68,14 +77,12 @@ abstract class BaseSpringSpec extends Specification {
|
||||
setupCsrf()
|
||||
}
|
||||
|
||||
def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN") {
|
||||
csrfToken = new CsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue)
|
||||
new HttpSessionCsrfTokenRepository().saveToken(csrfToken, request,response)
|
||||
request.setParameter(csrfToken.parameterName, csrfToken.token)
|
||||
def setupCsrf(csrfTokenValue="BaseSpringSpec_CSRFTOKEN",req=request,resp=response) {
|
||||
csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf",csrfTokenValue)
|
||||
new HttpSessionCsrfTokenRepository().saveToken(csrfToken, req, resp)
|
||||
req.setParameter(csrfToken.parameterName, csrfToken.token)
|
||||
}
|
||||
|
||||
AuthenticationManagerBuilder authenticationBldr = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR).inMemoryAuthentication().and()
|
||||
|
||||
def cleanup() {
|
||||
SecurityContextHolder.clearContext()
|
||||
}
|
||||
@@ -148,4 +155,14 @@ abstract class BaseSpringSpec extends Specification {
|
||||
repo.loadContext(requestResponseHolder)
|
||||
repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
|
||||
}
|
||||
}
|
||||
|
||||
def createAuthenticationManagerBuilder() {
|
||||
oppContext = new AnnotationConfigApplicationContext(ObjectPostProcessorConfiguration, AuthenticationConfiguration)
|
||||
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor)
|
||||
auth.inMemoryAuthentication().and()
|
||||
}
|
||||
|
||||
def getObjectPostProcessor() {
|
||||
oppContext.getBean(ObjectPostProcessor)
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -38,7 +38,7 @@ class AuthenticationManagerBuilderTests extends BaseSpringSpec {
|
||||
setup:
|
||||
ObjectPostProcessor opp = Mock()
|
||||
AuthenticationProvider provider = Mock()
|
||||
AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR).objectPostProcessor(opp)
|
||||
AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(objectPostProcessor).objectPostProcessor(opp)
|
||||
when: "Adding an AuthenticationProvider"
|
||||
builder.authenticationProvider(provider)
|
||||
builder.build()
|
||||
@@ -47,11 +47,11 @@ class AuthenticationManagerBuilderTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
// https://github.com/SpringSource/spring-security-javaconfig/issues/132
|
||||
def "#132 Custom AuthenticationEventPublisher with Web registerAuthentication"() {
|
||||
def "#132 Custom AuthenticationEventPublisher with Web configure(AuthenticationManagerBuilder)"() {
|
||||
setup:
|
||||
AuthenticationEventPublisher aep = Mock()
|
||||
when:
|
||||
AuthenticationManager am = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR)
|
||||
AuthenticationManager am = new AuthenticationManagerBuilder(objectPostProcessor)
|
||||
.authenticationEventPublisher(aep)
|
||||
.inMemoryAuthentication()
|
||||
.and()
|
||||
@@ -78,7 +78,7 @@ class AuthenticationManagerBuilderTests extends BaseSpringSpec {
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
|
||||
+1
-2
@@ -35,8 +35,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
@Configuration
|
||||
class BaseAuthenticationConfig {
|
||||
@Autowired
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@ class NamespaceAuthenticationManagerTests extends BaseSpringSpec {
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
@@ -74,7 +74,7 @@ class NamespaceAuthenticationManagerTests extends BaseSpringSpec {
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.eraseCredentials(false)
|
||||
.inMemoryAuthentication()
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ class NamespaceAuthenticationProviderTests extends BaseSpringSpec {
|
||||
@Configuration
|
||||
static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter {
|
||||
static DaoAuthenticationProvider expected = new DaoAuthenticationProvider()
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.authenticationProvider(expected)
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class NamespaceAuthenticationProviderTests extends BaseSpringSpec {
|
||||
@Configuration
|
||||
static class UserServiceRefConfig extends WebSecurityConfigurerAdapter {
|
||||
static InMemoryUserDetailsManager expected = new InMemoryUserDetailsManager([] as Collection)
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.userDetailsService(expected)
|
||||
}
|
||||
|
||||
+3
-3
@@ -54,7 +54,7 @@ class NamespaceJdbcUserServiceTests extends BaseSpringSpec {
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
.dataSource(dataSource) // jdbc-user-service@data-source-ref
|
||||
@@ -84,7 +84,7 @@ class NamespaceJdbcUserServiceTests extends BaseSpringSpec {
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
.dataSource(dataSource)
|
||||
@@ -132,7 +132,7 @@ class NamespaceJdbcUserServiceTests extends BaseSpringSpec {
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.jdbcAuthentication()
|
||||
// jdbc-user-service@dataSource
|
||||
|
||||
+3
-6
@@ -54,8 +54,7 @@ class NamespacePasswordEncoderTests extends BaseSpringSpec {
|
||||
@Configuration
|
||||
static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
|
||||
auth
|
||||
@@ -76,8 +75,7 @@ class NamespacePasswordEncoderTests extends BaseSpringSpec {
|
||||
@Configuration
|
||||
static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
|
||||
auth
|
||||
@@ -106,8 +104,7 @@ class NamespacePasswordEncoderTests extends BaseSpringSpec {
|
||||
@Configuration
|
||||
static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
|
||||
User user = new User("user",encoder.encode("password"), AuthorityUtils.createAuthorityList("ROLE_USER"))
|
||||
|
||||
+2
-4
@@ -37,8 +37,7 @@ public class PasswordEncoderConfigurerConfigs {
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
BCryptPasswordEncoder encoder = passwordEncoder();
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
@@ -66,8 +65,7 @@ public class PasswordEncoderConfigurerConfigs {
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class PasswordEncoderNoAuthManagerLoadsConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
BCryptPasswordEncoder encoder = passwordEncoder();
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.configuration;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
public class AroundMethodInterceptor implements MethodInterceptor {
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
return String.valueOf(methodInvocation.proceed());
|
||||
}
|
||||
}
|
||||
+29
-8
@@ -15,25 +15,23 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.configuration
|
||||
|
||||
import javax.servlet.ServletConfig
|
||||
import javax.servlet.ServletContext
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware
|
||||
import org.springframework.beans.factory.BeanFactoryAware
|
||||
import org.springframework.beans.factory.BeanNameAware
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.DisposableBean
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.ApplicationContextAware
|
||||
import org.springframework.context.ApplicationEventPublisherAware
|
||||
import org.springframework.context.EnvironmentAware
|
||||
import org.springframework.context.MessageSourceAware
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext
|
||||
import org.springframework.mock.web.MockServletConfig
|
||||
import org.springframework.mock.web.MockServletContext
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor
|
||||
import org.springframework.web.context.ServletConfigAware
|
||||
import org.springframework.web.context.ServletContextAware
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||
@@ -117,4 +115,27 @@ class AutowireBeanFactoryObjectPostProcessorTests extends BaseSpringSpec {
|
||||
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"
|
||||
}
|
||||
|
||||
@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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.configuration;
|
||||
|
||||
public class MyAdvisedBean {
|
||||
|
||||
public Object doStuff() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+231
-12
@@ -18,24 +18,27 @@ package org.springframework.security.config.annotation.method.configuration
|
||||
import static org.fest.assertions.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInterceptor
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.AccessDecisionManager
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.access.ConfigAttribute
|
||||
import org.springframework.security.access.PermissionEvaluator
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurerAdapterTests.InMemoryAuthWithWebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.authority.AuthorityUtils
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -67,8 +70,7 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
|
||||
static AuthenticationSuccessEvent EVENT
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
@@ -82,4 +84,221 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
|
||||
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
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration {
|
||||
static AuthenticationTrustResolver TR
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@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()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
|
||||
static class ExpressionHandlerHasBeanResolverSetConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServiceImpl service() {
|
||||
return new ServiceImpl()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CustomAuthzService authz() {
|
||||
return new CustomAuthzService()
|
||||
}
|
||||
}
|
||||
|
||||
static class ServiceImpl {
|
||||
@PreAuthorize("@authz.authorize()")
|
||||
public String message() {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
static class CustomAuthzService {
|
||||
boolean 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()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
static class MethodSecurityServiceConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@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)
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
|
||||
static PermissionEvaluator PE
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PermissionEvaluator pe() {
|
||||
PE
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MethodSecurityService service() {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
def "GlobalMethodSecurityConfiguration does not failw with multiple PermissionEvaluator"() {
|
||||
when:
|
||||
loadConfig(MultiPermissionEvaluatorConfig)
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
|
||||
static PermissionEvaluator PE
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PermissionEvaluator pe() {
|
||||
PE
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PermissionEvaluator pe2() {
|
||||
PE
|
||||
}
|
||||
|
||||
@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)
|
||||
}
|
||||
|
||||
static class ChildConfig extends ParentConfig {}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
static class ParentConfig {
|
||||
|
||||
@Autowired
|
||||
protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MethodSecurityService service() {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -16,8 +16,10 @@
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import javax.annotation.security.DenyAll
|
||||
import javax.annotation.security.PermitAll;
|
||||
|
||||
import org.springframework.security.access.annotation.Secured
|
||||
import org.springframework.security.access.method.P
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.security.core.Authentication
|
||||
@@ -34,9 +36,15 @@ public interface MethodSecurityService {
|
||||
@Secured("ROLE_ADMIN")
|
||||
public String secured();
|
||||
|
||||
@Secured("ROLE_USER")
|
||||
public String securedUser();
|
||||
|
||||
@DenyAll
|
||||
public String jsr250();
|
||||
|
||||
@PermitAll
|
||||
public String jsr250PermitAll();
|
||||
|
||||
@Secured(["ROLE_USER","RUN_AS_SUPER"])
|
||||
public Authentication runAs();
|
||||
|
||||
@@ -48,4 +56,7 @@ public interface MethodSecurityService {
|
||||
|
||||
@PostAuthorize("hasPermission(#object,'read')")
|
||||
public String postHasPermission(String object);
|
||||
|
||||
@PostAuthorize("#o?.contains('grant')")
|
||||
public String postAnnotation(@P("o") String object);
|
||||
}
|
||||
|
||||
+15
@@ -35,11 +35,21 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String securedUser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsr250() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsr250PermitAll() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication runAs() {
|
||||
return SecurityContextHolder.getContext().getAuthentication();
|
||||
@@ -59,4 +69,9 @@ public class MethodSecurityServiceImpl implements MethodSecurityService {
|
||||
public String postHasPermission(String object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String postAnnotation(String object) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class NamespaceGlobalMethodSecurityExpressionHandlerTests extends BaseSpr
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler expressionHandler() {
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler()
|
||||
expressionHandler.permissionEvaluator = new PermissionEvaluator() {
|
||||
boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
|
||||
|
||||
+7
@@ -134,6 +134,10 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
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)
|
||||
@@ -345,6 +349,9 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
service.secured()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
and: "service with ROLE_USER allowed"
|
||||
service.securedUser() == null
|
||||
and:
|
||||
service.preAuthorize() == null
|
||||
service.jsr250() == null
|
||||
}
|
||||
|
||||
+3
-4
@@ -67,7 +67,7 @@ public class SampleEnableGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
@@ -97,15 +97,14 @@ public class SampleEnableGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler expressionHandler() {
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
|
||||
return expressionHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
|
||||
+12
-10
@@ -16,6 +16,7 @@
|
||||
package org.springframework.security.config.annotation.web
|
||||
|
||||
import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
|
||||
@@ -27,9 +28,13 @@ import spock.lang.Specification
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
class AbstractConfiguredSecurityBuilderTests extends Specification {
|
||||
class AbstractConfiguredSecurityBuilderTests extends BaseSpringSpec {
|
||||
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder()
|
||||
ConcreteAbstractConfiguredBuilder builder
|
||||
|
||||
def setup() {
|
||||
builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor)
|
||||
}
|
||||
|
||||
def "Null ObjectPostProcessor rejected"() {
|
||||
when:
|
||||
@@ -86,7 +91,7 @@ class AbstractConfiguredSecurityBuilderTests extends Specification {
|
||||
|
||||
def "getConfigurer with multi fails"() {
|
||||
setup:
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true)
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
|
||||
builder.apply(new DelegateConfigurer())
|
||||
builder.apply(new DelegateConfigurer())
|
||||
when:
|
||||
@@ -97,7 +102,7 @@ class AbstractConfiguredSecurityBuilderTests extends Specification {
|
||||
|
||||
def "removeConfigurer with multi fails"() {
|
||||
setup:
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true)
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
|
||||
builder.apply(new DelegateConfigurer())
|
||||
builder.apply(new DelegateConfigurer())
|
||||
when:
|
||||
@@ -110,7 +115,7 @@ class AbstractConfiguredSecurityBuilderTests extends Specification {
|
||||
setup:
|
||||
DelegateConfigurer c1 = new DelegateConfigurer()
|
||||
DelegateConfigurer c2 = new DelegateConfigurer()
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true)
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
|
||||
builder.apply(c1)
|
||||
builder.apply(c2)
|
||||
when:
|
||||
@@ -126,7 +131,7 @@ class AbstractConfiguredSecurityBuilderTests extends Specification {
|
||||
setup:
|
||||
DelegateConfigurer c1 = new DelegateConfigurer()
|
||||
DelegateConfigurer c2 = new DelegateConfigurer()
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true)
|
||||
ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
|
||||
builder.apply(c1)
|
||||
builder.apply(c2)
|
||||
when:
|
||||
@@ -150,10 +155,7 @@ class AbstractConfiguredSecurityBuilderTests extends Specification {
|
||||
|
||||
private static class ConcreteConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> { }
|
||||
|
||||
private static class ConcreteAbstractConfiguredBuilder extends AbstractConfiguredSecurityBuilder<Object, ConcreteAbstractConfiguredBuilder> {
|
||||
|
||||
public ConcreteAbstractConfiguredBuilder() {
|
||||
}
|
||||
private class ConcreteAbstractConfiguredBuilder extends AbstractConfiguredSecurityBuilder<Object, ConcreteAbstractConfiguredBuilder> {
|
||||
|
||||
public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
super(objectPostProcessor);
|
||||
|
||||
+3
-3
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web;
|
||||
|
||||
import static org.springframework.security.config.annotation.web.AbstractRequestMatcherConfigurer.RequestMatchers.*
|
||||
import static org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry.RequestMatchers.*
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.web.util.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
|
||||
import spock.lang.Specification;
|
||||
|
||||
|
||||
+3
-3
@@ -91,7 +91,7 @@ public class SampleWebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
@EnableWebSecurity
|
||||
public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) {
|
||||
protected void configure(AuthenticationManagerBuilder auth) {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
@@ -179,7 +179,7 @@ public class SampleWebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth) {
|
||||
protected void configure(AuthenticationManagerBuilder auth) {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
@@ -276,7 +276,7 @@ public class SampleWebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
@EnableWebSecurity
|
||||
public static class SampleMultiHttpSecurityConfig {
|
||||
@Autowired
|
||||
public void registerAuthentication(AuthenticationManagerBuilder auth) {
|
||||
protected void configure(AuthenticationManagerBuilder auth) {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
|
||||
+60
-13
@@ -27,8 +27,12 @@ import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.Ordered
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator
|
||||
import org.springframework.core.annotation.Order
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent
|
||||
@@ -41,7 +45,7 @@ import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
@@ -77,10 +81,10 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
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',
|
||||
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block',
|
||||
'X-CSRF-TOKEN' : csrfToken.token]
|
||||
'Expires' : '0',
|
||||
'X-XSS-Protection' : '1; mode=block']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@@ -88,8 +92,7 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
static class HeadersArePopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
@@ -113,8 +116,7 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
static class WebAsyncPopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
@@ -126,7 +128,7 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "AuthenticationEventPublisher is registered for Web registerAuthentication"() {
|
||||
def "AuthenticationEventPublisher is registered for Web configure(AuthenticationManagerBuilder auth)"() {
|
||||
when:
|
||||
loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
|
||||
then:
|
||||
@@ -151,8 +153,7 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
@@ -235,14 +236,26 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
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
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
}
|
||||
|
||||
static class MyFilter extends OncePerRequestFilter {
|
||||
private UserDetailsService userDetailsService
|
||||
public MyFilter(UserDetailsService uds) {
|
||||
@@ -253,4 +266,38 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
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
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter {
|
||||
static AuthenticationTrustResolver 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
|
||||
}
|
||||
|
||||
class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {}
|
||||
}
|
||||
|
||||
+1
-2
@@ -61,8 +61,7 @@ public class WebSecurityConfigurerAdapterTestsConfigs {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerAuthentication(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication().and()
|
||||
.jdbcAuthentication()
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.builders;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.BaseWebConfig;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class DisableUseExpressionsConfig extends BaseWebConfig {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// This config is also on UrlAuthorizationConfigurer javadoc
|
||||
http
|
||||
.apply(new UrlAuthorizationConfigurer<HttpSecurity>()).getRegistry()
|
||||
.antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
.antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
.anyRequest().hasRole("USER");
|
||||
}
|
||||
}
|
||||
+9
-16
@@ -50,8 +50,8 @@ import org.springframework.security.web.savedrequest.NullRequestCache
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
|
||||
import org.springframework.security.web.session.SessionManagementFilter
|
||||
import org.springframework.security.web.util.RegexRequestMatcher
|
||||
import org.springframework.security.web.util.RequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
|
||||
/**
|
||||
* Tests to verify that all the functionality of <http> attributes is present
|
||||
@@ -331,16 +331,21 @@ public class NamespaceHttpTests extends BaseSpringSpec {
|
||||
// http@pattern is not available (instead see the tests http@request-matcher-ref ant or http@request-matcher-ref regex)
|
||||
|
||||
def "http@realm"() {
|
||||
when:
|
||||
setup:
|
||||
loadConfig(RealmConfig)
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
findFilter(BasicAuthenticationFilter).authenticationEntryPoint.realmName == "RealmConfig"
|
||||
response.getHeader("WWW-Authenticate") == 'Basic realm="RealmConfig"'
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class RealmConfig extends BaseWebConfig {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic().realmName("RealmConfig")
|
||||
}
|
||||
}
|
||||
@@ -496,16 +501,4 @@ public class NamespaceHttpTests extends BaseSpringSpec {
|
||||
findFilter(FilterSecurityInterceptor).securityMetadataSource.class == DefaultFilterInvocationSecurityMetadataSource
|
||||
findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [RoleVoter, AuthenticatedVoter]
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class DisableUseExpressionsConfig extends BaseWebConfig {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(new UrlAuthorizationConfigurer())
|
||||
.antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
.antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
.anyRequest().hasRole("USER")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -32,8 +32,7 @@ public abstract class BaseWebConfig extends WebSecurityConfigurerAdapter {
|
||||
BaseWebConfig() {
|
||||
}
|
||||
|
||||
protected void registerAuthentication(
|
||||
AuthenticationManagerBuilder auth) throws Exception {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER").and()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user