Compare commits
64 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 |
@@ -19,3 +19,4 @@ build/
|
||||
*.iws
|
||||
.gradle/
|
||||
atlassian-ide-plugin.xml
|
||||
/samples
|
||||
|
||||
+18
-24
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</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.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.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.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -132,7 +126,7 @@
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<version>2.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,19 +144,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.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.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.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
@@ -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
|
||||
|
||||
+14
-20
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</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.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -132,13 +126,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.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
|
||||
}
|
||||
+9
-6
@@ -5,11 +5,12 @@ buildscript {
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
|
||||
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('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')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +25,13 @@ 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-snapshot" }
|
||||
mavenCentral()
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
maven { url "http://repo.terracotta.org/maven2/" }
|
||||
}
|
||||
@@ -51,7 +54,7 @@ sonarRunner {
|
||||
}
|
||||
|
||||
// Set up different subproject lists for individual configuration
|
||||
ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && 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
|
||||
@@ -76,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
|
||||
@@ -106,7 +109,7 @@ configure(coreModuleProjects) {
|
||||
configurations.spring4TestRuntime {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.springframework') {
|
||||
details.useVersion '4.0.0.RC1'
|
||||
details.useVersion spring4Version
|
||||
}
|
||||
if (details.requested.name == 'ehcache') {
|
||||
details.useVersion '2.6.5'
|
||||
@@ -185,5 +188,5 @@ artifacts {
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.8'
|
||||
gradleVersion = '1.10-rc-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
|
||||
+15
-21
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</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.CI-SNAPSHOT</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.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.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.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -52,7 +52,7 @@ dependencies {
|
||||
}
|
||||
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion",
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:2.2"
|
||||
}
|
||||
|
||||
@@ -60,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
|
||||
|
||||
+30
-36
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</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.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -108,49 +102,49 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</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.CI-SNAPSHOT</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.CI-SNAPSHOT</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.4.RELEASE</version>
|
||||
<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.4.RELEASE</version>
|
||||
<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.4.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.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -172,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>
|
||||
@@ -256,6 +244,12 @@
|
||||
<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>
|
||||
@@ -331,25 +325,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+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
-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);
|
||||
|
||||
+4
-1
@@ -280,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) {
|
||||
|
||||
+1
-1
@@ -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 WebMvcSecurityConfiguration} 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.WebMvcSecurityConfiguration"} : new String[] {};
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -34,6 +34,7 @@ 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;
|
||||
@@ -87,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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ 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;
|
||||
@@ -53,6 +54,7 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Order(100)
|
||||
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {
|
||||
private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class);
|
||||
|
||||
|
||||
+78
-6
@@ -15,14 +15,22 @@
|
||||
*/
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
+22
-1
@@ -42,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;
|
||||
@@ -66,6 +67,7 @@ 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>
|
||||
@@ -83,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;
|
||||
@@ -365,6 +368,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
}
|
||||
http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy());
|
||||
http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -375,7 +379,7 @@ 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) {
|
||||
@@ -391,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}
|
||||
|
||||
+5
-4
@@ -27,6 +27,7 @@ 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.matcher.RequestMatcher;
|
||||
@@ -48,10 +49,10 @@ import org.springframework.util.Assert;
|
||||
* <pre>
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .apply(new UrlAuthorizationConfigurer()).getRegistry()
|
||||
* .antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
* .antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
* .anyRequest().hasRole("USER")
|
||||
* .apply(new UrlAuthorizationConfigurer<HttpSecurity>()).getRegistry()
|
||||
* .antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
* .antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
* .anyRequest().hasRole("USER");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
|
||||
+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 {
|
||||
}
|
||||
+5
-3
@@ -13,12 +13,13 @@
|
||||
* 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;
|
||||
@@ -38,7 +39,8 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
* @since 3.2
|
||||
*/
|
||||
@Configuration
|
||||
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
@EnableWebSecurity
|
||||
public class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(
|
||||
@@ -48,6 +50,6 @@ class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public RequestDataValueProcessor requestDataValueProcessor() {
|
||||
return CsrfRequestDataValueProcessor.create();
|
||||
return new CsrfRequestDataValueProcessor();
|
||||
}
|
||||
}
|
||||
+56
-4
@@ -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,12 +53,12 @@ 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());
|
||||
if(webmvcPresent) {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(CsrfRequestDataValueProcessor.class);
|
||||
beanDefinition.setFactoryMethodName("create");
|
||||
BeanComponentDefinition componentDefinition =
|
||||
new BeanComponentDefinition(beanDefinition, REQUEST_DATA_VALUE_PROCESSOR);
|
||||
pc.registerBeanComponent(componentDefinition);
|
||||
@@ -58,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() {
|
||||
|
||||
+15
-6
@@ -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() {
|
||||
|
||||
+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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+3
-3
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
+3
-2
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
+31
@@ -19,6 +19,7 @@ import static org.fest.assertions.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
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.Bean
|
||||
@@ -270,4 +271,34 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -27,6 +27,9 @@ 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
|
||||
@@ -283,4 +286,18 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
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 {}
|
||||
}
|
||||
|
||||
+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");
|
||||
}
|
||||
}
|
||||
-12
@@ -501,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()).getRegistry()
|
||||
.antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
.antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
.anyRequest().hasRole("USER")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.sec2377;
|
||||
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.web.configuration.sec2377.a.*
|
||||
import org.springframework.security.config.annotation.web.configuration.sec2377.b.*
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||
|
||||
public class Sec2377Tests extends BaseSpringSpec {
|
||||
|
||||
def "SEC-2377: Error reporting with multiple EnableWebSecurity from other packages"() {
|
||||
when:
|
||||
AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()
|
||||
parent.register(Sec2377AConfig)
|
||||
parent.refresh()
|
||||
|
||||
AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()
|
||||
child.register(Sec2377BConfig)
|
||||
child.parent = parent
|
||||
child.refresh()
|
||||
then:
|
||||
noExceptionThrown();
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.sec2377.a;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class Sec2377AConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
}
|
||||
+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.web.configuration.sec2377.b;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class Sec2377BConfig {
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.configurers;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.event.AuthorizedEvent;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class AuthorizedRequestsWithPostProcessorConfig extends WebSecurityConfigurerAdapter {
|
||||
static ApplicationListener<AuthorizedEvent> AL;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().permitAll()
|
||||
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
|
||||
public <O extends FilterSecurityInterceptor> O postProcess(
|
||||
O fsi) {
|
||||
fsi.setPublishAuthorizationSuccess(true);
|
||||
return fsi;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApplicationListener<AuthorizedEvent> applicationListener() {
|
||||
return AL;
|
||||
}
|
||||
}
|
||||
+46
-13
@@ -18,19 +18,21 @@ package org.springframework.security.config.annotation.web.configurers
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
import org.springframework.security.web.csrf.CsrfFilter
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor
|
||||
|
||||
import spock.lang.Unroll;
|
||||
import spock.lang.Unroll
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -69,7 +71,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvcSecurity
|
||||
static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@@ -100,6 +102,37 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
|
||||
setup:
|
||||
loadConfig(InvalidSessionUrlConfig)
|
||||
request.session.clearAttributes()
|
||||
request.setParameter("_csrf","abc")
|
||||
request.method = "POST"
|
||||
when: "No existing expected CsrfToken (session times out) and a POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the session timeout page page"
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/error/sessionError"
|
||||
when: "Existing expected CsrfToken and a POST (invalid token provided)"
|
||||
response = new MockHttpServletResponse()
|
||||
request = new MockHttpServletRequest(session: request.session, method:'POST')
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "Access Denied occurs"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf().and()
|
||||
.sessionManagement()
|
||||
.invalidSessionUrl("/error/sessionError")
|
||||
}
|
||||
}
|
||||
|
||||
def "csrf requireCsrfProtectionMatcher"() {
|
||||
setup:
|
||||
RequireCsrfProtectionMatcherConfig.matcher = Mock(RequestMatcher)
|
||||
@@ -158,7 +191,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
def "csrf clears on login"() {
|
||||
setup:
|
||||
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
|
||||
1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
|
||||
loadConfig(CsrfTokenRepositoryConfig)
|
||||
request.method = "POST"
|
||||
request.getSession()
|
||||
@@ -169,7 +202,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.redirectedUrl == "/"
|
||||
1 * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
|
||||
(1.._) * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -282,7 +315,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
when: "CSRF passes and our session times out"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the login page"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "http://localhost/login"
|
||||
when: "authenticate successfully"
|
||||
@@ -293,7 +326,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
request.method = "POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/"
|
||||
}
|
||||
@@ -308,7 +341,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
when: "CSRF passes and our session times out"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the login page"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "http://localhost/login"
|
||||
when: "authenticate successfully"
|
||||
@@ -319,7 +352,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
request.method = "POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to original URL since it was a GET"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "http://localhost/some-url"
|
||||
}
|
||||
|
||||
+13
@@ -20,7 +20,9 @@ import static org.springframework.security.config.annotation.web.configurers.Exp
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.event.AuthorizedEvent
|
||||
import org.springframework.security.access.vote.AffirmativeBased
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
@@ -462,4 +464,15 @@ public class ExpressionUrlAuthorizationConfigurerTests extends BaseSpringSpec {
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
def "AuthorizedRequests withPostProcessor"() {
|
||||
setup:
|
||||
ApplicationListener al = Mock()
|
||||
AuthorizedRequestsWithPostProcessorConfig.AL = al
|
||||
loadConfig(AuthorizedRequestsWithPostProcessorConfig)
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then:
|
||||
1 * al.onApplicationEvent(_ as AuthorizedEvent)
|
||||
}
|
||||
}
|
||||
|
||||
+23
-1
@@ -174,6 +174,28 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
response.redirectedUrl == "http://localhost/some-url"
|
||||
}
|
||||
|
||||
def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'csrf'()
|
||||
'session-management'('invalid-session-url': '/error/sessionError')
|
||||
}
|
||||
createAppContext()
|
||||
request.setParameter("_csrf","abc")
|
||||
request.method = "POST"
|
||||
when: "No existing expected CsrfToken (session times out) and a POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the session timeout page page"
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/error/sessionError"
|
||||
when: "Existing expected CsrfToken and a POST (invalid token provided)"
|
||||
response = new MockHttpServletResponse()
|
||||
request = new MockHttpServletRequest(session: request.session, method:'POST')
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "Access Denied occurs"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
|
||||
def "csrf requireCsrfProtectionMatcher"() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
@@ -235,7 +257,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
verify(repo).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
|
||||
verify(repo, atLeastOnce()).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
|
||||
}
|
||||
|
||||
def "csrf clears on logout"() {
|
||||
|
||||
+26
@@ -17,7 +17,10 @@ package org.springframework.security.config.http;
|
||||
|
||||
|
||||
import java.security.Principal
|
||||
|
||||
import javax.servlet.Filter
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.BeansException
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
|
||||
@@ -98,4 +101,27 @@ class InterceptUrlConfigTests extends AbstractHttpConfigTests {
|
||||
attrsPost.size() == 1
|
||||
attrsPost.contains(new SecurityConfig("ROLE_USER"))
|
||||
}
|
||||
|
||||
def "SEC-2355: intercept-url support patch"() {
|
||||
setup:
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET')
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
MockFilterChain chain = new MockFilterChain()
|
||||
xml.http() {
|
||||
'http-basic'()
|
||||
'intercept-url'(pattern: '/**', 'method':'PATCH',access: 'ROLE_ADMIN')
|
||||
}
|
||||
createAppContext()
|
||||
when: 'Method other than PATCH is used'
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: 'The response is OK'
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
when: 'Method of PATCH is used'
|
||||
request = new MockHttpServletRequest(method:'PATCH')
|
||||
response = new MockHttpServletResponse()
|
||||
chain = new MockFilterChain()
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: 'The response is unauthorized'
|
||||
response.status == HttpServletResponse.SC_UNAUTHORIZED
|
||||
}
|
||||
}
|
||||
+31
-1
@@ -17,6 +17,10 @@ package org.springframework.security.config.http
|
||||
|
||||
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
|
||||
import javax.sql.DataSource
|
||||
|
||||
import org.springframework.beans.FatalBeanException
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
|
||||
import org.springframework.security.TestDataSource
|
||||
import org.springframework.security.authentication.ProviderManager
|
||||
@@ -26,7 +30,7 @@ import org.springframework.security.util.FieldUtils
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
|
||||
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl
|
||||
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices
|
||||
@@ -154,6 +158,32 @@ class RememberMeConfigTests extends AbstractHttpConfigTests {
|
||||
rememberMeServices().tokenValiditySeconds == -1
|
||||
}
|
||||
|
||||
def 'remember-me@token-validity-seconds denies for persistent implementation'() {
|
||||
setup:
|
||||
httpAutoConfig () {
|
||||
'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'dataSource' : 'dataSource')
|
||||
}
|
||||
mockBean(DataSource)
|
||||
when:
|
||||
createAppContext(AUTH_PROVIDER_XML)
|
||||
then:
|
||||
thrown(FatalBeanException)
|
||||
}
|
||||
|
||||
def 'SEC-2165: remember-me@token-validity-seconds allows property placeholders'() {
|
||||
when:
|
||||
httpAutoConfig () {
|
||||
'remember-me'('key': 'ourkey', 'token-validity-seconds':'${security.rememberme.ttl}')
|
||||
}
|
||||
xml.'b:bean'(class: PropertyPlaceholderConfigurer.name) {
|
||||
'b:property'(name:'properties', value:'security.rememberme.ttl=30')
|
||||
}
|
||||
|
||||
createAppContext(AUTH_PROVIDER_XML)
|
||||
then:
|
||||
rememberMeServices().tokenValiditySeconds == 30
|
||||
}
|
||||
|
||||
def rememberMeSecureCookieAttributeIsSetCorrectly() {
|
||||
httpAutoConfig () {
|
||||
'remember-me'('key': 'ourkey', 'use-secure-cookie':'true')
|
||||
|
||||
@@ -34,7 +34,7 @@ public class DataSourcePopulator implements InitializingBean {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(template, "dataSource required");
|
||||
|
||||
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);");
|
||||
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);");
|
||||
template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
|
||||
template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
|
||||
|
||||
|
||||
+13
-16
@@ -16,30 +16,21 @@
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.powermock.api.mockito.PowerMockito.spy;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({ClassUtils.class})
|
||||
public class CsrfConfigurerNoWebMvcTests {
|
||||
ConfigurableApplicationContext context;
|
||||
|
||||
@@ -52,24 +43,30 @@ public class CsrfConfigurerNoWebMvcTests {
|
||||
|
||||
@Test
|
||||
public void missingDispatcherServletPreventsCsrfRequestDataValueProcessor() {
|
||||
spy(ClassUtils.class);
|
||||
when(ClassUtils.isPresent(eq("org.springframework.web.servlet.DispatcherServlet"), any(ClassLoader.class))).thenReturn(false);
|
||||
|
||||
loadContext(CsrfDefaultsConfig.class);
|
||||
loadContext(EnableWebConfig.class);
|
||||
|
||||
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDispatcherServletPreventsCsrfRequestDataValueProcessor() {
|
||||
loadContext(CsrfDefaultsConfig.class);
|
||||
loadContext(EnableWebMvcConfig.class);
|
||||
|
||||
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isTrue();
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class CsrfDefaultsConfig extends WebSecurityConfigurerAdapter {
|
||||
static class EnableWebConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebMvcSecurity
|
||||
@Configuration
|
||||
static class EnableWebMvcConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ dependencies {
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
powerMockDependencies
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion",
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:$cglibVersion"
|
||||
}
|
||||
|
||||
|
||||
+22
-28
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-core</name>
|
||||
<description>spring-security-core</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</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -88,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -122,14 +116,14 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<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.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -151,12 +145,6 @@
|
||||
<version>3.2</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>
|
||||
@@ -169,6 +157,12 @@
|
||||
<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>
|
||||
@@ -220,7 +214,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+61
@@ -12,30 +12,91 @@ import org.springframework.security.core.Authentication;
|
||||
*/
|
||||
public interface SecurityExpressionOperations {
|
||||
|
||||
/**
|
||||
* Gets the {@link Authentication} used for evaluating the expressions
|
||||
* @return the {@link Authentication} for evaluating the expressions
|
||||
*/
|
||||
Authentication getAuthentication();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has a particular authority within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAuthority(String)}.
|
||||
* @param authority the authority to test (i.e. "ROLE_USER")
|
||||
* @return true if the authority is found, else false
|
||||
*/
|
||||
boolean hasAuthority(String authority);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has any of the specified authorities within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAnyRole(String...)}.
|
||||
* @param authorities the authorities to test (i.e. "ROLE_USER", "ROLE_ADMIN")
|
||||
* @return true if any of the authorities is found, else false
|
||||
*/
|
||||
boolean hasAnyAuthority(String... authorities);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has a particular authority within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAuthority(String)}.
|
||||
* @param authority the authority to test (i.e. "ROLE_USER")
|
||||
* @return true if the authority is found, else false
|
||||
*/
|
||||
boolean hasRole(String role);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has any of the specified authorities within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAnyAuthority(String...)}.
|
||||
* @param authorities the authorities to test (i.e. "ROLE_USER", "ROLE_ADMIN")
|
||||
* @return true if any of the authorities is found, else false
|
||||
*/
|
||||
boolean hasAnyRole(String... roles);
|
||||
|
||||
/**
|
||||
* Always grants access.
|
||||
* @return true
|
||||
*/
|
||||
boolean permitAll();
|
||||
|
||||
/**
|
||||
* Always denies access
|
||||
* @return false
|
||||
*/
|
||||
boolean denyAll();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} is anonymous
|
||||
* @return true if the user is anonymous, else false
|
||||
*/
|
||||
boolean isAnonymous();
|
||||
|
||||
/**
|
||||
* Determines ifthe {@link #getAuthentication()} is authenticated
|
||||
* @return true if the {@link #getAuthentication()} is authenticated, else false
|
||||
*/
|
||||
boolean isAuthenticated();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} was authenticated using remember me
|
||||
* @return true if the {@link #getAuthentication()} authenticated using remember me, else false
|
||||
*/
|
||||
boolean isRememberMe();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} authenticated without the use of remember me
|
||||
* @return true if the {@link #getAuthentication()} authenticated without the use of remember me, else false
|
||||
*/
|
||||
boolean isFullyAuthenticated();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has permission to access the target given the permission
|
||||
* @param target the target domain object to check permission on
|
||||
* @param permission the permission to check on the domain object (i.e. "read", "write", etc).
|
||||
* @return true if permission is granted to the {@link #getAuthentication()}, else false
|
||||
*/
|
||||
boolean hasPermission(Object target, Object permission);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has permission to access the domain object with a given id, type, and permission.
|
||||
* @param targetId the identifier of the domain object to determine access
|
||||
* @param targetType the type (i.e. com.example.domain.Message)
|
||||
* @param permission the perission to check on the domain object (i.e. "read", "write", etc)
|
||||
* @return true if permission is granted to the {@link #getAuthentication()}, else false
|
||||
*/
|
||||
boolean hasPermission(Object targetId, String targetType, Object permission);
|
||||
|
||||
}
|
||||
|
||||
+11
-4
@@ -5,7 +5,6 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
@@ -38,11 +37,15 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
|
||||
public final String delete = "delete";
|
||||
public final String admin = "administration";
|
||||
|
||||
public SecurityExpressionRoot(Authentication a) {
|
||||
if (a == null) {
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param authentication the {@link Authentication} to use. Cannot be null.
|
||||
*/
|
||||
public SecurityExpressionRoot(Authentication authentication) {
|
||||
if (authentication == null) {
|
||||
throw new IllegalArgumentException("Authentication object cannot be null");
|
||||
}
|
||||
this.authentication = a;
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
public final boolean hasAuthority(String authority) {
|
||||
@@ -97,6 +100,10 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
|
||||
return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to access {@link Authentication#getPrincipal()} from {@link #getAuthentication()}
|
||||
* @return
|
||||
*/
|
||||
public Object getPrincipal() {
|
||||
return authentication.getPrincipal();
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ package org.springframework.security.authentication;
|
||||
* Thrown if an authentication request could not be processed due to a system problem that occurred internally. It
|
||||
* differs from {@link AuthenticationServiceException} in that it would not be thrown if an external system has an
|
||||
* internal error or failure. This ensures that we can handle errors that are within our control distinctly from errors
|
||||
* of other systems. The advantage to this distinction is that the unrusted external system should not be able to fill
|
||||
* of other systems. The advantage to this distinction is that the untrusted external system should not be able to fill
|
||||
* up logs and cause excessive IO. However, an internal system should report errors.
|
||||
* </p>
|
||||
* <p>
|
||||
|
||||
@@ -163,6 +163,9 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
|
||||
prepareException(e, authentication);
|
||||
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
|
||||
throw e;
|
||||
} catch (InternalAuthenticationServiceException e) {
|
||||
prepareException(e, authentication);
|
||||
throw e;
|
||||
} catch (AuthenticationException e) {
|
||||
lastException = e;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,7 @@ public class SpringSecurityCoreVersion {
|
||||
*/
|
||||
public static final long SERIAL_VERSION_UID = 320L;
|
||||
|
||||
static final String SPRING_MAJOR_VERSION = "3";
|
||||
|
||||
static final String MIN_SPRING_VERSION = "3.2.4.RELEASE";
|
||||
static final String MIN_SPRING_VERSION = "3.2.6.RELEASE";
|
||||
|
||||
static {
|
||||
performVersionChecks();
|
||||
@@ -49,18 +47,20 @@ public class SpringSecurityCoreVersion {
|
||||
}
|
||||
|
||||
logger.info("You are running with Spring Security Core " + version);
|
||||
if (!springVersion.startsWith(SPRING_MAJOR_VERSION)) {
|
||||
logger.warn("*** Spring Major version '" + SPRING_MAJOR_VERSION +
|
||||
"' expected, but you are running with version: " + springVersion +
|
||||
". Please check your classpath for unwanted jar files.");
|
||||
}
|
||||
|
||||
if (springVersion.compareTo(MIN_SPRING_VERSION) < 0) {
|
||||
logger.warn("**** You are advised to use Spring " + MIN_SPRING_VERSION +
|
||||
" or later with this version. You are running: " + springVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable if springVersion and springSecurityVersion are the same to allow
|
||||
* working with Uber Jars.
|
||||
*
|
||||
* @param springVersion
|
||||
* @param springSecurityVersion
|
||||
* @return
|
||||
*/
|
||||
private static boolean disableChecks(String springVersion, String springSecurityVersion) {
|
||||
if(springVersion == null || springVersion.equals(springSecurityVersion)) {
|
||||
return true;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PopulatedDatabase {
|
||||
JdbcTemplate template = new JdbcTemplate(dataSource);
|
||||
|
||||
template.execute(
|
||||
"CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL)");
|
||||
"CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL)");
|
||||
template.execute(
|
||||
"CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME))");
|
||||
template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY)");
|
||||
|
||||
+14
@@ -287,6 +287,20 @@ public class ProviderManagerTests {
|
||||
verify(publisher).publishAuthenticationFailure(expected, authReq);
|
||||
}
|
||||
|
||||
// SEC-2367
|
||||
@Test
|
||||
public void providerThrowsInternalAuthenticationServiceException() {
|
||||
InternalAuthenticationServiceException expected = new InternalAuthenticationServiceException("Expected");
|
||||
ProviderManager mgr = new ProviderManager(
|
||||
Arrays.asList(createProviderWhichThrows(expected), createProviderWhichThrows(new BadCredentialsException("Oops"))), null);
|
||||
final Authentication authReq = mock(Authentication.class);
|
||||
|
||||
try {
|
||||
mgr.authenticate(authReq);
|
||||
fail("Expected Exception");
|
||||
} catch(InternalAuthenticationServiceException success) {}
|
||||
}
|
||||
|
||||
private AuthenticationProvider createProviderWhichThrows(final AuthenticationException e) {
|
||||
AuthenticationProvider provider = mock(AuthenticationProvider.class);
|
||||
when(provider.supports(any(Class.class))).thenReturn(true);
|
||||
|
||||
+17
-2
@@ -17,6 +17,7 @@ package org.springframework.security.core;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
@@ -24,7 +25,9 @@ import static org.powermock.api.mockito.PowerMockito.spy;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.*;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
@@ -110,7 +113,19 @@ public class SpringSecurityCoreVersionTests {
|
||||
|
||||
performChecks();
|
||||
|
||||
verify(logger, times(2)).warn(any());
|
||||
verify(logger, times(1)).warn(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noWarnIfSpringVersionLarger() throws Exception {
|
||||
spy(SpringSecurityCoreVersion.class);
|
||||
spy(SpringVersion.class);
|
||||
when(SpringSecurityCoreVersion.getVersion()).thenReturn("3.2.0.RELEASE");
|
||||
when(SpringVersion.getVersion()).thenReturn("4.0.0.RELEASE");
|
||||
|
||||
performChecks();
|
||||
|
||||
verify(logger, never()).warn(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+10
-16
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-crypto</name>
|
||||
<description>spring-security-crypto</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,17 +42,11 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -101,7 +95,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -25,6 +25,8 @@ project('manual') {
|
||||
doctype: 'book',
|
||||
numbered: '',
|
||||
'spring-security-version' : project.version,
|
||||
'spring-version' : springVersion,
|
||||
'spring4-version' : spring4Version,
|
||||
revnumber : project.version
|
||||
]
|
||||
]
|
||||
|
||||
+39
-29
@@ -1,36 +1,46 @@
|
||||
apply plugin: 'asciidoctor'
|
||||
|
||||
import org.asciidoctor.gradle.*
|
||||
|
||||
file("src/asciidoc").eachFileMatch(~/.*\.asc/) { file->
|
||||
task "asciidoctor-${file.name}"(type: AsciidoctorTask) {
|
||||
sourceDocumentName = file
|
||||
options = [
|
||||
eruby: 'erubis',
|
||||
eruby: 'erubis',
|
||||
attributes: [
|
||||
copycss : '',
|
||||
icons : 'font',
|
||||
'source-highlighter': 'prettify',
|
||||
sectanchors : '',
|
||||
toc2: '',
|
||||
idprefix: '',
|
||||
idseparator: '-',
|
||||
doctype: 'book',
|
||||
'spring-security-version' : project.version,
|
||||
revnumber : project.version
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
task asciidoctor {
|
||||
group = 'Documentation'
|
||||
description = "Generates the asciidoc for $project.name"
|
||||
dependsOn tasks.matching { t -> t.name.startsWith('asciidoctor-') }
|
||||
asciidoctor {
|
||||
baseDir = file('src/asciidoc')
|
||||
options = [
|
||||
eruby: 'erubis',
|
||||
eruby: 'erubis',
|
||||
attributes: [
|
||||
copycss : '',
|
||||
icons : 'font',
|
||||
'source-highlighter': 'prettify',
|
||||
sectanchors : '',
|
||||
toc: '',
|
||||
'toc-placement' : 'preamble',
|
||||
idprefix: '',
|
||||
idseparator: '-',
|
||||
doctype: 'book',
|
||||
'spring-security-version' : project.version,
|
||||
'download-url' : getDownloadUrl(),
|
||||
'include-maven-repository' : getMavenRepositoryInclude(),
|
||||
revnumber : project.version
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
ext.spec = copySpec {
|
||||
into ('guides') {
|
||||
from("$buildDir/asciidoctor/dist/html5/")
|
||||
from(asciidoctor.outputDir)
|
||||
exclude 'build', 'Guardfile'
|
||||
}
|
||||
}
|
||||
|
||||
def getDownloadUrl() {
|
||||
snapshotBuild ? "https://github.com/SpringSource/spring-security/archive/master.zip" : "https://github.com/spring-projects/spring-security/archive/${project.version}.zip"
|
||||
}
|
||||
|
||||
|
||||
def getMavenRepositoryInclude() {
|
||||
if(snapshotBuild) {
|
||||
return "_includes/maven-repository-snapshot.asc"
|
||||
} else if(releaseBuild) {
|
||||
return "_includes/maven-repository-release.asc"
|
||||
} else {
|
||||
return "_includes/maven-repository-milestone.asc"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,10 @@ require 'erb'
|
||||
|
||||
guard 'shell' do
|
||||
watch(/^.*\.asc$/) {|m|
|
||||
Asciidoctor.render_file(m[0], :to_dir => "build/", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'toc' => '', 'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'toc-placement' => 'preamble', 'spring-security-version' => '3.2.0.CI-SNAPSHOT', 'revnumber' => '3.2.0.CI-SNAPSHOT' })
|
||||
Asciidoctor.render_file(m[0], :to_dir => "build/", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'toc' => '', 'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'toc-placement' => 'preamble', 'revnumber' => '3.2.0.CI-SNAPSHOT',
|
||||
'spring-security-version' => '3.2.0.CI-SNAPSHOT',
|
||||
'download-url' => 'https://github.com/SpringSource/spring-security/archive/master.zip',
|
||||
'include-maven-repository' => '_includes/maven-repository-snapshot.asc' })
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
==== Basic authentication
|
||||
|
||||
We stated that Spring Security supported both form and HTTP Basic authentication, but how does Spring Security know when to use one and not the other? When using HTTP Basic, the user should receive a HTTP 401 response, but when we visit our application in our web browser we are redirected to a login page. The reason for this is because Spring Security uses content negotiation to determine which type of authentication to use. For example, if we specified our *Accept* header to be _application/json_ the result would be an HTTP 401.
|
||||
|
||||
You can use any tool you prefer (i.e. curl), but the instructions in this section we will use https://www.google.com/intl/en/chrome/browser/[Google Chrome] and the https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en[Postman - REST Client] to make an _application/json_ request to our application.
|
||||
|
||||
* Open Google Chrome and launch the Postman - REST Client extension
|
||||
* Enter _http://localhost:8080/sample/_ into the request URL field
|
||||
* Select the *Headers* button
|
||||
* Enter _Accept_ into the *Header* input
|
||||
* Enter _application/json_ into the *Value* field
|
||||
* Presss the *Send* button
|
||||
|
||||
Observe that we get an HTTP Status of 401 instead of our redirect. Now lets try entering our user name and password.
|
||||
|
||||
* Select the *Basic Auth* tab
|
||||
* Enter _user_ for the *Username*
|
||||
* Enter _password_ for the *Password*
|
||||
* Click the *Refresh headers* button
|
||||
* Click the *Send* button
|
||||
|
||||
This time you should see the HTML of our secured page.
|
||||
@@ -16,4 +16,4 @@ You should see an error message stating that authentication failed. Now try ente
|
||||
|
||||
You should now see the page that we wanted to secure.
|
||||
|
||||
NOTE: The reason we can successfully authenticate with *Username* _user_ and *Password* _password_ is because that is what we configured in our <<security-config-java,`SecurityConfig`>>.
|
||||
NOTE: The reason we can successfully authenticate with *Username* _user_ and *Password* _password_ is because that is what we configured in our <<security-config-java,SecurityConfig>>.
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
== Securing the application
|
||||
|
||||
Before securing your application, it is important to ensure that the existing application works as we did in <<running-the-{starter-appname}-application>>. Now that the application runs without security, we are ready to add security to our application. This section demonstrates the minimal steps to add Spring Security to a Spring MVC application.
|
||||
Before securing your application, it is important to ensure that the existing application works as we did in <<running-the-{starter-appname}-application>>. Now that the application runs without security, we are ready to add security to our application. This section demonstrates the minimal steps to add Spring Security to our application.
|
||||
|
||||
=== Updating your dependencies
|
||||
|
||||
You will need to ensure you have added the dependencies. Spring Security milestones and release candidates are available in the https://github.com/SpringSource/spring-framework/wiki/SpringSource-repository-FAQ[Spring Milestone Repository]. In short, if you are using Maven and using a milestone or release candidates ensure you have the following repository in your pom.xml:
|
||||
include::../{include-maven-repository}[]
|
||||
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
<repositories>
|
||||
<!-- ... possibly other repository elements ... -->
|
||||
<repository>
|
||||
<id>spring-libs-milestone</id>
|
||||
<name>Spring Milestone Repository</name>
|
||||
<url>http://repo.springsource.org/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
|
||||
You will then need to include the Spring Security dependencies
|
||||
In order to use Spring Security you must add the necessary dependencies. For the sample we will add the following Spring Security dependencies:
|
||||
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
@@ -64,9 +51,8 @@ The next step is to create a Spring Security configuration.
|
||||
package org.springframework.security.samples.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.security.config.annotation.authentication.builders.*;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.*;
|
||||
|
||||
@Configuration
|
||||
@@ -83,7 +69,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
[[servlet-api-integration]]
|
||||
The <<security-config-java,`SecurityConfig`>> will:
|
||||
The <<security-config-java,SecurityConfig>> will:
|
||||
|
||||
* Require authentication to every URL in your application
|
||||
* Generate a login form for you
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
== Setting up the sample
|
||||
|
||||
This section outlines how to setup a workspace within STS so that you can follow along with this guide. The next section outlines generic steps for how to apply Spring Security to your existing application. While you could simply apply the steps to your existing application, we encourage you to follow along with this guide as is to reduce the complexity.
|
||||
|
||||
=== Obtaining the sample projects
|
||||
|
||||
There are multiple ways in which you can obtain the source. We have highlighted a few ways below:
|
||||
|
||||
* <<downloading-from-github>>
|
||||
* <<cloning-from-github>>
|
||||
|
||||
==== Downloading from github
|
||||
|
||||
You can download the source from github.
|
||||
|
||||
* https://github.com/SpringSource/spring-security/archive/master.zip[Development Version]
|
||||
* https://github.com/SpringSource/spring-security/releases[Released Versions]
|
||||
|
||||
Extract the zip to a known location and remember it as _SPRING_SECURITY_HOME_. You are now ready to <<import-the-{starter-appname}-sample-application>>
|
||||
|
||||
==== Cloning from github
|
||||
|
||||
If you wish you can also obtain the source by cloning from github. For example, if you have a git client installed you can type the following:
|
||||
|
||||
----
|
||||
cd ~/git/
|
||||
git clone https://github.com/SpringSource/spring-security.git
|
||||
----
|
||||
|
||||
In this example, the code will be placed at "~/git/spring-security". Remember this location as _SPRING_SECURITY_HOME_.
|
||||
|
||||
=== Import the {starter-appname} sample application
|
||||
|
||||
In oder to follow along, we encourage you to import the {starter-appname} sample application into your IDE. You may use any IDE you prefer, but the instructions in the guide will assume you are using Spring Tool Suite (STS).
|
||||
|
||||
TIP: The completed sample application can be found at _SPRING_SECURITY_HOME_/{completed-appname}
|
||||
|
||||
* If you do not have STS installed, download STS from http://www.springsource.org/spring-tool-suite-download For performance reasons, we prefer the release based on Eclipse Juno.
|
||||
* Start STS and import the sample applications into STS using the following steps:
|
||||
** *File->Import*
|
||||
** *Existing Maven Projects*
|
||||
** Click *Next >*
|
||||
** Click *Browse...*
|
||||
** Navigate to the samples (i.e. _SPRING_SECURITY_HOME_/samples/{starter-appname}) and click *OK*
|
||||
** Click *Finish*
|
||||
|
||||
=== Running the {starter-appname} application
|
||||
|
||||
In the following exerecise we will be modifying the _spring-security-samples-{starter-appname}_ application. Before we make any changes, it is best to verify that the sample works properly. Perform the following steps to ensure that _spring-security-samples-{starter-appname}_ works.
|
||||
|
||||
* Right click on the _spring-security-samples-{starter-appname}_ application
|
||||
* Select *Run As->Run on Server*
|
||||
* Select the latest tc Server (i.e. v2.9)
|
||||
* Click *Finish*
|
||||
|
||||
include::{verify-starter-app-include}[]
|
||||
|
||||
Once you have verified the application runs, stop the application server using the following steps:
|
||||
|
||||
* In the Servers view select the latest tc Server
|
||||
* Click the stop button (a red square) to stop the application server
|
||||
@@ -1 +0,0 @@
|
||||
A page stating *TODO Secure this* should be displayed at http://localhost:8080/sample/
|
||||
@@ -1,5 +0,0 @@
|
||||
Verify the application is working:
|
||||
|
||||
* A page displaying a user's inbox can be seen at http://localhost:8080/sample/
|
||||
* Try clicking on the Compose link and creating a message. The message details should be displayed.
|
||||
* Now click on the Inbox link and see the message listed. You can click on the summary link to see the details displayed again.
|
||||
@@ -0,0 +1,14 @@
|
||||
In order to resolve Spring Security milestones and release candidates add the Spring Milestone repository. For our example, the repository has already been added for you. In the event you were working on another application, you would need to ensure you add the following to your pom:
|
||||
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
<repositories>
|
||||
<!-- ... possibly other repository elements ... -->
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<name>Spring Milestone Repository</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
@@ -0,0 +1 @@
|
||||
Spring Security GA releases are included within Maven Central, so no additional Maven repositories are necessary.
|
||||
@@ -0,0 +1,14 @@
|
||||
In order to resolve Spring Security SNAPSHOT dependencies add the Spring Snapshot repository. For our example, the repository has already been added for you. In the event you were working on another application, you would need to ensure you add the following to your pom:
|
||||
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
<repositories>
|
||||
<!-- ... possibly other repository elements ... -->
|
||||
<repository>
|
||||
<id>spring-snapshot</id>
|
||||
<name>Spring Snapshot Repository</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
----
|
||||
@@ -0,0 +1,40 @@
|
||||
////
|
||||
|
||||
Variables:
|
||||
|
||||
starter-appname: the name of the module users should start with to complete the excercise
|
||||
completed-appname: the name of the module that contains the completed application
|
||||
download-url: the URL to download the Spring Security distribution
|
||||
////
|
||||
|
||||
== Setting up the sample
|
||||
|
||||
This section outlines how to setup a workspace within https://spring.io/tools/sts[Spring Tool Suite (STS)] so that you can follow along with this guide. The next section outlines generic steps for how to apply Spring Security to your existing application. While you could simply apply the steps to your existing application, we encourage you to follow along with this guide as is to reduce the complexity.
|
||||
|
||||
=== Obtaining the sample projects
|
||||
|
||||
Extract the {download-url}[Spring Security Distribution] to a known location and remember it as _SPRING_SECURITY_HOME_.
|
||||
|
||||
=== Import the {starter-appname} sample application
|
||||
|
||||
In order to follow along, we encourage you to import the {starter-appname} sample application into your IDE. You may use any IDE you prefer, but the instructions in the guide will assume you are using Spring Tool Suite (STS).
|
||||
|
||||
TIP: The completed sample application can be found at _SPRING_SECURITY_HOME_/samples/{completed-appname}
|
||||
|
||||
* If you do not have STS installed, download STS from https://spring.io/tools
|
||||
* Start STS and import the sample applications into STS using the following steps:
|
||||
** *File->Import*
|
||||
** *Existing Maven Projects*
|
||||
** Click *Next >*
|
||||
** Click *Browse...*
|
||||
** Navigate to the samples (i.e. _SPRING_SECURITY_HOME_/samples/{starter-appname}) and click *OK*
|
||||
** Click *Finish*
|
||||
|
||||
=== Running the {starter-appname} application
|
||||
|
||||
In the following exercise we will be modifying the _spring-security-samples-{starter-appname}_ application. Before we make any changes, it is best to verify that the sample works properly. Perform the following steps to ensure that _spring-security-samples-{starter-appname}_ works.
|
||||
|
||||
* Right click on the _spring-security-samples-{starter-appname}_ application
|
||||
* Select *Run As->Run on Server*
|
||||
* Select the latest tc Server
|
||||
* Click *Finish*
|
||||
@@ -2,17 +2,23 @@
|
||||
:author: Rob Winch
|
||||
:starter-appname: hellomvc-jc
|
||||
:completed-appname: form-jc
|
||||
:include-dir: src/asciidoc/_hello-includes
|
||||
:verify-starter-app-include: ../_form-includes/verify-app.asc
|
||||
:include-dir: _includes
|
||||
|
||||
This guide builds off of link:hellomvc.html[Hello Spring MVC Security Java Config] to explain how to configure and use a custom login form with Spring Security Java Configuration.
|
||||
|
||||
include::{include-dir}/setting-up-the-sample.asc[]
|
||||
|
||||
Verify the application is working:
|
||||
|
||||
* A page displaying a user's inbox can be seen at http://localhost:8080/sample/ after authenticating with the *username* _user_ and the *password* _password_.
|
||||
* Try clicking on the Compose link and creating a message. The message details should be displayed.
|
||||
* Now click on the Inbox link and see the message listed. You can click on the summary link to see the details displayed again.
|
||||
|
||||
|
||||
= Overriding the default configure(HttpSecurity) method
|
||||
|
||||
As we saw in link:hellomvc.html[Hello Spring MVC Security Java Config], Spring Security's `WebSecurityConfigurerAdapter` provides some convenient defaults to get our application
|
||||
up and running quickly. However, our login form does not match the rest of our application. Let's see how we can update our configuration to use a custom form.
|
||||
up and running quickly. However, our login form does not look like the rest of our application. Let's see how we can update our configuration to use a custom form.
|
||||
|
||||
== Default configure(HttpSecurity)
|
||||
|
||||
@@ -46,8 +52,10 @@ We will want to ensure we compensate for overriding these defaults in our update
|
||||
----
|
||||
// ...
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvcSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@@ -94,7 +102,7 @@ To fix this we need to instruct Spring Security to allow anyone to access the */
|
||||
// ...
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvcSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@@ -112,11 +120,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
----
|
||||
|
||||
The `permitAll()` statement instructs Spring Security to allow any access to any URL (i.e. */login* and */login?error*) associated to `formLogin()`.
|
||||
The method `formLogin().permitAll()` statement instructs Spring Security to allow any access to any URL (i.e. */login* and */login?error*) associated to `formLogin()`.
|
||||
|
||||
NOTE: Granting access to the `formLogin()` URLs is not done by default since Spring Security needs to make certain assumptions about what is allowed and what is not. To be secure, it is best to ensure granting access to resources is explicit.
|
||||
|
||||
Start up the server and try visiting http://localhost:8080/sample/ to see the updates to our configuration. You should now get a 404 error stating that */login* cannot be found.
|
||||
Start up the server and try visiting http://localhost:8080/sample/ to see the updates to our configuration. You should now get a 500 error stating **Error resolving template "login"**.
|
||||
|
||||
= Creating a login page
|
||||
|
||||
@@ -144,71 +152,54 @@ public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InternalResourceViewResolver jspxViewResolver() {
|
||||
InternalResourceViewResolver result = new InternalResourceViewResolver();
|
||||
result.setPrefix("/WEB-INF/views/");
|
||||
result.setSuffix(".jspx");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
== Creating a login view
|
||||
|
||||
Our existing configuration means that all we need to do is create a *login.jspx* file with the following contents:
|
||||
Our existing configuration means that all we need to do is create a *login.html* file with the following contents:
|
||||
|
||||
.src/main/webapp/WEB-INF/views/login.jspx
|
||||
.src/main/resources/views/login.html
|
||||
[source,xml]
|
||||
----
|
||||
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
|
||||
xmlns:spring="http://www.springframework.org/tags"
|
||||
xmlns:c="http://java.sun.com/jsp/jstl/core"
|
||||
xmlns:form="http://www.springframework.org/tags/form" version="2.0">
|
||||
<jsp:directive.page language="java" contentType="text/html" />
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>Please Login</title>
|
||||
</head>
|
||||
<body>
|
||||
<c:url value="/login" var="loginUrl"/>
|
||||
<form:form name="f" action="${loginUrl}" method="post"> <1>
|
||||
<fieldset>
|
||||
<legend>Please Login</legend>
|
||||
<c:if test="${param.error != null}"> <2>
|
||||
<div class="alert alert-error">
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title tiles:fragment="title">Messages : Create</title>
|
||||
</head>
|
||||
<body>
|
||||
<div tiles:fragment="content">
|
||||
<form name="f" th:action="@{/login}" method="post"> <1>
|
||||
<fieldset>
|
||||
<legend>Please Login</legend>
|
||||
<div th:if="${param.error}" class="alert alert-error"> <2>
|
||||
Invalid username and password.
|
||||
</div>
|
||||
</c:if>
|
||||
<c:if test="${param.logout != null}"> <3>
|
||||
<div class="alert alert-success">
|
||||
<div th:if="${param.logout}" class="alert alert-success"> <3>
|
||||
You have been logged out.
|
||||
</div>
|
||||
</c:if>
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username"/> <4>
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password"/> <5>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn">Log in</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form:form>
|
||||
</body>
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username"/> <4>
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password"/> <5>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn">Log in</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</jsp:root>
|
||||
----
|
||||
|
||||
<1> The URL we submit our username and password to is the same URL as our login form (i.e. */login*), but a *POST* instead of a *GET*.
|
||||
<2> When authentication fails, the browser is redirected to */login?error* so we can display an error message by detecting if the parameter *error* is non-null.
|
||||
<3> When we are successfully loged out, the browser is redirected to */login?logout* so we can display an logout success message by detecting if the parameter *logout* is non-null.
|
||||
<3> When we are successfully logged out, the browser is redirected to */login?logout* so we can display an logout success message by detecting if the parameter *logout* is non-null.
|
||||
<4> The username should be present on the HTTP parameter username
|
||||
<5> The password should be present on the HTTP parameter password
|
||||
|
||||
IMPORTANT: Do not display details about why authentication failed. For example, we do not want to display that the user does not exist as this will tell an attacker that they should try a different username.
|
||||
|
||||
TIP: We use Spring Web MVC's <form:form> tag to automatically add the CSRF token to our form. We could also manually add the CSRF token using `<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>`.
|
||||
TIP: We use Thymeleaf to automatically add the CSRF token to our form. If we were not using Thymleaf or Spring MVCs taglib we could also manually add the CSRF token using `<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>`.
|
||||
|
||||
Start up the server and try visiting http://localhost:8080/sample/ to see the updates to our configuration. We now see our login page, but it does not look very pretty. The issue is that we have not granted access to the css files.
|
||||
|
||||
@@ -222,7 +213,7 @@ We need to update our configuration to allow anyone to access our resources and
|
||||
// ...
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvcSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@@ -248,8 +239,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
<2> As you might expect, `logout().permitAll()` allows any user to request logout and view logout success URL.
|
||||
|
||||
|
||||
Start up the server and try visiting http://localhost:8080/sample/ to see the updates to our configuration. We now see a custom login page that looks like the rest of our application.
|
||||
Restart the server and try visiting http://localhost:8080/sample/ to see the updates to our configuration. We now see a custom login page that looks like the rest of our application.
|
||||
|
||||
* Try entering an invalid username and password. You will see our error message is displayed.
|
||||
* Try entering a valid username and password. You will be authenticated successfully.
|
||||
* Try entering a valid username (user) and password (password). You will be authenticated successfully.
|
||||
* Try clicking the Log Out button. You will see our logout success message
|
||||
|
||||
== Conclusion
|
||||
|
||||
You should now know how to add a custom login form using Spring Security's Java Configuration. To learn more refer to the link:index.html[Spring Security Guides index page].
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
:author: Rob Winch
|
||||
:starter-appname: insecuremvc
|
||||
:completed-appname: hellomvc-jc
|
||||
:include-dir: src/asciidoc/_hello-includes
|
||||
:verify-starter-app-include: verify-insecuremvc-app.asc
|
||||
:include-dir: _includes
|
||||
:hello-include-dir: _hello-includes
|
||||
|
||||
This guide provides instructions on how to add Spring Security to an existing Spring MVC application without the use of XML.
|
||||
|
||||
include::{include-dir}/setting-up-the-sample.asc[]
|
||||
|
||||
include::{include-dir}/secure-the-application.asc[]
|
||||
Verify the application is working:
|
||||
|
||||
* A page displaying a user's inbox can be seen at http://localhost:8080/sample/
|
||||
* Try clicking on the Compose link and creating a message. The message details should be displayed.
|
||||
* Now click on the Inbox link and see the message listed. You can click on the summary link to see the details displayed again.
|
||||
|
||||
|
||||
include::{hello-include-dir}/secure-the-application.asc[]
|
||||
|
||||
=== Registering Spring Security with the war
|
||||
|
||||
@@ -18,35 +25,32 @@ We have created the Spring Security configuration, but we still need to register
|
||||
* Right click the _spring-security-samples-{starter-appname}_ project the Package Explorer view
|
||||
* Select *New->Class*
|
||||
* Enter _org.springframework.security.samples.config_ for the *Package*
|
||||
* Enter _SecurityWebApplicationInitializer_ for the *Name*
|
||||
* Enter MessageSecurityWebApplicationInitializer for the *Name*
|
||||
* Click *Finish*
|
||||
* Replace the file with the following contents:
|
||||
|
||||
.src/main/java/org/springframework/security/samples/config/SecurityWebApplicationInitializer.java
|
||||
.src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java
|
||||
[source,java]
|
||||
----
|
||||
package org.springframework.security.samples.config;
|
||||
|
||||
import org.springframework.core.annotation.*;
|
||||
import org.springframework.security.web.context.*;
|
||||
|
||||
@Order(2)
|
||||
public class MessageSecurityWebApplicationInitializer
|
||||
extends AbstractSecurityWebApplicationInitializer {
|
||||
}
|
||||
----
|
||||
|
||||
The `MessageSecurityWebApplicationInitializer` will automatically register the springSecurityFilterChain Filter for every URL in your application. We add `@Order(2)` so the springSecurityFilterChain is inserted before our Sitemesh Filter declared in <<message-web-application-inititializer-java, MessageWebApplicationInitializer.java>>
|
||||
The `MessageSecurityWebApplicationInitializer` will automatically register the springSecurityFilterChain Filter for every URL in your application. If Filters are added within other `WebApplicationInitializer` instances we can use `@Order` to control the ordering of the Filter instances.
|
||||
|
||||
=== Verify SecurityConfig is loaded
|
||||
|
||||
Just because <<security-config-java,`SecurityConfig`>> exists, does not mean that our Spring application knows about it. In this instance, our Spring root application context is initialized using MessageWebApplicationInitializer which is included with our spring-security-samples-messages-jc project. You can find a snippet of it below:
|
||||
Just because <<security-config-java,SecurityConfig>> exists, does not mean that our Spring application knows about it. In this instance, our Spring root application context is initialized using MessageWebApplicationInitializer which is included with our spring-security-samples-messages-jc project. You can find a snippet of it below:
|
||||
|
||||
[[message-web-application-inititializer-java]]
|
||||
.MessageWebApplicationInitializer.java
|
||||
[source,java]
|
||||
----
|
||||
@Order(1)
|
||||
public class MessageWebApplicationInitializer extends
|
||||
AbstractAnnotationConfigDispatcherServletInitializer {
|
||||
|
||||
@@ -66,81 +70,68 @@ You will notice it is loading the `RootConfiguration` class which is also includ
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
@ComponentScan(value = "org.springframework.security.samples.config",
|
||||
excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = RootConfiguration.class))
|
||||
@ComponentScan
|
||||
public class RootConfiguration {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
The `@ComponentScan` is loading all configuration in the org.springframework.security.samples.config package. Since <<security-config-java,`SecurityConfig`>> is in this package, it will be loaded with our existing setup and there is nothing more to do.
|
||||
The `@ComponentScan` is loading all configuration within the same package (and child packags) as `RootConfiguration`. Since <<security-config-java,SecurityConfig>> is in this package, it will be loaded with our existing setup and there is nothing more to do.
|
||||
|
||||
NOTE: Had <<security-config-java,`SecurityConfig`>> not been loaded, we could have used an `@Import(SecurityConfig)` above the class definition of <<root-configuration-java,`RootConfiguration`>> or added <<security-config-java,`SecurityConfig`>> as one of the results for `getRootConfigClasses()`.
|
||||
NOTE: Had <<security-config-java,SecurityConfig>> not been loaded, we could have used an `@Import(SecurityConfig)` above the class definition of <<root-configuration-java,RootConfiguration>> or added <<security-config-java,SecurityConfig>> as one of the results for `getRootConfigClasses()`.
|
||||
|
||||
include::{include-dir}/exploring-the-secured-application.asc[]
|
||||
include::{hello-include-dir}/exploring-the-secured-application.asc[]
|
||||
|
||||
==== Displaying the user name
|
||||
|
||||
Now that we have authenticated, let's update the application to display the username if the user is authenticated. Update main.jsp to contain the following snippet:
|
||||
Now that we have authenticated, let's see how our application is displaying the username if the user is authenticated.
|
||||
|
||||
.src/main/webapp/WEB-INF/decorators/main.jsp
|
||||
.messages-jc/src/main/resources/views/layout.html
|
||||
[source,html]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<div class="nav-collapse collapse">
|
||||
*<c:if test="${pageContext.request.remoteUser != null}">
|
||||
<p class="navbar-text pull-right">
|
||||
<c:out value="${pageContext.request.remoteUser}"/>
|
||||
<div th:if="${#httpServletRequest.remoteUser != null}">
|
||||
<p th:text="${#httpServletRequest.remoteUser}">
|
||||
sample_user
|
||||
</p>
|
||||
</c:if>*
|
||||
<ul class="nav">
|
||||
<c:url var="inboxUrl" value="/"/>
|
||||
<li><a href="${inboxUrl}">Inbox</a></li>
|
||||
<c:url var="composeUrl" value="/?form"/>
|
||||
<li><a href="${composeUrl}">Compose</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
----
|
||||
|
||||
WARNING: The `<c:out />` tag ensures the username is escaped to avoid http://en.wikipedia.org/wiki/Cross-site_scripting[XSS vulnerabilities] Regardless of how an application renders user inputed values, it should ensure that the values are properly escaped.
|
||||
In our samples we use http://www.thymeleaf.org/[Thymeleaf], but any view technology will work. Any technology can inspect the `HttpServletRequest#getRemoteUser()` to view the current user since Spring Security integrates with the <<servlet-api-integration,Servlet API methods>>.
|
||||
|
||||
Refresh the page at http://localhost:8080/sample/ and you will see the user name displayed. This works because Spring Security integrates with the <<servlet-api-integration,Servlet API methods>>
|
||||
WARNING: The Thymeleaf ensures the username is escaped to avoid http://en.wikipedia.org/wiki/Cross-site_scripting[XSS vulnerabilities] Regardless of how an application renders user inputed values, it should ensure that the values are properly escaped.
|
||||
|
||||
==== Logging out
|
||||
|
||||
Now that we can view the user name, let's update the application to allow logging out. Update the body of index.jsp to contain a log out link as shown below:
|
||||
We can view the user name, but how are we able to log out? Below you can see how we are able to log out.
|
||||
|
||||
.src/main/webapp/index.jsp
|
||||
.messages-jc/src/main/resources/views/layout.html
|
||||
[source,html]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
<div class="nav-collapse collapse">
|
||||
*<c:if test="${pageContext.request.remoteUser != null}">
|
||||
<c:url var="logoutUrl" value="/logout"/>
|
||||
<form:form class="navbar-form pull-right" action="${logoutUrl}" method="post">
|
||||
<input type="submit" value="Log out" />
|
||||
</form:form>
|
||||
</c:if>*
|
||||
<p class="navbar-text pull-right">
|
||||
<c:out value="${pageContext.request.remoteUser}"/>
|
||||
</p>
|
||||
<ul class="nav">
|
||||
<c:url var="inboxUrl" value="/"/>
|
||||
<li><a href="${inboxUrl}">Inbox</a></li>
|
||||
<c:url var="composeUrl" value="/?form"/>
|
||||
<li><a href="${composeUrl}">Compose</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<form th:action="@{/logout}" method="post">
|
||||
<input type="submit" value="Log out" />
|
||||
</form>
|
||||
----
|
||||
|
||||
If you try to log out right now the request will fail. The reason is that Spring Security is protecting against CSRF attakcks and there is no CSRF token include in our request. Update our configuration to use the `@EnableWebMvcSecurity` annotation which will do the same as `@EnableWebMvcSecurity` and provide integration with Spring MVC. Among other things, it will ensure our CSRF Token is included in our forms automatically when using Thymleaf 2.1+ or Spring MVC taglibs.
|
||||
|
||||
.src/main/java/org/springframework/security/samples/config/SecurityConfig.java
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.*;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvcSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
----
|
||||
|
||||
In order to help protect against http://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attacks], by default, Spring Security Java Configuration log out requires:
|
||||
|
||||
* the HTTP method must be a POST
|
||||
* the CSRF token must be added to the request. Since we are using Spring MVC, the CSRF token is automatically added as a hidden input for you (view the source to see it). If you were not using Spring MVC, you can access the CsrfToken on the ServletRequest using the attribute _csrf
|
||||
* the CSRF token must be added to the request. Since we have used `@EnableWebMvcSecurity` and are using Thymeleaf, the CSRF token is automatically added as a hidden input for you (view the source to see it).
|
||||
|
||||
Refresh the page at http://localhost:8080/sample/ and you will see the log out button. Click the button and see that the application logs you out successfully.
|
||||
NOTE: If you were not using Spring MVC taglibs or Thymeleaf, you can access the CsrfToken on the ServletRequest using the attribute _csrf. You can find an example of including the CSRF token in a JSP within the link:helloworld.html[Hello Spring Security Java Config].
|
||||
|
||||
include::{include-dir}/basic-authentication.asc[]
|
||||
Restart the application server and click the Log out button and see that the application logs you out successfully.
|
||||
|
||||
== Conclusion
|
||||
|
||||
You should now now how to secure your application using Spring Security without using any XML. Next, we will see how to link:form.html[customize our login form].
|
||||
You should now know how to secure your application using Spring Security without using any XML. Next, we will see how to link:form.html[customize our login form].
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
:author: Rob Winch
|
||||
:starter-appname: insecure
|
||||
:completed-appname: helloworld-jc
|
||||
:include-dir: src/asciidoc/_hello-includes
|
||||
:verify-starter-app-include: verify-insecure-app.asc
|
||||
:include-dir: _includes
|
||||
:hello-include-dir: _hello-includes
|
||||
|
||||
This guide provides instructions on how to add Spring Security to an existing application without the use of XML.
|
||||
|
||||
include::{include-dir}/setting-up-the-sample.asc[]
|
||||
|
||||
include::{include-dir}/secure-the-application.asc[]
|
||||
Verify the application is working by ensuring a page stating *TODO Secure this* is displayed at http://localhost:8080/sample/
|
||||
|
||||
Once you have verified the application runs, stop the application server using the following steps:
|
||||
|
||||
* In the Servers view select the latest tc Server
|
||||
* Click the stop button (a red square) to stop the application server
|
||||
|
||||
include::{hello-include-dir}/secure-the-application.asc[]
|
||||
|
||||
=== Registering Spring Security with the war
|
||||
|
||||
@@ -41,11 +48,11 @@ public class SecurityWebApplicationInitializer
|
||||
The `SecurityWebApplicationInitializer` will do the following things:
|
||||
|
||||
* Automatically register the springSecurityFilterChain Filter for every URL in your application
|
||||
* Add a ContextLoaderListener that loads the <<security-config-java,`SecurityConfig`>>.
|
||||
* Add a ContextLoaderListener that loads the <<security-config-java,SecurityConfig>>.
|
||||
|
||||
NOTE: Since we were not already using Spring, this is a simple way to add our <<security-config-java,`SecurityConfig`>>. If we were already using Spring, then we should add our <<security-config-java,`SecurityConfig`>> with the reset of our Spring configuration (i.e. a subclass of AbstractContextLoaderInitializer or AbstractDispatcherServletInitializer) and use the default constructor instead.
|
||||
NOTE: Since we were not already using Spring, this is a simple way to add our <<security-config-java,SecurityConfig>>. If we were already using Spring, then we should add our <<security-config-java,SecurityConfig>> with the reset of our Spring configuration (i.e. a subclass of AbstractContextLoaderInitializer or AbstractDispatcherServletInitializer) and use the default constructor instead.
|
||||
|
||||
include::{include-dir}/exploring-the-secured-application.asc[]
|
||||
include::{hello-include-dir}/exploring-the-secured-application.asc[]
|
||||
|
||||
==== Displaying the user name
|
||||
|
||||
@@ -70,7 +77,7 @@ Refresh the page at http://localhost:8080/sample/ and you will see the user name
|
||||
|
||||
==== Logging out
|
||||
|
||||
Now that we can view the user name, let's update the application to allow logging out. Update the body of index.jsp to contain a log out link as shown below:
|
||||
Now that we can view the user name, let's update the application to allow logging out. Update the body of index.jsp to contain a log out form as shown below:
|
||||
|
||||
.src/main/webapp/index.jsp
|
||||
[source,html]
|
||||
@@ -93,12 +100,12 @@ Now that we can view the user name, let's update the application to allow loggin
|
||||
In order to help protect against http://en.wikipedia.org/wiki/Cross-site_request_forgery[CSRF attacks], by default, Spring Security Java Configuration log out requires:
|
||||
|
||||
* the HTTP method must be a POST
|
||||
* the CSRF token must be added to the request You can access it on the ServletRequest using the attribute _csrf as illustrated above. If you were using Spring MVC, the CSRF token is automatically added as a hidden input for you.
|
||||
* the CSRF token must be added to the request You can access it on the ServletRequest using the attribute _csrf as illustrated above.
|
||||
|
||||
NOTE: If you were using Spring MVC's tag library or Thymeleaf, the CSRF token is automatically added as a hidden input for you.
|
||||
|
||||
Refresh the page at http://localhost:8080/sample/ and you will see the log out button. Click the logout button and see that the application logs you out successfully.
|
||||
|
||||
include::{include-dir}/basic-authentication.asc[]
|
||||
|
||||
== Conclusion
|
||||
|
||||
You should now now how to secure your application using Spring Security without using any XML.
|
||||
You should now know how to secure your application using Spring Security without using any XML. To learn more refer to the link:index.html[Spring Security Guides index page].
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
= Spring Security Guides
|
||||
Rob Winch
|
||||
|
||||
These are set by step guides on how to use Spring Security.
|
||||
These are step by step guides on how to use Spring Security.
|
||||
|
||||
== Hello World
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'erb'
|
||||
|
||||
guard 'shell' do
|
||||
watch(/^.*\.adoc$/) {|m|
|
||||
Asciidoctor.render_file(m[0], :to_dir => "build/", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'doctype' => 'book','toc2' => '', 'spring-security-version' => '3.2.0.CI-SNAPSHOT', 'revnumber' => '3.2.0.CI-SNAPSHOT' })
|
||||
Asciidoctor.render_file(m[0], :to_dir => "build/", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'doctype' => 'book','toc2' => '', 'spring-security-version' => '3.2.0.CI-SNAPSHOT','spring-version' => '3.2.0.RELEASE','spring4-version' => '4.0.0.RELEASE', 'revnumber' => '3.2.0.CI-SNAPSHOT', 'numbered'=>'' })
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ From a Spring Security perspective, the first thing you should do is follow the
|
||||
.. <<faq-session-listener-missing>>
|
||||
.. <<faq-unwanted-session-creation>>
|
||||
. Miscellaneous
|
||||
.. <<403-csrf>>
|
||||
.. <<faq-no-security-on-forward>>
|
||||
.. <<faq-method-security-in-web-context>>
|
||||
.. <<faq-no-filters-no-context>>
|
||||
@@ -206,6 +207,11 @@ This usually means that the user's application is creating a session somewhere,
|
||||
|
||||
If you are having trouble working out where a session is being created, you can add some debugging code to track down the location(s). One way to do this would be to add a `javax.servlet.http.HttpSessionListener` to your application, which calls `Thread.dumpStack()` in the `sessionCreated` method.
|
||||
|
||||
[[403-csrf]]
|
||||
=== I get a 403 Forbidden when performing a POST
|
||||
|
||||
If an HTTP 403 Forbidden is returned for HTTP POST, but works for HTTP GET then the issue is most likely related to http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#csrf[CSRF]. Either provide the CSRF Token or disable CSRF protection (not recommended).
|
||||
|
||||
[[faq-no-security-on-forward]]
|
||||
=== I'm forwarding a request to another URL using the RequestDispatcher, but my security constraints aren't being applied.
|
||||
|
||||
|
||||
+777
-613
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
version=3.2.0.CI-SNAPSHOT
|
||||
version=3.2.0.RELEASE
|
||||
|
||||
@@ -11,14 +11,13 @@ apply plugin: 'propdeps-eclipse'
|
||||
sourceCompatibility = 1.5
|
||||
targetCompatibility = 1.5
|
||||
|
||||
ext.springVersion = '3.2.4.RELEASE'
|
||||
ext.springLdapVersion = '1.3.2.RELEASE'
|
||||
ext.ehcacheVersion = '1.6.2'
|
||||
ext.aspectjVersion = '1.6.10'
|
||||
ext.apacheDsVersion = '1.5.5'
|
||||
ext.jstlVersion = '1.2'
|
||||
ext.jettyVersion = '6.1.26'
|
||||
ext.hsqlVersion = '1.8.0.10'
|
||||
ext.hsqlVersion = '2.3.1'
|
||||
ext.slf4jVersion = '1.7.5'
|
||||
ext.logbackVersion = '0.9.29'
|
||||
ext.cglibVersion = '2.2'
|
||||
@@ -28,6 +27,7 @@ ext.seleniumVersion = '2.33.0'
|
||||
ext.groovyVersion = '2.0.5'
|
||||
ext.spockVersion = '0.7-groovy-2.0'
|
||||
ext.gebVersion = '0.9.0'
|
||||
ext.thymeleafVersion = '2.1.2.RELEASE'
|
||||
|
||||
ext.powerMockDependencies = [
|
||||
"org.powermock:powermock-core:$powerMockVersion",
|
||||
@@ -204,3 +204,7 @@ task javadocJar(type: Jar) {
|
||||
classifier = 'javadoc'
|
||||
from javadoc
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ task sourceJar(type: Jar) {
|
||||
|
||||
artifacts {
|
||||
archives sourceJar
|
||||
archives javadocJar
|
||||
}
|
||||
|
||||
// Configuration for SpringSource s3 maven deployer
|
||||
@@ -21,7 +20,9 @@ dependencies {
|
||||
}
|
||||
|
||||
install {
|
||||
customizePom(repositories.mavenInstaller.pom, project)
|
||||
repositories.mavenInstaller {
|
||||
customizePom(pom, project)
|
||||
}
|
||||
}
|
||||
|
||||
def customizePom(pom, gradleProject) {
|
||||
@@ -42,10 +43,10 @@ def customizePom(pom, gradleProject) {
|
||||
packaging = "war"
|
||||
}
|
||||
description = gradleProject.name
|
||||
url = 'http://springsource.org/spring-security'
|
||||
url = 'http://spring.io/spring-security'
|
||||
organization {
|
||||
name = 'SpringSource'
|
||||
url = 'http://springsource.org/'
|
||||
name = 'spring.io'
|
||||
url = 'http://spring.io/'
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
@@ -55,15 +56,15 @@ def customizePom(pom, gradleProject) {
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url = 'https://github.com/SpringSource/spring-security'
|
||||
connection = 'scm:git:git://github.com/SpringSource/spring-security'
|
||||
developerConnection = 'scm:git:git://github.com/SpringSource/spring-security'
|
||||
url = 'https://github.com/spring-projects/spring-security'
|
||||
connection = 'scm:git:git://github.com/spring-projects/spring-security'
|
||||
developerConnection = 'scm:git:git://github.com/spring-projects/spring-security'
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'rwinch'
|
||||
name = 'Rob Winch'
|
||||
email = 'rwinch@vmware.com'
|
||||
email = 'rwinch@gopivotal.com'
|
||||
}
|
||||
}
|
||||
if(isWar) {
|
||||
@@ -71,11 +72,18 @@ def customizePom(pom, gradleProject) {
|
||||
'm2eclipse.wtp.contextRoot' '/' + project.war.baseName
|
||||
}
|
||||
}
|
||||
if(!project.releaseBuild) {
|
||||
if(project.snapshotBuild) {
|
||||
repositories {
|
||||
repository {
|
||||
id 'spring-snasphot'
|
||||
url 'http://repo.springsource.org/libs-snapshot'
|
||||
url 'https://repo.spring.io/snapshot'
|
||||
}
|
||||
}
|
||||
} else if(!project.releaseBuild) {
|
||||
repositories {
|
||||
repository {
|
||||
id 'spring-milestone'
|
||||
url 'https://repo.spring.io/milestone'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Tue Sep 24 11:43:41 CDT 2013
|
||||
#Wed Dec 11 17:49:08 CST 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-bin.zip
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-rc-2-bin.zip
|
||||
|
||||
+18
-24
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>itest-context</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>itest-context</name>
|
||||
<description>itest-context</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>
|
||||
@@ -64,31 +58,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -100,7 +94,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -155,25 +149,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+19
-25
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>itest-web</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>itest-web</name>
|
||||
<description>itest-web</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,23 +42,17 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -70,7 +64,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -149,49 +143,49 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -29,13 +29,11 @@ integrationTest {
|
||||
include('**/ApacheDSServerIntegrationTests.class')
|
||||
// exclude('**/OpenLDAPIntegrationTestSuite.class')
|
||||
maxParallelForks = 1
|
||||
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
|
||||
}
|
||||
|
||||
// Runs a server for running the integration tests against (from an IDE, for example)
|
||||
task(ldapServer, dependsOn: 'integrationTestClasses', type: JavaExec) {
|
||||
classpath = sourceSets.integrationTest.runtimeClasspath
|
||||
main = 'org.springframework.security.ldap.ApacheDSServerIntegrationTests'
|
||||
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
|
||||
}
|
||||
|
||||
|
||||
+14
-20
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<name>spring-security-ldap</name>
|
||||
<description>spring-security-ldap</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.springframework.ldap</groupId>
|
||||
@@ -76,25 +70,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -106,7 +100,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -204,7 +198,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.6.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import org.springframework.security.ldap.userdetails.LdapUserDetailsManagerTests
|
||||
DefaultLdapAuthoritiesPopulatorTests.class,
|
||||
LdapUserDetailsManagerTests.class,
|
||||
DefaultSpringSecurityContextSourceTests.class,
|
||||
SpringSecurityLdapTemplateTests.class
|
||||
SpringSecurityLdapTemplateITests.class
|
||||
}
|
||||
)
|
||||
public final class ApacheDSServerIntegrationTests {
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import org.springframework.security.crypto.codec.Utf8;
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTests {
|
||||
public class SpringSecurityLdapTemplateITests extends AbstractLdapIntegrationTests {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private SpringSecurityLdapTemplate template;
|
||||
+36
-26
@@ -1,10 +1,11 @@
|
||||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
/*
|
||||
* 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
|
||||
* 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,
|
||||
@@ -12,23 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.ldap;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.CompositeName;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.PartialResultException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
@@ -42,6 +28,18 @@ import org.springframework.ldap.core.LdapEncoder;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.PartialResultException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Extension of Spring LDAP's LdapTemplate class which adds extra functionality required by Spring Security.
|
||||
@@ -55,6 +53,7 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
private static final Log logger = LogFactory.getLog(SpringSecurityLdapTemplate.class);
|
||||
|
||||
public static final String[] NO_ATTRS = new String[0];
|
||||
private static final boolean RETURN_OBJECT = true;
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
@@ -207,7 +206,7 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
String base, String filter, Object[] params) throws NamingException {
|
||||
final DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
|
||||
final DistinguishedName searchBaseDn = new DistinguishedName(base);
|
||||
final NamingEnumeration<SearchResult> resultsEnum = ctx.search(searchBaseDn, filter, params, searchControls);
|
||||
final NamingEnumeration<SearchResult> resultsEnum = ctx.search(searchBaseDn, filter, params, buildControls(searchControls));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Searching for entry under DN '" + ctxBaseDn
|
||||
@@ -218,17 +217,13 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
try {
|
||||
while (resultsEnum.hasMore()) {
|
||||
SearchResult searchResult = resultsEnum.next();
|
||||
// Work out the DN of the matched entry
|
||||
DistinguishedName dn = new DistinguishedName(new CompositeName(searchResult.getName()));
|
||||
|
||||
if (base.length() > 0) {
|
||||
dn.prepend(searchBaseDn);
|
||||
}
|
||||
DirContextAdapter dca = (DirContextAdapter) searchResult.getObject();
|
||||
Assert.notNull(dca, "No object returned by search, DirContext is not correctly configured");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found DN: " + dn);
|
||||
logger.debug("Found DN: " + dca.getDn());
|
||||
}
|
||||
results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn));
|
||||
results.add(dca);
|
||||
}
|
||||
} catch (PartialResultException e) {
|
||||
LdapUtils.closeEnumeration(resultsEnum);
|
||||
@@ -246,6 +241,21 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
return results.iterator().next();
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to make sure the search controls has the return object flag set to true, in order for
|
||||
* the search to return DirContextAdapter instances.
|
||||
* @param originalControls
|
||||
* @return
|
||||
*/
|
||||
private static SearchControls buildControls(SearchControls originalControls) {
|
||||
return new SearchControls(originalControls.getSearchScope(),
|
||||
originalControls.getCountLimit(),
|
||||
originalControls.getTimeLimit(),
|
||||
originalControls.getReturningAttributes(),
|
||||
RETURN_OBJECT,
|
||||
originalControls.getDerefLinkFlag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the search controls which will be used for search operations by the template.
|
||||
*
|
||||
|
||||
+2
@@ -15,6 +15,7 @@ package org.springframework.security.ldap.authentication.ad;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
||||
import org.springframework.ldap.support.LdapUtils;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
@@ -174,6 +175,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
env.put(Context.PROVIDER_URL, bindUrl);
|
||||
env.put(Context.SECURITY_CREDENTIALS, password);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
env.put(Context.OBJECT_FACTORIES, DefaultDirObjectFactory.class.getName());
|
||||
|
||||
try {
|
||||
return contextFactory.createContext(env);
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData
|
||||
sb.append("CredentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
|
||||
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
|
||||
|
||||
if (this.getAuthorities() != null) {
|
||||
if (this.getAuthorities() != null && !this.getAuthorities().isEmpty()) {
|
||||
sb.append("Granted Authorities: ");
|
||||
boolean first = true;
|
||||
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SpringSecurityLdapTemplateTests {
|
||||
|
||||
@Mock
|
||||
private DirContext ctx;
|
||||
@Captor
|
||||
private ArgumentCaptor<SearchControls> searchControls;
|
||||
@Mock
|
||||
private NamingEnumeration<SearchResult> resultsEnum;
|
||||
@Mock
|
||||
private SearchResult searchResult;
|
||||
|
||||
// SEC-2405
|
||||
@Test
|
||||
public void searchForSingleEntryInternalAllowsReferrals() throws Exception {
|
||||
String base = "";
|
||||
String filter = "";
|
||||
String searchResultName = "ldap://example.com/dc=springframework,dc=org";
|
||||
Object[] params = new Object[] {};
|
||||
DirContextAdapter searchResultObject = mock(DirContextAdapter.class);
|
||||
|
||||
when(ctx.search(any(DistinguishedName.class), eq(filter), eq(params), searchControls.capture())).thenReturn(resultsEnum);
|
||||
when(resultsEnum.hasMore()).thenReturn(true, false);
|
||||
when(resultsEnum.next()).thenReturn(searchResult);
|
||||
when(searchResult.getName()).thenReturn(searchResultName);
|
||||
when(searchResult.getObject()).thenReturn(searchResultObject);
|
||||
|
||||
SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, mock(SearchControls.class), base, filter, params);
|
||||
|
||||
assertThat(searchControls.getValue().getReturningObjFlag()).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
+15
-13
@@ -12,16 +12,14 @@
|
||||
*/
|
||||
package org.springframework.security.ldap.authentication.ad;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.ContextFactory;
|
||||
|
||||
import org.apache.directory.shared.ldap.util.EmptyEnumeration;
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
@@ -33,8 +31,6 @@ import org.springframework.security.authentication.DisabledException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
import javax.naming.AuthenticationException;
|
||||
import javax.naming.CommunicationException;
|
||||
@@ -45,7 +41,15 @@ import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
import java.util.*;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.ContextFactory;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
@@ -75,7 +79,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||
when(ctx.getNameInNamespace()).thenReturn("");
|
||||
|
||||
DirContextAdapter dca = new DirContextAdapter();
|
||||
SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", null, dca.getAttributes());
|
||||
SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes());
|
||||
when(ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class)))
|
||||
.thenReturn(new MockNamingEnumeration(sr))
|
||||
.thenReturn(new MockNamingEnumeration(sr));
|
||||
@@ -88,8 +92,6 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||
|
||||
dca.addAttributeValue("memberOf","CN=Admin,CN=Users,DC=mydomain,DC=eu");
|
||||
|
||||
sr.setAttributes(dca.getAttributes());
|
||||
|
||||
result = provider.authenticate(joe);
|
||||
|
||||
assertEquals(1, result.getAuthorities().size());
|
||||
@@ -102,7 +104,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||
when(ctx.getNameInNamespace()).thenReturn("");
|
||||
|
||||
DirContextAdapter dca = new DirContextAdapter();
|
||||
SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", null, dca.getAttributes());
|
||||
SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes());
|
||||
when(ctx.search(eq(new DistinguishedName("DC=mydomain,DC=eu")), any(String.class), any(Object[].class), any(SearchControls.class)))
|
||||
.thenReturn(new MockNamingEnumeration(sr));
|
||||
provider.contextFactory = createContextFactoryReturning(ctx);
|
||||
@@ -149,7 +151,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests {
|
||||
NamingEnumeration<SearchResult> searchResults = mock(NamingEnumeration.class);
|
||||
when(searchResults.hasMore()).thenReturn(true,true,false);
|
||||
SearchResult searchResult = mock(SearchResult.class);
|
||||
when(searchResult.getName()).thenReturn("ou=1","ou=2");
|
||||
when(searchResult.getObject()).thenReturn(new DirContextAdapter("ou=1"),new DirContextAdapter("ou=2"));
|
||||
when(searchResults.next()).thenReturn(searchResult);
|
||||
when(ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class)))
|
||||
.thenReturn(searchResults );
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user