Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 081f0c4d94 | |||
| 247f54dc41 | |||
| 017e9834bd | |||
| 49719480a8 | |||
| f3edaa673a | |||
| f99fe36e02 | |||
| 546d44d6e7 | |||
| 901a4e183a | |||
| 72d08a2a5f | |||
| 2ac51c9c7f | |||
| b64cdb5765 | |||
| aa31f1f695 | |||
| 8353984733 | |||
| c31bdb6390 | |||
| 168f4b8f70 | |||
| 9c03571bbb | |||
| 4c79107e01 | |||
| 3f543d0fbd | |||
| 08104eb06c | |||
| b54d350e54 | |||
| b5e0886bde | |||
| 38492a5794 | |||
| b7541d56d0 | |||
| 7a7ce11ebb | |||
| 028854b936 | |||
| aa5df61eff | |||
| 6df5b76f24 | |||
| c8ed130008 | |||
| d39f3385b6 | |||
| 6bec625e68 | |||
| 666e356ebc | |||
| fc516b55a6 | |||
| bb834bccf6 | |||
| 09436649cc | |||
| f94399cff9 | |||
| 94fb1893de | |||
| 3185876a7d | |||
| 2cb38ae115 | |||
| 24fcb6c45a | |||
| a9024de734 | |||
| fd9f57eb5f | |||
| 7259759f8d | |||
| 14e5e06ae0 | |||
| 697daeab7c | |||
| f97f38fd57 | |||
| a853d38076 | |||
| f0a9421aa4 | |||
| 36f4f7d081 | |||
| 07d1c7c5eb | |||
| d2c28c58e2 | |||
| 14a656186d | |||
| 2a197c72eb | |||
| ab5af87953 | |||
| 23294c4c57 | |||
| eb2870bf82 | |||
| 9fa42117f7 | |||
| cf3d6e7167 | |||
| 08f0b57243 | |||
| 97b4cb0b73 | |||
| 8ca4b55d32 | |||
| 8e546454a5 | |||
| 406bb1d4d5 | |||
| 8437d0fea3 | |||
| df3b8bc284 | |||
| 57d7ad05f9 | |||
| e62596f36d | |||
| d3685d89c5 | |||
| a98389fa98 | |||
| dc9f9b140f | |||
| f432c04111 | |||
| 50b72dddbc | |||
| 94e580fe64 | |||
| af9139b613 | |||
| f019ea89e7 | |||
| 0d700628dc | |||
| aaa9708b95 | |||
| df9e6c973c | |||
| 1da9c06f3b | |||
| 0c35209d77 | |||
| badb466cc5 | |||
| 46bb855737 | |||
| 6a3a5f7beb | |||
| 52c6e3cf89 | |||
| 17cfd4707b | |||
| 2c99cd3bbf | |||
| 8a7ac398e6 | |||
| 5e35e37a2b | |||
| c1e9140940 | |||
| 1222fc5f10 | |||
| 08c1f500a7 | |||
| a18707c870 | |||
| 48ff518a41 | |||
| 0b1e3b4e4a | |||
| 6b4a52715b | |||
| 7fb052e7ae |
+2
-2
@@ -29,9 +29,9 @@ In the instructions below, http://vimeo.com/34436402[`./gradlew`] is invoked fro
|
||||
a cross-platform, self-contained bootstrap mechanism for the build.
|
||||
|
||||
=== Prerequisites
|
||||
http://help.github.com/set-up-git-redirect[Git] and the http://www.oracle.com/technetwork/java/javase/downloads[JDK7 build].
|
||||
http://help.github.com/set-up-git-redirect[Git] and the http://www.oracle.com/technetwork/java/javase/downloads[JDK8 build].
|
||||
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.7.0` folder extracted from the JDK download.
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder extracted from the JDK download.
|
||||
|
||||
=== Check out sources
|
||||
[indent=0]
|
||||
|
||||
+3
-9
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-acl</name>
|
||||
<description>spring-security-acl</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -51,7 +51,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -151,12 +151,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
+7
-4
@@ -16,18 +16,20 @@
|
||||
|
||||
package org.springframework.security.acls.domain;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link AclAuthorizationStrategy}.
|
||||
* <p>
|
||||
@@ -118,7 +120,8 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||
}
|
||||
|
||||
// Iterate this principal's authorities to determine right
|
||||
if (authentication.getAuthorities().contains(requiredAuthority)) {
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
|
||||
if (authorities.contains(requiredAuthority.getAuthority())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -26,6 +26,8 @@ import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AclService;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.security.acls.model.SidRetrievalStrategy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
@@ -37,7 +39,6 @@ import org.springframework.security.core.Authentication;
|
||||
public class AclPermissionEvaluatorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void hasPermissionReturnsTrueIfAclGrantsPermission() throws Exception {
|
||||
AclService service = mock(AclService.class);
|
||||
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
||||
@@ -48,8 +49,8 @@ public class AclPermissionEvaluatorTests {
|
||||
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||
Acl acl = mock(Acl.class);
|
||||
|
||||
when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl);
|
||||
when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true);
|
||||
when(service.readAclById(any(ObjectIdentity.class), anyListOf(Sid.class))).thenReturn(acl);
|
||||
when(acl.isGranted(anyListOf(Permission.class), anyListOf(Sid.class), eq(false))).thenReturn(true);
|
||||
|
||||
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "READ")).isTrue();
|
||||
}
|
||||
@@ -68,8 +69,8 @@ public class AclPermissionEvaluatorTests {
|
||||
pe.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
|
||||
Acl acl = mock(Acl.class);
|
||||
|
||||
when(service.readAclById(any(ObjectIdentity.class), anyList())).thenReturn(acl);
|
||||
when(acl.isGranted(anyList(), anyList(), eq(false))).thenReturn(true);
|
||||
when(service.readAclById(any(ObjectIdentity.class), anyListOf(Sid.class))).thenReturn(acl);
|
||||
when(acl.isGranted(anyListOf(Permission.class), anyListOf(Sid.class), eq(false))).thenReturn(true);
|
||||
|
||||
assertThat(pe.hasPermission(mock(Authentication.class), new Object(), "write")).isTrue();
|
||||
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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.acls.domain;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AclAuthorizationStrategyImplTests {
|
||||
@Mock
|
||||
Acl acl;
|
||||
GrantedAuthority authority;
|
||||
AclAuthorizationStrategyImpl strategy;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
authority = new SimpleGrantedAuthority("ROLE_AUTH");
|
||||
TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar", Arrays.asList(authority));
|
||||
authentication.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
// gh-4085
|
||||
@Test
|
||||
public void securityCheckWhenCustomAuthorityThenNameIsUsed() {
|
||||
strategy = new AclAuthorizationStrategyImpl(new CustomAuthority());
|
||||
strategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class CustomAuthority implements GrantedAuthority {
|
||||
@Override
|
||||
public String getAuthority() {
|
||||
return authority.getAuthority();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-9
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-aspects</name>
|
||||
<description>spring-security-aspects</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -45,7 +45,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -130,12 +130,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
+10
-6
@@ -1,15 +1,16 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
maven { url "https://repo.spring.io/plugins-snapshot" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
|
||||
classpath("io.spring.gradle:spring-io-plugin:0.0.5.RELEASE")
|
||||
classpath("io.spring.gradle:spring-io-plugin:0.0.6.RELEASE")
|
||||
classpath("com.bmuschko:gradle-tomcat-plugin:2.2.4")
|
||||
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
||||
classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.1')
|
||||
classpath("io.spring.gradle:docbook-reference-plugin:0.3.1")
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE")
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.0.BUILD-SNAPSHOT")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +28,8 @@ allprojects {
|
||||
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.springVersion = '4.3.2.RELEASE'
|
||||
ext.springLdapVersion = '2.0.2.RELEASE'
|
||||
ext.springVersion = '4.3.5.RELEASE'
|
||||
ext.springLdapVersion = '2.2.0.RELEASE'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
|
||||
@@ -39,7 +40,6 @@ allprojects {
|
||||
maven { url "http://repo.terracotta.org/maven2/" }
|
||||
}
|
||||
|
||||
eclipse.project.name = "${project.name}-4.1.x"
|
||||
}
|
||||
|
||||
sonarqube {
|
||||
@@ -115,7 +115,11 @@ configure(coreModuleProjects) {
|
||||
dependencyManagement {
|
||||
springIoTestRuntime {
|
||||
imports {
|
||||
mavenBom "io.spring.platform:platform-bom:${springIoVersion}"
|
||||
mavenBom("io.spring.platform:platform-bom:${springIoVersion}") {
|
||||
bomProperties([
|
||||
'mockito.version': '1.10.19'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.*
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.plugins.ide.eclipse.GenerateEclipseProject
|
||||
import org.gradle.plugins.ide.eclipse.GenerateEclipseClasspath
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin
|
||||
@@ -41,28 +42,25 @@ class AspectJPlugin implements Plugin<Project> {
|
||||
project.configurations.create('aspectpath')
|
||||
}
|
||||
|
||||
project.tasks.create(name: 'compileAspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
|
||||
dependsOn project.configurations*.getTaskDependencyFromProjectDependency(true, "compileJava")
|
||||
project.tasks.withType(JavaCompile) { javaCompileTask ->
|
||||
def javaCompileTaskName = javaCompileTask.name
|
||||
def ajCompileTask = project.tasks.create(name: javaCompileTaskName + 'Aspect', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) {
|
||||
inputs.files(javaCompileTask.inputs.files)
|
||||
inputs.properties(javaCompileTask.inputs.properties)
|
||||
|
||||
sourceRoots.addAll(project.sourceSets.main.java.srcDirs)
|
||||
if(javaCompileTaskName.contains("Test")) {
|
||||
sourceRoots.addAll(project.sourceSets.test.java.srcDirs)
|
||||
}
|
||||
compileClasspath = javaCompileTask.classpath
|
||||
destinationDir = javaCompileTask.destinationDir
|
||||
aspectPath = project.configurations.aspectpath
|
||||
}
|
||||
|
||||
javaCompileTask.deleteAllActions()
|
||||
javaCompileTask.dependsOn ajCompileTask
|
||||
|
||||
dependsOn project.processResources
|
||||
sourceSet = project.sourceSets.main
|
||||
inputs.files(sourceSet.allSource)
|
||||
outputs.dir(sourceSet.output.classesDir)
|
||||
aspectPath = project.configurations.aspectpath
|
||||
}
|
||||
project.tasks.compileJava.deleteAllActions()
|
||||
project.tasks.compileJava.dependsOn project.tasks.compileAspect
|
||||
|
||||
|
||||
project.tasks.create(name: 'compileTestAspect', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) {
|
||||
dependsOn project.processTestResources, project.compileJava, project.jar
|
||||
sourceSet = project.sourceSets.test
|
||||
inputs.files(sourceSet.allSource)
|
||||
outputs.dir(sourceSet.output.classesDir)
|
||||
aspectPath = project.files(project.configurations.aspectpath, project.jar.archivePath)
|
||||
}
|
||||
project.tasks.compileTestJava.deleteAllActions()
|
||||
project.tasks.compileTestJava.dependsOn project.tasks.compileTestAspect
|
||||
|
||||
project.tasks.withType(GenerateEclipseProject) {
|
||||
project.eclipse.project.file.whenMerged { p ->
|
||||
@@ -91,7 +89,9 @@ class AspectJPlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
class Ajc extends DefaultTask {
|
||||
SourceSet sourceSet
|
||||
Set<File> sourceRoots = []
|
||||
FileCollection compileClasspath
|
||||
File destinationDir
|
||||
FileCollection aspectPath
|
||||
|
||||
Ajc() {
|
||||
@@ -103,15 +103,18 @@ class Ajc extends DefaultTask {
|
||||
logger.info("="*30)
|
||||
logger.info("="*30)
|
||||
logger.info("Running ajc ...")
|
||||
logger.info("classpath: ${sourceSet.compileClasspath.asPath}")
|
||||
logger.info("srcDirs $sourceSet.java.srcDirs")
|
||||
logger.info("classpath: ${compileClasspath?.files}")
|
||||
logger.info("srcDirs ${sourceRoots}")
|
||||
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: project.configurations.ajtools.asPath)
|
||||
ant.iajc(classpath: sourceSet.compileClasspath.asPath, fork: 'true', destDir: sourceSet.output.classesDir.absolutePath,
|
||||
if(sourceRoots.empty) {
|
||||
return
|
||||
}
|
||||
ant.iajc(classpath: compileClasspath.asPath, fork: 'true', destDir: destinationDir.absolutePath,
|
||||
source: project.convention.plugins.java.sourceCompatibility,
|
||||
target: project.convention.plugins.java.targetCompatibility,
|
||||
aspectPath: aspectPath.asPath, sourceRootCopyFilter: '**/*.java', showWeaveInfo: 'true') {
|
||||
sourceroots {
|
||||
sourceSet.java.srcDirs.each {
|
||||
sourceRoots.each {
|
||||
logger.info(" sourceRoot $it")
|
||||
pathelement(location: it.absolutePath)
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ dependencies {
|
||||
"org.jasig.cas.client:cas-client-core:$casClientVersion"
|
||||
|
||||
optional "net.sf.ehcache:ehcache:$ehcacheVersion",
|
||||
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion"
|
||||
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
|
||||
|
||||
testCompile "org.skyscreamer:jsonassert:$jsonassertVersion"
|
||||
|
||||
|
||||
+6
-12
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-cas</name>
|
||||
<description>spring-security-cas</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -51,13 +51,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -89,7 +89,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.4.4</version>
|
||||
<version>2.8.4</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -110,7 +110,7 @@
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -155,12 +155,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see CasJackson2Module
|
||||
* @see org.springframework.security.jackson2.SecurityJacksonModules
|
||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see CasJackson2Module
|
||||
* @see org.springframework.security.jackson2.SecurityJacksonModules
|
||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ import java.util.Collection;
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see CasJackson2Module
|
||||
* @see org.springframework.security.jackson2.SecurityJacksonModules
|
||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
|
||||
import org.jasig.cas.client.validation.AssertionImpl;
|
||||
import org.springframework.security.cas.authentication.CasAuthenticationToken;
|
||||
import org.springframework.security.jackson2.SecurityJacksonModules;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
|
||||
/**
|
||||
* Jackson module for spring-security-cas. This module register {@link AssertionImplMixin},
|
||||
@@ -34,10 +34,10 @@ import org.springframework.security.jackson2.SecurityJacksonModules;
|
||||
* ObjectMapper mapper = new ObjectMapper();
|
||||
* mapper.registerModule(new CasJackson2Module());
|
||||
* </pre>
|
||||
* <b>Note: use {@link SecurityJacksonModules#getModules(ClassLoader)} to get list of all security modules on the classpath.</b>
|
||||
* <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules on the classpath.</b>
|
||||
*
|
||||
* @author Jitendra Singh.
|
||||
* @see org.springframework.security.jackson2.SecurityJacksonModules
|
||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
public class CasJackson2Module extends SimpleModule {
|
||||
@@ -48,7 +48,7 @@ public class CasJackson2Module extends SimpleModule {
|
||||
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner());
|
||||
SecurityJackson2Modules.enableDefaultTyping((ObjectMapper) context.getOwner());
|
||||
context.setMixInAnnotations(AssertionImpl.class, AssertionImplMixin.class);
|
||||
context.setMixInAnnotations(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
|
||||
context.setMixInAnnotations(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
||||
* @return
|
||||
*/
|
||||
static Pattern createArtifactPattern(String artifactParameterName) {
|
||||
Assert.hasLength(artifactParameterName);
|
||||
Assert.hasLength(artifactParameterName, "artifactParameterName is expected to have a length");
|
||||
return Pattern.compile("&?" + Pattern.quote(artifactParameterName) + "=[^&]*");
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.jackson2.SecurityJacksonModules;
|
||||
import org.springframework.security.jackson2.SecurityJackson2Modules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -103,7 +103,7 @@ public class CasAuthenticationTokenMixinTests {
|
||||
public void setup() {
|
||||
mapper = new ObjectMapper();
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
mapper.registerModules(SecurityJacksonModules.getModules(loader));
|
||||
mapper.registerModules(SecurityJackson2Modules.getModules(loader));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -39,8 +39,8 @@ dependencies {
|
||||
"org.springframework:spring-orm:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
"org.eclipse.persistence:javax.persistence:2.0.5",
|
||||
"org.hibernate:hibernate-entitymanager:4.1.0.Final",
|
||||
"org.eclipse.persistence:javax.persistence:$javaPersistenceVersion",
|
||||
"org.hibernate:hibernate-entitymanager:$hibernateVersion",
|
||||
"org.codehaus.groovy:groovy-all:$groovyVersion",
|
||||
"org.apache.directory.server:apacheds-core:$apacheDsVersion",
|
||||
"org.apache.directory.server:apacheds-core-entry:$apacheDsVersion",
|
||||
@@ -50,7 +50,6 @@ dependencies {
|
||||
'org.apache.directory.shared:shared-ldap:0.9.15',
|
||||
'ldapsdk:ldapsdk:4.1',
|
||||
powerMockDependencies,
|
||||
"org.hibernate:hibernate-entitymanager:3.6.10.Final",
|
||||
"org.hsqldb:hsqldb:$hsqlVersion",
|
||||
spockDependencies
|
||||
|
||||
|
||||
+13
-19
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-config</name>
|
||||
<description>spring-security-config</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -51,7 +51,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -97,28 +97,28 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-messaging</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -155,7 +155,7 @@
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -239,13 +239,13 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>javax.persistence</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>4.1.0.Final</version>
|
||||
<version>5.0.11.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -359,19 +359,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap-core</artifactId>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<version>2.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -390,12 +390,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
+2
-2
@@ -86,7 +86,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
if (!namespaceMatchesVersion(element)) {
|
||||
pc.getReaderContext()
|
||||
.fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
|
||||
+ "with Spring Security 4.1. Please update your schema declarations to the 4.1 schema.",
|
||||
+ "with Spring Security 4.2. Please update your schema declarations to the 4.2 schema.",
|
||||
element);
|
||||
}
|
||||
String name = pc.getDelegate().getLocalName(element);
|
||||
@@ -221,7 +221,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
private boolean matchesVersionInternal(Element element) {
|
||||
String schemaLocation = element.getAttributeNS(
|
||||
"http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||
return schemaLocation.matches("(?m).*spring-security-4\\.1.*.xsd.*")
|
||||
return schemaLocation.matches("(?m).*spring-security-4\\.2.*.xsd.*")
|
||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||
}
|
||||
|
||||
+3
@@ -31,11 +31,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -48,6 +50,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Import(ObjectPostProcessorConfiguration.class)
|
||||
public class AuthenticationConfiguration {
|
||||
|
||||
private AtomicBoolean buildingAuthenticationManager = new AtomicBoolean();
|
||||
|
||||
+16
-32
@@ -16,19 +16,16 @@
|
||||
package org.springframework.security.config.annotation.authentication.configurers.provisioning;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.userdetails.UserDetailsServiceConfigurer;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.User.UserBuilder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.provisioning.UserDetailsManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for populating an
|
||||
@@ -82,13 +79,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* should provided. The remaining attributes have reasonable defaults.
|
||||
*/
|
||||
public class UserDetailsBuilder {
|
||||
private String username;
|
||||
private String password;
|
||||
private List<GrantedAuthority> authorities;
|
||||
private boolean accountExpired;
|
||||
private boolean accountLocked;
|
||||
private boolean credentialsExpired;
|
||||
private boolean disabled;
|
||||
private UserBuilder user;
|
||||
private final C builder;
|
||||
|
||||
/**
|
||||
@@ -117,8 +108,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
private UserDetailsBuilder username(String username) {
|
||||
Assert.notNull(username, "username cannot be null");
|
||||
this.username = username;
|
||||
this.user = User.withUsername(username);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -130,8 +120,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserDetailsBuilder password(String password) {
|
||||
Assert.notNull(password, "password cannot be null");
|
||||
this.password = password;
|
||||
this.user.password(password);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -161,14 +150,8 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserDetailsBuilder roles(String... roles) {
|
||||
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(
|
||||
roles.length);
|
||||
for (String role : roles) {
|
||||
Assert.isTrue(!role.startsWith("ROLE_"), role
|
||||
+ " cannot start with ROLE_ (it is automatically added)");
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
|
||||
}
|
||||
return authorities(authorities);
|
||||
this.user.roles(roles);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +164,8 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserDetailsBuilder authorities(GrantedAuthority... authorities) {
|
||||
return authorities(Arrays.asList(authorities));
|
||||
this.user.authorities(authorities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +178,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserDetailsBuilder authorities(List<? extends GrantedAuthority> authorities) {
|
||||
this.authorities = new ArrayList<GrantedAuthority>(authorities);
|
||||
this.user.authorities(authorities);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -208,7 +192,8 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserDetailsBuilder authorities(String... authorities) {
|
||||
return authorities(AuthorityUtils.createAuthorityList(authorities));
|
||||
this.user.authorities(authorities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +204,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserDetailsBuilder accountExpired(boolean accountExpired) {
|
||||
this.accountExpired = accountExpired;
|
||||
this.user.accountExpired(accountExpired);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -231,7 +216,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserDetailsBuilder accountLocked(boolean accountLocked) {
|
||||
this.accountLocked = accountLocked;
|
||||
this.user.accountLocked(accountLocked);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -243,7 +228,7 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserDetailsBuilder credentialsExpired(boolean credentialsExpired) {
|
||||
this.credentialsExpired = credentialsExpired;
|
||||
this.user.credentialsExpired(credentialsExpired);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -255,13 +240,12 @@ public class UserDetailsManagerConfigurer<B extends ProviderManagerBuilder<B>, C
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserDetailsBuilder disabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
this.user.disabled(disabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
private UserDetails build() {
|
||||
return new User(username, password, !disabled, !accountExpired,
|
||||
!credentialsExpired, !accountLocked, authorities);
|
||||
return this.user.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -25,7 +25,6 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -45,7 +44,7 @@ import org.springframework.security.config.annotation.configuration.ObjectPostPr
|
||||
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value = { java.lang.annotation.ElementType.TYPE })
|
||||
@Documented
|
||||
@Import({ GlobalMethodSecuritySelector.class, ObjectPostProcessorConfiguration.class })
|
||||
@Import({ GlobalMethodSecuritySelector.class })
|
||||
@EnableGlobalAuthentication
|
||||
@Configuration
|
||||
public @interface EnableGlobalMethodSecurity {
|
||||
|
||||
-1
@@ -49,7 +49,6 @@ import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.access.intercept.AfterInvocationManager;
|
||||
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
|
||||
import org.springframework.security.access.intercept.RunAsManager;
|
||||
import org.springframework.security.access.intercept.RunAsManagerImpl;
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
|
||||
|
||||
+1
-2
@@ -22,7 +22,6 @@ import java.lang.annotation.Target;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
|
||||
/**
|
||||
@@ -73,7 +72,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,
|
||||
@Import({ WebSecurityConfiguration.class,
|
||||
SpringWebMvcImportSelector.class })
|
||||
@EnableGlobalAuthentication
|
||||
@Configuration
|
||||
|
||||
+17
-4
@@ -15,7 +15,14 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.expression.BeanResolver;
|
||||
import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
|
||||
import org.springframework.security.web.method.annotation.CsrfTokenArgumentResolver;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
@@ -24,8 +31,6 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring Security CSRF
|
||||
* integration. This configuration is added whenever {@link EnableWebMvc} is added by
|
||||
@@ -36,12 +41,15 @@ import java.util.List;
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter implements ApplicationContextAware {
|
||||
private BeanResolver beanResolver;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
|
||||
AuthenticationPrincipalArgumentResolver authenticationPrincipalResolver = new AuthenticationPrincipalArgumentResolver();
|
||||
authenticationPrincipalResolver.setBeanResolver(beanResolver);
|
||||
argumentResolvers.add(authenticationPrincipalResolver);
|
||||
argumentResolvers
|
||||
.add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver());
|
||||
argumentResolvers.add(new CsrfTokenArgumentResolver());
|
||||
@@ -51,4 +59,9 @@ class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
public RequestDataValueProcessor requestDataValueProcessor() {
|
||||
return new CsrfRequestDataValueProcessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.beanResolver = new BeanFactoryResolver(applicationContext.getAutowireCapableBeanFactory());
|
||||
}
|
||||
}
|
||||
+27
-2
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
@@ -44,6 +45,7 @@ import org.springframework.security.config.annotation.authentication.configurati
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -59,8 +61,23 @@ import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
/**
|
||||
* Provides a convenient base class for creating a {@link WebSecurityConfigurer} instance.
|
||||
* The implementation allows customization by overriding methods.
|
||||
* Provides a convenient base class for creating a {@link WebSecurityConfigurer}
|
||||
* instance. The implementation allows customization by overriding methods.
|
||||
*
|
||||
* <p>
|
||||
* Will automatically apply the result of looking up
|
||||
* {@link AbstractHttpConfigurer} from {@link SpringFactoriesLoader} to allow
|
||||
* developers to extend the defaults.
|
||||
* To do this, you must create a class that extends AbstractHttpConfigurer and then create a file in the classpath at "META-INF/spring.factories" that looks something like:
|
||||
* </p>
|
||||
* <pre>
|
||||
* org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer
|
||||
* </pre>
|
||||
* If you have multiple classes that should be added you can use "," to separate the values. For example:
|
||||
*
|
||||
* <pre>
|
||||
* org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer, sample.OtherThatExtendsAbstractHttpConfigurer
|
||||
* </pre>
|
||||
*
|
||||
* @see EnableWebSecurity
|
||||
*
|
||||
@@ -165,6 +182,7 @@ public abstract class WebSecurityConfigurerAdapter implements
|
||||
* ] * @return the {@link HttpSecurity}
|
||||
* @throws Exception
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected final HttpSecurity getHttp() throws Exception {
|
||||
if (http != null) {
|
||||
return http;
|
||||
@@ -195,6 +213,13 @@ public abstract class WebSecurityConfigurerAdapter implements
|
||||
.apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()
|
||||
.logout();
|
||||
// @formatter:on
|
||||
ClassLoader classLoader = this.context.getClassLoader();
|
||||
List<AbstractHttpConfigurer> defaultHttpConfigurers =
|
||||
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
|
||||
|
||||
for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
|
||||
http.apply(configurer);
|
||||
}
|
||||
}
|
||||
configure(http);
|
||||
return http;
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
|
||||
public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
|
||||
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {
|
||||
|
||||
/**
|
||||
|
||||
+69
@@ -28,6 +28,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||
import org.springframework.security.web.header.HeaderWriter;
|
||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||
import org.springframework.security.web.header.writers.*;
|
||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
@@ -56,6 +57,7 @@ import org.springframework.util.Assert;
|
||||
* @author Rob Winch
|
||||
* @author Tim Ysewyn
|
||||
* @author Joe Grandja
|
||||
* @author Eddú Meléndez
|
||||
* @since 3.2
|
||||
*/
|
||||
public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
@@ -78,6 +80,8 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
|
||||
private final ContentSecurityPolicyConfig contentSecurityPolicy = new ContentSecurityPolicyConfig();
|
||||
|
||||
private final ReferrerPolicyConfig referrerPolicy = new ReferrerPolicyConfig();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
@@ -770,6 +774,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
addIfNotNull(writers, frameOptions.writer);
|
||||
addIfNotNull(writers, hpkp.writer);
|
||||
addIfNotNull(writers, contentSecurityPolicy.writer);
|
||||
addIfNotNull(writers, referrerPolicy.writer);
|
||||
writers.addAll(headerWriters);
|
||||
return writers;
|
||||
}
|
||||
@@ -779,4 +784,68 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer Policy</a>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing
|
||||
* of the header as detailed in the W3C Technical Report:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Referrer-Policy</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Default value is:</p>
|
||||
*
|
||||
* <pre>
|
||||
* Referrer-Policy: no-referrer
|
||||
* </pre>
|
||||
*
|
||||
* @see ReferrerPolicyHeaderWriter
|
||||
* @since 4.2
|
||||
* @return the ReferrerPolicyConfig for additional configuration
|
||||
*/
|
||||
public ReferrerPolicyConfig referrerPolicy() {
|
||||
this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter();
|
||||
return this.referrerPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer Policy</a>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing
|
||||
* of the header as detailed in the W3C Technical Report:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Referrer-Policy</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see ReferrerPolicyHeaderWriter
|
||||
* @since 4.2
|
||||
* @return the ReferrerPolicyConfig for additional configuration
|
||||
* @throws IllegalArgumentException if policy is null or empty
|
||||
*/
|
||||
public ReferrerPolicyConfig referrerPolicy(ReferrerPolicy policy) {
|
||||
this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(policy);
|
||||
return this.referrerPolicy;
|
||||
}
|
||||
|
||||
public final class ReferrerPolicyConfig {
|
||||
|
||||
private ReferrerPolicyHeaderWriter writer;
|
||||
|
||||
private ReferrerPolicyConfig() {
|
||||
}
|
||||
|
||||
public HeadersConfigurer<H> and() {
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -481,7 +481,7 @@ final class AuthenticationConfigBuilder {
|
||||
SimpleAttributes2GrantedAuthoritiesMapper.class));
|
||||
|
||||
String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES);
|
||||
Assert.state(StringUtils.hasText(roles));
|
||||
Assert.hasLength(roles, "roles is expected to have length");
|
||||
BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(StringUtils.class);
|
||||
rolesBuilder.addConstructorArgValue(roles);
|
||||
|
||||
+12
-7
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
@@ -99,7 +102,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
||||
MatcherType matcherType = MatcherType.fromElement(httpElt);
|
||||
boolean useExpressions = isUseExpressions(httpElt);
|
||||
|
||||
ManagedMap<BeanDefinition, BeanDefinition> requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap(
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> requestToAttributesMap = parseInterceptUrlsForFilterInvocationRequestMap(
|
||||
matcherType, interceptUrls, useExpressions, addAllAuth, pc);
|
||||
BeanDefinitionBuilder fidsBuilder;
|
||||
|
||||
@@ -148,11 +151,11 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
||||
return !StringUtils.hasText(useExpressions) || "true".equals(useExpressions);
|
||||
}
|
||||
|
||||
private static ManagedMap<BeanDefinition, BeanDefinition> parseInterceptUrlsForFilterInvocationRequestMap(
|
||||
private static ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForFilterInvocationRequestMap(
|
||||
MatcherType matcherType, List<Element> urlElts, boolean useExpressions,
|
||||
boolean addAuthenticatedAll, ParserContext parserContext) {
|
||||
|
||||
ManagedMap<BeanDefinition, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<BeanDefinition, BeanDefinition>();
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<BeanMetadataElement, BeanDefinition>();
|
||||
|
||||
for (Element urlElt : urlElts) {
|
||||
String access = urlElt.getAttribute(ATT_ACCESS);
|
||||
@@ -161,8 +164,10 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
||||
}
|
||||
|
||||
String path = urlElt.getAttribute(ATT_PATTERN);
|
||||
String matcherRef = urlElt.getAttribute(ATT_REQUEST_MATCHER_REF);
|
||||
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
|
||||
|
||||
if (!StringUtils.hasText(path)) {
|
||||
if (!hasMatcherRef && !StringUtils.hasText(path)) {
|
||||
parserContext.getReaderContext().error(
|
||||
"path attribute cannot be empty or null", urlElt);
|
||||
}
|
||||
@@ -180,7 +185,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
||||
ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt);
|
||||
}
|
||||
|
||||
BeanDefinition matcher = matcherType.createMatcher(parserContext, path,
|
||||
BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(parserContext, path,
|
||||
method, servletPath);
|
||||
BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(SecurityConfig.class);
|
||||
@@ -189,7 +194,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
||||
logger.info("Creating access control expression attribute '" + access
|
||||
+ "' for " + path);
|
||||
// The single expression will be parsed later by the
|
||||
// ExpressionFilterInvocationSecurityMetadataSource
|
||||
// ExpressionBasedFilterInvocationSecurityMetadataSource
|
||||
attributeBuilder.addConstructorArgValue(new String[] { access });
|
||||
attributeBuilder.setFactoryMethod("createList");
|
||||
|
||||
|
||||
+22
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||
import org.springframework.security.web.header.writers.*;
|
||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.RegExpAllowFromStrategy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.WhiteListedAllowFromStrategy;
|
||||
@@ -45,6 +46,7 @@ import org.w3c.dom.Node;
|
||||
*
|
||||
* @author Marten Deinum
|
||||
* @author Tim Ysewyn
|
||||
* @author Eddú Meléndez
|
||||
* @since 3.2
|
||||
*/
|
||||
public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
@@ -82,6 +84,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private static final String GENERIC_HEADER_ELEMENT = "header";
|
||||
|
||||
private static final String CONTENT_SECURITY_POLICY_ELEMENT = "content-security-policy";
|
||||
private static final String REFERRER_POLICY_ELEMENT = "referrer-policy";
|
||||
|
||||
private static final String ALLOW_FROM = "ALLOW-FROM";
|
||||
|
||||
@@ -109,6 +112,8 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
parseContentSecurityPolicyElement(disabled, element, parserContext);
|
||||
|
||||
parseReferrerPolicyElement(element, parserContext);
|
||||
|
||||
parseHeaderElements(element);
|
||||
|
||||
boolean noWriters = headerWriters.isEmpty();
|
||||
@@ -291,6 +296,23 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void parseReferrerPolicyElement(Element element, ParserContext context) {
|
||||
Element referrerPolicyElement = (element == null) ? null : DomUtils.getChildElementByTagName(element, REFERRER_POLICY_ELEMENT);
|
||||
if (referrerPolicyElement != null) {
|
||||
addReferrerPolicy(referrerPolicyElement, context);
|
||||
}
|
||||
}
|
||||
|
||||
private void addReferrerPolicy(Element referrerPolicyElement, ParserContext context) {
|
||||
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(ReferrerPolicyHeaderWriter.class);
|
||||
|
||||
String policy = referrerPolicyElement.getAttribute(ATT_POLICY);
|
||||
if (StringUtils.hasLength(policy)) {
|
||||
headersWriter.addConstructorArgValue(ReferrerPolicy.get(policy));
|
||||
}
|
||||
headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void attrNotAllowed(ParserContext context, String attrName,
|
||||
String otherAttrName, Element element) {
|
||||
context.getReaderContext().error(
|
||||
|
||||
+8
-5
@@ -80,6 +80,7 @@ import org.springframework.util.xml.DomUtils;
|
||||
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_FILTERS;
|
||||
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_HTTP_METHOD;
|
||||
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN;
|
||||
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF;
|
||||
import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL;
|
||||
import static org.springframework.security.config.http.SecurityFilters.CHANNEL_FILTER;
|
||||
import static org.springframework.security.config.http.SecurityFilters.CONCURRENT_SESSION_FILTER;
|
||||
@@ -582,7 +583,7 @@ class HttpConfigurationBuilder {
|
||||
}
|
||||
|
||||
private void createChannelProcessingFilter() {
|
||||
ManagedMap<BeanDefinition, BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = parseInterceptUrlsForChannelSecurity();
|
||||
|
||||
if (channelRequestMap.isEmpty()) {
|
||||
return;
|
||||
@@ -636,15 +637,17 @@ class HttpConfigurationBuilder {
|
||||
* will be empty unless the <tt>requires-channel</tt> attribute has been used on a URL
|
||||
* path.
|
||||
*/
|
||||
private ManagedMap<BeanDefinition, BeanDefinition> parseInterceptUrlsForChannelSecurity() {
|
||||
private ManagedMap<BeanMetadataElement, BeanDefinition> parseInterceptUrlsForChannelSecurity() {
|
||||
|
||||
ManagedMap<BeanDefinition, BeanDefinition> channelRequestMap = new ManagedMap<BeanDefinition, BeanDefinition>();
|
||||
ManagedMap<BeanMetadataElement, BeanDefinition> channelRequestMap = new ManagedMap<BeanMetadataElement, BeanDefinition>();
|
||||
|
||||
for (Element urlElt : interceptUrls) {
|
||||
String path = urlElt.getAttribute(ATT_PATH_PATTERN);
|
||||
String method = urlElt.getAttribute(ATT_HTTP_METHOD);
|
||||
String matcherRef = urlElt.getAttribute(ATT_REQUEST_MATCHER_REF);
|
||||
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
|
||||
|
||||
if (!StringUtils.hasText(path)) {
|
||||
if (!hasMatcherRef && !StringUtils.hasText(path)) {
|
||||
pc.getReaderContext().error("pattern attribute cannot be empty or null",
|
||||
urlElt);
|
||||
}
|
||||
@@ -652,7 +655,7 @@ class HttpConfigurationBuilder {
|
||||
String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL);
|
||||
|
||||
if (StringUtils.hasText(requiredChannel)) {
|
||||
BeanDefinition matcher = matcherType.createMatcher(pc, path, method);
|
||||
BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(pc, path, method);
|
||||
|
||||
RootBeanDefinition channelAttributes = new RootBeanDefinition(
|
||||
ChannelAttributeFactory.class);
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
.getLog(HttpSecurityBeanDefinitionParser.class);
|
||||
|
||||
private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";
|
||||
private static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
|
||||
static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";
|
||||
static final String ATT_PATH_PATTERN = "pattern";
|
||||
static final String ATT_HTTP_METHOD = "method";
|
||||
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
||||
}
|
||||
|
||||
public void setPointcutMap(Map<String, List<ConfigAttribute>> map) {
|
||||
Assert.notEmpty(map);
|
||||
Assert.notEmpty(map, "configAttributes cannot be empty");
|
||||
for (String expression : map.keySet()) {
|
||||
List<ConfigAttribute> value = map.get(expression);
|
||||
addPointcut(expression, value);
|
||||
|
||||
+8
-8
@@ -255,8 +255,8 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
|
||||
for (String beanName : beanNames) {
|
||||
BeanDefinition bd = registry.getBeanDefinition(beanName);
|
||||
String beanClassName = bd.getBeanClassName();
|
||||
if (beanClassName.equals(SimpAnnotationMethodMessageHandler.class
|
||||
.getName()) || beanClassName.equals(WEB_SOCKET_AMMH_CLASS_NAME)) {
|
||||
if (SimpAnnotationMethodMessageHandler.class.getName().equals(beanClassName) ||
|
||||
WEB_SOCKET_AMMH_CLASS_NAME.equals(beanClassName)) {
|
||||
PropertyValue current = bd.getPropertyValues().getPropertyValue(
|
||||
CUSTOM_ARG_RESOLVERS_PROP);
|
||||
ManagedList<Object> argResolvers = new ManagedList<Object>();
|
||||
@@ -275,16 +275,16 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (beanClassName
|
||||
.equals("org.springframework.web.socket.server.support.WebSocketHttpRequestHandler")) {
|
||||
else if ("org.springframework.web.socket.server.support.WebSocketHttpRequestHandler"
|
||||
.equals(beanClassName)) {
|
||||
addCsrfTokenHandshakeInterceptor(bd);
|
||||
}
|
||||
else if (beanClassName
|
||||
.equals("org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService")) {
|
||||
else if ("org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService"
|
||||
.equals(beanClassName)) {
|
||||
addCsrfTokenHandshakeInterceptor(bd);
|
||||
}
|
||||
else if (beanClassName
|
||||
.equals("org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService")) {
|
||||
else if ("org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService"
|
||||
.equals(beanClassName)) {
|
||||
addCsrfTokenHandshakeInterceptor(bd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-4.1.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-4.2.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-4.2.xsd=org/springframework/security/config/spring-security-4.2.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-4.1.xsd=org/springframework/security/config/spring-security-4.1.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-4.0.xsd=org/springframework/security/config/spring-security-4.0.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-3.2.xsd=org/springframework/security/config/spring-security-3.2.xsd
|
||||
|
||||
+10
-7
@@ -366,8 +366,7 @@ intercept-url =
|
||||
## Specifies the access attributes and/or filter list for a particular set of URLs.
|
||||
element intercept-url {intercept-url.attlist, empty}
|
||||
intercept-url.attlist &=
|
||||
## The pattern which defines the URL path. The content will depend on the type set in the containing http element, so will default to ant path syntax.
|
||||
attribute pattern {xsd:token}
|
||||
(pattern | request-matcher-ref)
|
||||
intercept-url.attlist &=
|
||||
## The access configuration attributes that apply for the configured path.
|
||||
attribute access {xsd:token}?
|
||||
@@ -508,9 +507,6 @@ fsmds.attlist &=
|
||||
use-expressions?
|
||||
fsmds.attlist &=
|
||||
id?
|
||||
fsmds.attlist &=
|
||||
## Compare after forcing to lowercase
|
||||
attribute lowercase-comparisons {xsd:boolean}?
|
||||
fsmds.attlist &=
|
||||
request-matcher?
|
||||
|
||||
@@ -551,7 +547,7 @@ concurrency-control =
|
||||
element concurrency-control {concurrency-control.attlist, empty}
|
||||
|
||||
concurrency-control.attlist &=
|
||||
## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimitted sessions.
|
||||
## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimited sessions.
|
||||
attribute max-sessions {xsd:integer}?
|
||||
concurrency-control.attlist &=
|
||||
## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again.
|
||||
@@ -757,7 +753,7 @@ csrf-options.attlist &=
|
||||
|
||||
headers =
|
||||
## Element for configuration of the HeaderWritersFilter. Enables easy setting for the X-Frame-Options, X-XSS-Protection and X-Content-Type-Options headers.
|
||||
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & header*)}
|
||||
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & referrer-policy? & header*)}
|
||||
headers-options.attlist &=
|
||||
## Specifies if the default headers should be disabled. Default false.
|
||||
attribute defaults-disabled {xsd:boolean}?
|
||||
@@ -828,6 +824,13 @@ csp-options.attlist &=
|
||||
## Set to true, to enable the Content-Security-Policy-Report-Only header for reporting policy violations only. Defaults to false.
|
||||
attribute report-only {xsd:boolean}?
|
||||
|
||||
referrer-policy =
|
||||
## Adds support for Referrer Policy
|
||||
element referrer-policy {referrer-options.attlist}
|
||||
referrer-options.attlist &=
|
||||
## The policies for the Referrer-Policy header.
|
||||
attribute policy {"no-referrer","no-referrer-when-downgrade","same-origin","origin","strict-origin","origin-when-cross-origin","strict-origin-when-cross-origin","unsafe-url"}?
|
||||
|
||||
cache-control =
|
||||
## Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for every request
|
||||
element cache-control {cache-control.attlist}
|
||||
|
||||
+39
-10
@@ -1292,10 +1292,15 @@
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:attributeGroup name="intercept-url.attlist">
|
||||
<xs:attribute name="pattern" use="required" type="xs:token">
|
||||
<xs:attribute name="pattern" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The pattern which defines the URL path. The content will depend on the type set in the
|
||||
containing http element, so will default to ant path syntax.
|
||||
<xs:documentation>The request URL pattern which will be mapped to the FilterChain.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="request-matcher-ref" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Allows a RequestMatcher instance to be used, as an alternative to pattern-matching.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
@@ -1673,12 +1678,6 @@
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lowercase-comparisons" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Compare after forcing to lowercase
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="request-matcher">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
|
||||
@@ -1773,7 +1772,7 @@
|
||||
<xs:attribute name="max-sessions" type="xs:integer">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The maximum number of sessions a single authenticated user can have open at the same time.
|
||||
Defaults to "1". A negative value denotes unlimitted sessions.
|
||||
Defaults to "1". A negative value denotes unlimited sessions.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
@@ -2358,6 +2357,7 @@
|
||||
<xs:element ref="security:content-type-options"/>
|
||||
<xs:element ref="security:hpkp"/>
|
||||
<xs:element ref="security:content-security-policy"/>
|
||||
<xs:element ref="security:referrer-policy"/>
|
||||
<xs:element ref="security:header"/>
|
||||
</xs:choice>
|
||||
<xs:attributeGroup ref="security:headers-options.attlist"/>
|
||||
@@ -2540,6 +2540,35 @@
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="referrer-policy">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds support for Referrer Policy
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:attributeGroup ref="security:referrer-options.attlist"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:attributeGroup name="referrer-options.attlist">
|
||||
<xs:attribute name="policy">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The policies for the Referrer-Policy header.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="no-referrer"/>
|
||||
<xs:enumeration value="no-referrer-when-downgrade"/>
|
||||
<xs:enumeration value="same-origin"/>
|
||||
<xs:enumeration value="origin"/>
|
||||
<xs:enumeration value="strict-origin"/>
|
||||
<xs:enumeration value="origin-when-cross-origin"/>
|
||||
<xs:enumeration value="strict-origin-when-cross-origin"/>
|
||||
<xs:enumeration value="unsafe-url"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="cache-control">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for
|
||||
|
||||
+44
@@ -20,12 +20,14 @@ import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
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 static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Tim Ysewyn
|
||||
* @author Joe Grandja
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@@ -453,4 +455,46 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "headers.referrerPolicy default"() {
|
||||
setup:
|
||||
loadConfig(ReferrerPolicyDefaultConfig)
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Referrer-Policy': 'no-referrer']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class ReferrerPolicyDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.referrerPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
def "headers.referrerPolicy custom"() {
|
||||
setup:
|
||||
loadConfig(ReferrerPolicyCustomConfig)
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Referrer-Policy': 'same-origin']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class ReferrerPolicyCustomConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.referrerPolicy(ReferrerPolicy.SAME_ORIGIN);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
@@ -920,6 +920,38 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def 'http headers defaults : referrer-policy'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'referrer-policy'()
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, ['Referrer-Policy': 'no-referrer'])
|
||||
}
|
||||
|
||||
def 'http headers defaults : referrer-policy same-origin'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'referrer-policy'('policy': 'same-origin')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, ['Referrer-Policy': 'same-origin'])
|
||||
}
|
||||
|
||||
def assertHeaders(MockHttpServletResponse response, Map<String,String> expected) {
|
||||
assert response.headerNames == expected.keySet()
|
||||
expected.each { headerName, value ->
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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.authentication.configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class EnableGlobalAuthenticationTests {
|
||||
@Autowired
|
||||
AuthenticationConfiguration auth;
|
||||
|
||||
// gh-4086
|
||||
@Test
|
||||
public void authenticationConfigurationWhenGetAuthenticationManagerThenNotNull() throws Exception {
|
||||
assertThat(auth.getAuthenticationManager()).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalAuthentication
|
||||
static class Config {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
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.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class HttpSecurityHeadersTests {
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
@Autowired
|
||||
Filter springSecurityFilterChain;
|
||||
|
||||
MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup(wac)
|
||||
.addFilters(springSecurityFilterChain)
|
||||
.build();
|
||||
}
|
||||
|
||||
// gh-2953
|
||||
// gh-3975
|
||||
@Test
|
||||
public void headerWhenSpringMvcResourceThenCacheRelatedHeadersReset() throws Exception {
|
||||
mockMvc.perform(get("/resources/file.js"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.CACHE_CONTROL,"max-age=12345"))
|
||||
.andExpect(header().string(HttpHeaders.PRAGMA, ""))
|
||||
.andExpect(header().string(HttpHeaders.EXPIRES, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerWhenNotSpringResourceThenCacheRelatedHeadersSet() throws Exception {
|
||||
mockMvc.perform(get("/notresource"))
|
||||
.andExpect(header().string(HttpHeaders.CACHE_CONTROL,"no-cache, no-store, max-age=0, must-revalidate"))
|
||||
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
|
||||
.andExpect(header().string(HttpHeaders.EXPIRES, "0"));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
static class WebMvcConfig extends WebMvcConfigurerAdapter {
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/").setCachePeriod(12345);
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.powermock.api.mockito.PowerMockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
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.core.io.support.SpringFactoriesLoader;
|
||||
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.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({ SpringFactoriesLoader.class })
|
||||
public class WebSecurityConfigurerAdapterPowermockTests {
|
||||
ConfigurableWebApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if(context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadConfigWhenDefaultConfigurerAsSpringFactoryhenDefaultConfigurerApplied() {
|
||||
spy(SpringFactoriesLoader.class);
|
||||
DefaultConfigurer configurer = new DefaultConfigurer();
|
||||
when(SpringFactoriesLoader
|
||||
.loadFactories(AbstractHttpConfigurer.class, getClass().getClassLoader()))
|
||||
.thenReturn(Arrays.<AbstractHttpConfigurer>asList(configurer));
|
||||
|
||||
loadConfig(Config.class);
|
||||
|
||||
assertThat(configurer.init).isTrue();
|
||||
assertThat(configurer.configure).isTrue();
|
||||
}
|
||||
|
||||
private void loadConfig(Class<?>... classes) {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.setClassLoader(getClass().getClassLoader());
|
||||
context.register(classes);
|
||||
context.refresh();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class Config extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer,HttpSecurity> {
|
||||
boolean init;
|
||||
boolean configure;
|
||||
|
||||
@Override
|
||||
public void init(HttpSecurity builder) throws Exception {
|
||||
this.init = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity builder) throws Exception {
|
||||
this.configure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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 static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class AuthenticationPrincipalArgumentResolverTests {
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationPrincipalExpressionWhenBeanExpressionSuppliedThenBeanUsed() throws Exception {
|
||||
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()));
|
||||
SecurityContextHolder.setContext(context);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup(wac)
|
||||
.build();
|
||||
|
||||
mockMvc.perform(get("/users/self"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("extracted-user"));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc
|
||||
static class Config {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UsernameExtractor usernameExtractor() {
|
||||
return new UsernameExtractor();
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class UserController {
|
||||
@GetMapping("/users/self")
|
||||
public String usersSelf(@AuthenticationPrincipal(expression = "@usernameExtractor.extract(#this)") String userName) {
|
||||
return userName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class UsernameExtractor {
|
||||
public String extract(User u) {
|
||||
return "extracted-" + u.getUsername();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -444,7 +444,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
|
||||
// @formatter:on
|
||||
|
||||
@Bean
|
||||
public SecurityExpressionHandler<Message<Object>> messageSecurityExpressionHandler() {
|
||||
public static SecurityExpressionHandler<Message<Object>> messageSecurityExpressionHandler() {
|
||||
return new DefaultMessageSecurityExpressionHandler<Object>() {
|
||||
@Override
|
||||
protected SecurityExpressionOperations createSecurityExpressionRoot(
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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.http;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
|
||||
public class HttpInterceptUrlTests {
|
||||
ConfigurableWebApplicationContext context;
|
||||
|
||||
MockMvc mockMvc;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if(context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interceptUrlWhenRequestMatcherRefThenWorks() throws Exception {
|
||||
loadConfig("interceptUrlWhenRequestMatcherRefThenWorks.xml");
|
||||
|
||||
mockMvc.perform(get("/foo"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
mockMvc.perform(get("/FOO"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
mockMvc.perform(get("/other"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
private void loadConfig(String... configLocations) {
|
||||
for(int i=0;i<configLocations.length;i++) {
|
||||
configLocations[i] = getClass().getName().replaceAll("\\.", "/") + "-" + configLocations[i];
|
||||
}
|
||||
XmlWebApplicationContext context = new XmlWebApplicationContext();
|
||||
context.setConfigLocations(configLocations);
|
||||
context.setServletContext(new MockServletContext());
|
||||
context.refresh();
|
||||
this.context = context;
|
||||
|
||||
context.getAutowireCapableBeanFactory().autowireBean(this);
|
||||
|
||||
Filter springSecurityFilterChain = context.getBean("springSecurityFilterChain", Filter.class);
|
||||
mockMvc = MockMvcBuilders
|
||||
.standaloneSetup(new FooController())
|
||||
.addFilters(springSecurityFilterChain)
|
||||
.build();
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class FooController {
|
||||
@GetMapping("/*")
|
||||
String foo() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
|
||||
+ "http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-";
|
||||
static final String BEANS_CLOSE = "</b:beans>\n";
|
||||
|
||||
static final String SPRING_SECURITY_VERSION = "4.1";
|
||||
static final String SPRING_SECURITY_VERSION = "4.2";
|
||||
|
||||
Resource inMemoryXml;
|
||||
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.websocket;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
|
||||
public class MessageSecurityPostProcessorTest {
|
||||
|
||||
private WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor postProcessor =
|
||||
new WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor("id", false);
|
||||
|
||||
@Test
|
||||
public void handlesBeansWithoutClass() {
|
||||
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
registry.registerBeanDefinition("beanWithoutClass", new GenericBeanDefinition());
|
||||
postProcessor.postProcessBeanDefinitionRegistry(registry);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:c="http://www.springframework.org/schema/c"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http>
|
||||
<http-basic/>
|
||||
<intercept-url request-matcher-ref="matcherRef" access="denyAll"/>
|
||||
</http>
|
||||
|
||||
<user-service>
|
||||
<user name="user" password="password" authorities="ROLE_USER"/>
|
||||
</user-service>
|
||||
|
||||
<b:bean id="matcherRef" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
|
||||
c:pattern="/foo"
|
||||
c:httpMethod="GET"
|
||||
c:caseSensitive="false"/>
|
||||
</b:beans>
|
||||
@@ -131,7 +131,7 @@
|
||||
<constructor-arg ref="fooMatcher"/>
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<ref local="mockFilter"/>
|
||||
<ref bean="mockFilter"/>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
@@ -143,9 +143,9 @@
|
||||
</constructor-arg>
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<ref local="sif"/>
|
||||
<ref local="mockFilter"/>
|
||||
<ref local="mockFilter2"/>
|
||||
<ref bean="sif"/>
|
||||
<ref bean="mockFilter"/>
|
||||
<ref bean="mockFilter2"/>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
@@ -167,9 +167,9 @@
|
||||
</constructor-arg>
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<ref local="sif"/>
|
||||
<ref local="apf"/>
|
||||
<ref local="mockFilter"/>
|
||||
<ref bean="sif"/>
|
||||
<ref bean="apf"/>
|
||||
<ref bean="mockFilter"/>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
var f = 1;
|
||||
+1
-1
@@ -25,7 +25,7 @@ dependencies {
|
||||
"org.aspectj:aspectjrt:$aspectjVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatavindVersion"
|
||||
"com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
|
||||
|
||||
included cryptoProject
|
||||
|
||||
|
||||
+3
-9
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-core</name>
|
||||
<description>spring-security-core</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -82,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.4.4</version>
|
||||
<version>2.8.4</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -294,12 +294,6 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public class SecuredAnnotationSecurityMetadataSource extends
|
||||
|
||||
public SecuredAnnotationSecurityMetadataSource(
|
||||
AnnotationMetadataExtractor annotationMetadataExtractor) {
|
||||
Assert.notNull(annotationMetadataExtractor);
|
||||
Assert.notNull(annotationMetadataExtractor, "annotationMetadataExtractor cannot be null");
|
||||
annotationExtractor = annotationMetadataExtractor;
|
||||
annotationType = (Class<? extends Annotation>) GenericTypeResolver
|
||||
.resolveTypeArgument(annotationExtractor.getClass(),
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider,
|
||||
private String key;
|
||||
|
||||
public RememberMeAuthenticationProvider(String key) {
|
||||
Assert.hasLength(key);
|
||||
Assert.hasLength(key, "key must have a length");
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -35,13 +35,12 @@ class PasswordEncoderUtils {
|
||||
byte[] actualBytes = bytesUtf8(actual);
|
||||
int expectedLength = expectedBytes == null ? -1 : expectedBytes.length;
|
||||
int actualLength = actualBytes == null ? -1 : actualBytes.length;
|
||||
if (expectedLength != actualLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
for (int i = 0; i < expectedLength; i++) {
|
||||
result |= expectedBytes[i] ^ actualBytes[i];
|
||||
int result = expectedLength == actualLength ? 0 : 1;
|
||||
for (int i = 0; i < actualLength; i++) {
|
||||
byte expectedByte = expectedLength <= 0 ? 0 : expectedBytes[i % expectedLength];
|
||||
byte actualByte = actualBytes[i % actualLength];
|
||||
result |= expectedByte ^ actualByte;
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
@@ -51,7 +50,7 @@ class PasswordEncoderUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Utf8.encode(s);
|
||||
return Utf8.encode(s); // need to check if Utf8.encode() runs in constant time (probably not). This may leak length of string.
|
||||
}
|
||||
|
||||
private PasswordEncoderUtils() {
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticatio
|
||||
public InteractiveAuthenticationSuccessEvent(Authentication authentication,
|
||||
Class<?> generatedBy) {
|
||||
super(authentication);
|
||||
Assert.notNull(generatedBy);
|
||||
Assert.notNull(generatedBy, "generatedBy cannot be null");
|
||||
this.generatedBy = generatedBy;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class SpringSecurityCoreVersion {
|
||||
*/
|
||||
public static final long SERIAL_VERSION_UID = 420L;
|
||||
|
||||
static final String MIN_SPRING_VERSION = "4.3.2.RELEASE";
|
||||
static final String MIN_SPRING_VERSION = "4.3.5.RELEASE";
|
||||
|
||||
static {
|
||||
performVersionChecks();
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
package org.springframework.security.core.context;
|
||||
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
@@ -93,7 +94,7 @@ public class SecurityContextHolder {
|
||||
}
|
||||
|
||||
private static void initialize() {
|
||||
if ((strategyName == null) || "".equals(strategyName)) {
|
||||
if (!StringUtils.hasText(strategyName)) {
|
||||
// Set default
|
||||
strategyName = MODE_THREADLOCAL;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
package org.springframework.security.core.userdetails;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
@@ -27,6 +30,8 @@ import java.util.TreeSet;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.CredentialsContainer;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -238,4 +243,183 @@ public class User implements UserDetails, CredentialsContainer {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static UserBuilder withUsername(String username) {
|
||||
return new UserBuilder().username(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the user to be added. At minimum the username, password, and authorities
|
||||
* should provided. The remaining attributes have reasonable defaults.
|
||||
*/
|
||||
public static class UserBuilder {
|
||||
private String username;
|
||||
private String password;
|
||||
private List<GrantedAuthority> authorities;
|
||||
private boolean accountExpired;
|
||||
private boolean accountLocked;
|
||||
private boolean credentialsExpired;
|
||||
private boolean disabled;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*/
|
||||
private UserBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the username. This attribute is required.
|
||||
*
|
||||
* @param username the username. Cannot be null.
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
private UserBuilder username(String username) {
|
||||
Assert.notNull(username, "username cannot be null");
|
||||
this.username = username;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the password. This attribute is required.
|
||||
*
|
||||
* @param password the password. Cannot be null.
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserBuilder password(String password) {
|
||||
Assert.notNull(password, "password cannot be null");
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the roles. This method is a shortcut for calling
|
||||
* {@link #authorities(String...)}, but automatically prefixes each entry with
|
||||
* "ROLE_". This means the following:
|
||||
*
|
||||
* <code>
|
||||
* builder.roles("USER","ADMIN");
|
||||
* </code>
|
||||
*
|
||||
* is equivalent to
|
||||
*
|
||||
* <code>
|
||||
* builder.authorities("ROLE_USER","ROLE_ADMIN");
|
||||
* </code>
|
||||
*
|
||||
* <p>
|
||||
* This attribute is required, but can also be populated with
|
||||
* {@link #authorities(String...)}.
|
||||
* </p>
|
||||
*
|
||||
* @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null,
|
||||
* contain null values or start with "ROLE_"
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserBuilder roles(String... roles) {
|
||||
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(
|
||||
roles.length);
|
||||
for (String role : roles) {
|
||||
Assert.isTrue(!role.startsWith("ROLE_"), role
|
||||
+ " cannot start with ROLE_ (it is automatically added)");
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
|
||||
}
|
||||
return authorities(authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the authorities. This attribute is required.
|
||||
*
|
||||
* @param authorities the authorities for this user. Cannot be null, or contain
|
||||
* null values
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserBuilder authorities(GrantedAuthority... authorities) {
|
||||
return authorities(Arrays.asList(authorities));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the authorities. This attribute is required.
|
||||
*
|
||||
* @param authorities the authorities for this user. Cannot be null, or contain
|
||||
* null values
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserBuilder authorities(List<? extends GrantedAuthority> authorities) {
|
||||
this.authorities = new ArrayList<GrantedAuthority>(authorities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the authorities. This attribute is required.
|
||||
*
|
||||
* @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN,
|
||||
* etc). Cannot be null, or contain null values
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserBuilder authorities(String... authorities) {
|
||||
return authorities(AuthorityUtils.createAuthorityList(authorities));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the account is expired or not. Default is false.
|
||||
*
|
||||
* @param accountExpired true if the account is expired, false otherwise
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserBuilder accountExpired(boolean accountExpired) {
|
||||
this.accountExpired = accountExpired;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the account is locked or not. Default is false.
|
||||
*
|
||||
* @param accountLocked true if the account is locked, false otherwise
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserBuilder accountLocked(boolean accountLocked) {
|
||||
this.accountLocked = accountLocked;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the credentials are expired or not. Default is false.
|
||||
*
|
||||
* @param credentialsExpired true if the credentials are expired, false otherwise
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserBuilder credentialsExpired(boolean credentialsExpired) {
|
||||
this.credentialsExpired = credentialsExpired;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the account is disabled or not. Default is false.
|
||||
*
|
||||
* @param disabled true if the account is disabled, false otherwise
|
||||
* @return the {@link UserBuilder} for method chaining (i.e. to populate
|
||||
* additional attributes for this user)
|
||||
*/
|
||||
public UserBuilder disabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserDetails build() {
|
||||
return new User(username, password, !disabled, !accountExpired,
|
||||
!credentialsExpired, !accountLocked, authorities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ import java.util.Collection;
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see CoreJackson2Module
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
@@ -38,12 +38,13 @@ import java.util.Collections;
|
||||
* ObjectMapper mapper = new ObjectMapper();
|
||||
* mapper.registerModule(new CoreJackson2Module());
|
||||
* </pre>
|
||||
* <b>Note: use {@link SecurityJacksonModules#getModules(ClassLoader)} to get list of all security modules.</b>
|
||||
* <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules.</b>
|
||||
*
|
||||
* @author Jitendra Singh.
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class CoreJackson2Module extends SimpleModule {
|
||||
|
||||
public CoreJackson2Module() {
|
||||
@@ -52,7 +53,7 @@ public class CoreJackson2Module extends SimpleModule {
|
||||
|
||||
@Override
|
||||
public void setupModule(SetupContext context) {
|
||||
SecurityJacksonModules.enableDefaultTyping((ObjectMapper) context.getOwner());
|
||||
SecurityJackson2Modules.enableDefaultTyping((ObjectMapper) context.getOwner());
|
||||
context.setMixInAnnotations(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
|
||||
context.setMixInAnnotations(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class);
|
||||
context.setMixInAnnotations(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ import java.util.Collection;
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see CoreJackson2Module
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
+4
-4
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
* <p>
|
||||
* <pre>
|
||||
* ObjectMapper mapper = new ObjectMapper();
|
||||
* mapper.registerModules(SecurityJacksonModules.getModules());
|
||||
* mapper.registerModules(SecurityJackson2Modules.getModules());
|
||||
* </pre>
|
||||
* Above code is equivalent to
|
||||
* <p>
|
||||
@@ -49,16 +49,16 @@ import java.util.List;
|
||||
* @author Jitendra Singh.
|
||||
* @since 4.2
|
||||
*/
|
||||
public final class SecurityJacksonModules {
|
||||
public final class SecurityJackson2Modules {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SecurityJacksonModules.class);
|
||||
private static final Log logger = LogFactory.getLog(SecurityJackson2Modules.class);
|
||||
private static final List<String> securityJackson2ModuleClasses = Arrays.asList(
|
||||
"org.springframework.security.jackson2.CoreJackson2Module",
|
||||
"org.springframework.security.cas.jackson2.CasJackson2Module",
|
||||
"org.springframework.security.web.jackson2.WebJackson2Module"
|
||||
);
|
||||
|
||||
private SecurityJacksonModules() {
|
||||
private SecurityJackson2Modules() {
|
||||
}
|
||||
|
||||
public static void enableDefaultTyping(ObjectMapper mapper) {
|
||||
+1
-1
@@ -28,7 +28,7 @@ import com.fasterxml.jackson.annotation.*;
|
||||
* </pre>
|
||||
* @author Jitendra Singh
|
||||
* @see CoreJackson2Module
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* 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.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Custom deserializer for {@link UnmodifiableSetMixin}.
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see UnmodifiableSetMixin
|
||||
* @since 4.2
|
||||
*/
|
||||
class UnmodifiableSetDeserializer extends JsonDeserializer<Set> {
|
||||
|
||||
@Override
|
||||
public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
|
||||
JsonNode node = mapper.readTree(jp);
|
||||
Set<Object> resultSet = new HashSet<Object>();
|
||||
if (node != null) {
|
||||
if (node instanceof ArrayNode) {
|
||||
ArrayNode arrayNode = (ArrayNode) node;
|
||||
Iterator<JsonNode> nodeIterator = arrayNode.iterator();
|
||||
while (nodeIterator.hasNext()) {
|
||||
JsonNode elementNode = nodeIterator.next();
|
||||
resultSet.add(mapper.readValue(elementNode.toString(), Object.class));
|
||||
}
|
||||
} else {
|
||||
resultSet.add(mapper.readValue(node.toString(), Object.class));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(resultSet);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.springframework.security.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -31,11 +32,13 @@ import java.util.Set;
|
||||
* </pre>
|
||||
*
|
||||
* @author Jitendra Singh
|
||||
* @see UnmodifiableSetDeserializer
|
||||
* @see CoreJackson2Module
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
@JsonDeserialize(using = UnmodifiableSetDeserializer.class)
|
||||
class UnmodifiableSetMixin {
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,7 +37,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
* @author Jitendra Singh
|
||||
* @see UserDeserializer
|
||||
* @see CoreJackson2Module
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
* </pre>
|
||||
* @author Jitendra Singh
|
||||
* @see CoreJackson2Module
|
||||
* @see SecurityJacksonModules
|
||||
* @see SecurityJackson2Modules
|
||||
* @since 4.2
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
|
||||
|
||||
+5
-2
@@ -52,6 +52,9 @@ public class InMemoryUserDetailsManager implements UserDetailsManager {
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
public InMemoryUserDetailsManager() {
|
||||
}
|
||||
|
||||
public InMemoryUserDetailsManager(Collection<UserDetails> users) {
|
||||
for (UserDetails user : users) {
|
||||
createUser(user);
|
||||
@@ -73,7 +76,7 @@ public class InMemoryUserDetailsManager implements UserDetailsManager {
|
||||
}
|
||||
|
||||
public void createUser(UserDetails user) {
|
||||
Assert.isTrue(!userExists(user.getUsername()));
|
||||
Assert.isTrue(!userExists(user.getUsername()), "user should not exist");
|
||||
|
||||
users.put(user.getUsername().toLowerCase(), new MutableUser(user));
|
||||
}
|
||||
@@ -83,7 +86,7 @@ public class InMemoryUserDetailsManager implements UserDetailsManager {
|
||||
}
|
||||
|
||||
public void updateUser(UserDetails user) {
|
||||
Assert.isTrue(userExists(user.getUsername()));
|
||||
Assert.isTrue(userExists(user.getUsername()), "user should exist");
|
||||
|
||||
users.put(user.getUsername().toLowerCase(), new MutableUser(user));
|
||||
}
|
||||
|
||||
+35
-35
@@ -258,15 +258,15 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
}
|
||||
|
||||
public List<String> findUsersInGroup(String groupName) {
|
||||
Assert.hasText(groupName);
|
||||
Assert.hasText(groupName, "groupName should have text");
|
||||
return getJdbcTemplate().queryForList(findUsersInGroupSql,
|
||||
new String[] { groupName }, String.class);
|
||||
}
|
||||
|
||||
public void createGroup(final String groupName,
|
||||
final List<GrantedAuthority> authorities) {
|
||||
Assert.hasText(groupName);
|
||||
Assert.notNull(authorities);
|
||||
Assert.hasText(groupName, "groupName should have text");
|
||||
Assert.notNull(authorities, "authorities cannot be null");
|
||||
|
||||
logger.debug("Creating new group '" + groupName + "' with authorities "
|
||||
+ AuthorityUtils.authorityListToSet(authorities));
|
||||
@@ -289,7 +289,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
|
||||
public void deleteGroup(String groupName) {
|
||||
logger.debug("Deleting group '" + groupName + "'");
|
||||
Assert.hasText(groupName);
|
||||
Assert.hasText(groupName, "groupName should have text");
|
||||
|
||||
final int id = findGroupId(groupName);
|
||||
PreparedStatementSetter groupIdPSS = new PreparedStatementSetter() {
|
||||
@@ -304,16 +304,16 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
|
||||
public void renameGroup(String oldName, String newName) {
|
||||
logger.debug("Changing group name from '" + oldName + "' to '" + newName + "'");
|
||||
Assert.hasText(oldName);
|
||||
Assert.hasText(newName);
|
||||
Assert.hasText(oldName,"oldName should have text");;
|
||||
Assert.hasText(newName,"newName should have text");;
|
||||
|
||||
getJdbcTemplate().update(renameGroupSql, newName, oldName);
|
||||
}
|
||||
|
||||
public void addUserToGroup(final String username, final String groupName) {
|
||||
logger.debug("Adding user '" + username + "' to group '" + groupName + "'");
|
||||
Assert.hasText(username);
|
||||
Assert.hasText(groupName);
|
||||
Assert.hasText(username,"username should have text");;
|
||||
Assert.hasText(groupName,"groupName should have text");;
|
||||
|
||||
final int id = findGroupId(groupName);
|
||||
getJdbcTemplate().update(insertGroupMemberSql, new PreparedStatementSetter() {
|
||||
@@ -328,8 +328,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
|
||||
public void removeUserFromGroup(final String username, final String groupName) {
|
||||
logger.debug("Removing user '" + username + "' to group '" + groupName + "'");
|
||||
Assert.hasText(username);
|
||||
Assert.hasText(groupName);
|
||||
Assert.hasText(username,"username should have text");;
|
||||
Assert.hasText(groupName,"groupName should have text");;
|
||||
|
||||
final int id = findGroupId(groupName);
|
||||
|
||||
@@ -345,7 +345,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
|
||||
public List<GrantedAuthority> findGroupAuthorities(String groupName) {
|
||||
logger.debug("Loading authorities for group '" + groupName + "'");
|
||||
Assert.hasText(groupName);
|
||||
Assert.hasText(groupName,"groupName should have text");;
|
||||
|
||||
return getJdbcTemplate().query(groupAuthoritiesSql, new String[] { groupName },
|
||||
new RowMapper<GrantedAuthority>() {
|
||||
@@ -361,8 +361,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
public void removeGroupAuthority(String groupName, final GrantedAuthority authority) {
|
||||
logger.debug("Removing authority '" + authority + "' from group '" + groupName
|
||||
+ "'");
|
||||
Assert.hasText(groupName);
|
||||
Assert.notNull(authority);
|
||||
Assert.hasText(groupName,"groupName should have text");
|
||||
Assert.notNull(authority, "authority cannot be null");
|
||||
|
||||
final int id = findGroupId(groupName);
|
||||
|
||||
@@ -377,8 +377,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
|
||||
public void addGroupAuthority(final String groupName, final GrantedAuthority authority) {
|
||||
logger.debug("Adding authority '" + authority + "' to group '" + groupName + "'");
|
||||
Assert.hasText(groupName);
|
||||
Assert.notNull(authority);
|
||||
Assert.hasText(groupName,"groupName should have text");;
|
||||
Assert.notNull(authority, "authority cannot be null");
|
||||
|
||||
final int id = findGroupId(groupName);
|
||||
getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() {
|
||||
@@ -398,102 +398,102 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
|
||||
}
|
||||
|
||||
public void setCreateUserSql(String createUserSql) {
|
||||
Assert.hasText(createUserSql);
|
||||
Assert.hasText(createUserSql,"createUserSql should have text");;
|
||||
this.createUserSql = createUserSql;
|
||||
}
|
||||
|
||||
public void setDeleteUserSql(String deleteUserSql) {
|
||||
Assert.hasText(deleteUserSql);
|
||||
Assert.hasText(deleteUserSql,"deleteUserSql should have text");;
|
||||
this.deleteUserSql = deleteUserSql;
|
||||
}
|
||||
|
||||
public void setUpdateUserSql(String updateUserSql) {
|
||||
Assert.hasText(updateUserSql);
|
||||
Assert.hasText(updateUserSql,"updateUserSql should have text");;
|
||||
this.updateUserSql = updateUserSql;
|
||||
}
|
||||
|
||||
public void setCreateAuthoritySql(String createAuthoritySql) {
|
||||
Assert.hasText(createAuthoritySql);
|
||||
Assert.hasText(createAuthoritySql,"createAuthoritySql should have text");;
|
||||
this.createAuthoritySql = createAuthoritySql;
|
||||
}
|
||||
|
||||
public void setDeleteUserAuthoritiesSql(String deleteUserAuthoritiesSql) {
|
||||
Assert.hasText(deleteUserAuthoritiesSql);
|
||||
Assert.hasText(deleteUserAuthoritiesSql,"deleteUserAuthoritiesSql should have text");;
|
||||
this.deleteUserAuthoritiesSql = deleteUserAuthoritiesSql;
|
||||
}
|
||||
|
||||
public void setUserExistsSql(String userExistsSql) {
|
||||
Assert.hasText(userExistsSql);
|
||||
Assert.hasText(userExistsSql,"userExistsSql should have text");;
|
||||
this.userExistsSql = userExistsSql;
|
||||
}
|
||||
|
||||
public void setChangePasswordSql(String changePasswordSql) {
|
||||
Assert.hasText(changePasswordSql);
|
||||
Assert.hasText(changePasswordSql,"changePasswordSql should have text");;
|
||||
this.changePasswordSql = changePasswordSql;
|
||||
}
|
||||
|
||||
public void setFindAllGroupsSql(String findAllGroupsSql) {
|
||||
Assert.hasText(findAllGroupsSql);
|
||||
Assert.hasText(findAllGroupsSql,"findAllGroupsSql should have text");;
|
||||
this.findAllGroupsSql = findAllGroupsSql;
|
||||
}
|
||||
|
||||
public void setFindUsersInGroupSql(String findUsersInGroupSql) {
|
||||
Assert.hasText(findUsersInGroupSql);
|
||||
Assert.hasText(findUsersInGroupSql,"findUsersInGroupSql should have text");;
|
||||
this.findUsersInGroupSql = findUsersInGroupSql;
|
||||
}
|
||||
|
||||
public void setInsertGroupSql(String insertGroupSql) {
|
||||
Assert.hasText(insertGroupSql);
|
||||
Assert.hasText(insertGroupSql,"insertGroupSql should have text");;
|
||||
this.insertGroupSql = insertGroupSql;
|
||||
}
|
||||
|
||||
public void setFindGroupIdSql(String findGroupIdSql) {
|
||||
Assert.hasText(findGroupIdSql);
|
||||
Assert.hasText(findGroupIdSql,"findGroupIdSql should have text");;
|
||||
this.findGroupIdSql = findGroupIdSql;
|
||||
}
|
||||
|
||||
public void setInsertGroupAuthoritySql(String insertGroupAuthoritySql) {
|
||||
Assert.hasText(insertGroupAuthoritySql);
|
||||
Assert.hasText(insertGroupAuthoritySql,"insertGroupAuthoritySql should have text");;
|
||||
this.insertGroupAuthoritySql = insertGroupAuthoritySql;
|
||||
}
|
||||
|
||||
public void setDeleteGroupSql(String deleteGroupSql) {
|
||||
Assert.hasText(deleteGroupSql);
|
||||
Assert.hasText(deleteGroupSql,"deleteGroupSql should have text");;
|
||||
this.deleteGroupSql = deleteGroupSql;
|
||||
}
|
||||
|
||||
public void setDeleteGroupAuthoritiesSql(String deleteGroupAuthoritiesSql) {
|
||||
Assert.hasText(deleteGroupAuthoritiesSql);
|
||||
Assert.hasText(deleteGroupAuthoritiesSql,"deleteGroupAuthoritiesSql should have text");;
|
||||
this.deleteGroupAuthoritiesSql = deleteGroupAuthoritiesSql;
|
||||
}
|
||||
|
||||
public void setDeleteGroupMembersSql(String deleteGroupMembersSql) {
|
||||
Assert.hasText(deleteGroupMembersSql);
|
||||
Assert.hasText(deleteGroupMembersSql,"deleteGroupMembersSql should have text");;
|
||||
this.deleteGroupMembersSql = deleteGroupMembersSql;
|
||||
}
|
||||
|
||||
public void setRenameGroupSql(String renameGroupSql) {
|
||||
Assert.hasText(renameGroupSql);
|
||||
Assert.hasText(renameGroupSql,"renameGroupSql should have text");;
|
||||
this.renameGroupSql = renameGroupSql;
|
||||
}
|
||||
|
||||
public void setInsertGroupMemberSql(String insertGroupMemberSql) {
|
||||
Assert.hasText(insertGroupMemberSql);
|
||||
Assert.hasText(insertGroupMemberSql,"insertGroupMemberSql should have text");;
|
||||
this.insertGroupMemberSql = insertGroupMemberSql;
|
||||
}
|
||||
|
||||
public void setDeleteGroupMemberSql(String deleteGroupMemberSql) {
|
||||
Assert.hasText(deleteGroupMemberSql);
|
||||
Assert.hasText(deleteGroupMemberSql,"deleteGroupMemberSql should have text");;
|
||||
this.deleteGroupMemberSql = deleteGroupMemberSql;
|
||||
}
|
||||
|
||||
public void setGroupAuthoritiesSql(String groupAuthoritiesSql) {
|
||||
Assert.hasText(groupAuthoritiesSql);
|
||||
Assert.hasText(groupAuthoritiesSql,"groupAuthoritiesSql should have text");;
|
||||
this.groupAuthoritiesSql = groupAuthoritiesSql;
|
||||
}
|
||||
|
||||
public void setDeleteGroupAuthoritySql(String deleteGroupAuthoritySql) {
|
||||
Assert.hasText(deleteGroupAuthoritySql);
|
||||
Assert.hasText(deleteGroupAuthoritySql,"deleteGroupAuthoritySql should have text");;
|
||||
this.deleteGroupAuthoritySql = deleteGroupAuthoritySql;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class InMemoryResource extends AbstractResource {
|
||||
}
|
||||
|
||||
public InMemoryResource(byte[] source, String description) {
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(source, "source cannot be null");
|
||||
this.source = source;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ public abstract class HierarchicalRolesTestHelper {
|
||||
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(roles.length);
|
||||
|
||||
for (final String role : roles) {
|
||||
// Use non GrantedAuthorityImpl (SEC-863)
|
||||
// Use non SimpleGrantedAuthority (SEC-863)
|
||||
authorities.add(new GrantedAuthority() {
|
||||
public String getAuthority() {
|
||||
return role;
|
||||
|
||||
+7
-1
@@ -28,10 +28,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class RoleHierarchyUtilsTests {
|
||||
private static final String EOL = System.lineSeparator();
|
||||
|
||||
@Test
|
||||
public void roleHierarchyFromMapWhenMapValidThenConvertsCorrectly() throws Exception {
|
||||
String expectedRoleHierarchy = "ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_B > ROLE_D\nROLE_C > ROLE_D\n";
|
||||
// @formatter:off
|
||||
String expectedRoleHierarchy = "ROLE_A > ROLE_B" + EOL +
|
||||
"ROLE_A > ROLE_C" + EOL +
|
||||
"ROLE_B > ROLE_D" + EOL +
|
||||
"ROLE_C > ROLE_D" + EOL;
|
||||
// @formatter:on
|
||||
|
||||
Map<String, List<String>> roleHierarchyMap = new TreeMap<String, List<String>>();
|
||||
roleHierarchyMap.put("ROLE_A", asList("ROLE_B", "ROLE_C"));
|
||||
|
||||
+25
-4
@@ -25,25 +25,46 @@ import org.junit.Test;
|
||||
public class PasswordEncoderUtilsTests {
|
||||
|
||||
@Test
|
||||
public void differentLength() {
|
||||
public void equalsWhenDifferentLengthThenFalse() {
|
||||
assertThat(PasswordEncoderUtils.equals("abc", "a")).isFalse();
|
||||
assertThat(PasswordEncoderUtils.equals("a", "abc")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsNull() {
|
||||
public void equalsWhenNullAndNotEmtpyThenFalse() {
|
||||
assertThat(PasswordEncoderUtils.equals(null, "a")).isFalse();
|
||||
assertThat(PasswordEncoderUtils.equals("a", null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWhenNullAndNullThenTrue() {
|
||||
assertThat(PasswordEncoderUtils.equals(null, null)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsCaseSensitive() {
|
||||
public void equalsWhenNullAndEmptyThenFalse() {
|
||||
assertThat(PasswordEncoderUtils.equals(null, "")).isFalse();
|
||||
assertThat(PasswordEncoderUtils.equals("", null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWhenNotEmptyAndEmptyThenFalse() {
|
||||
assertThat(PasswordEncoderUtils.equals("abc", "")).isFalse();
|
||||
assertThat(PasswordEncoderUtils.equals("", "abc")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWhenEmtpyAndEmptyThenTrue() {
|
||||
assertThat(PasswordEncoderUtils.equals("", "")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWhenDifferentCaseThenFalse() {
|
||||
assertThat(PasswordEncoderUtils.equals("aBc", "abc")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsSuccess() {
|
||||
public void equalsWhenSameThenTrue() {
|
||||
assertThat(PasswordEncoderUtils.equals("abcdef", "abcdef")).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public abstract class AbstractMixinTests {
|
||||
public void setup() {
|
||||
mapper = new ObjectMapper();
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
mapper.registerModules(SecurityJacksonModules.getModules(loader));
|
||||
mapper.registerModules(SecurityJackson2Modules.getModules(loader));
|
||||
}
|
||||
|
||||
User createDefaultUser() {
|
||||
|
||||
+2
-8
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-crypto</name>
|
||||
<description>spring-security-crypto</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -92,12 +92,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -532,8 +532,9 @@ public class BCrypt {
|
||||
* @param password the password to hash
|
||||
* @param salt the salt to hash with (perhaps generated using BCrypt.gensalt)
|
||||
* @return the hashed password
|
||||
* @throws IllegalArgumentException if invalid salt is passed
|
||||
*/
|
||||
public static String hashpw(String password, String salt) {
|
||||
public static String hashpw(String password, String salt) throws IllegalArgumentException {
|
||||
BCrypt B;
|
||||
String real_salt;
|
||||
byte passwordb[], saltb[], hashed[];
|
||||
@@ -541,6 +542,10 @@ public class BCrypt {
|
||||
int rounds, off = 0;
|
||||
StringBuilder rs = new StringBuilder();
|
||||
|
||||
if (salt == null) {
|
||||
throw new IllegalArgumentException("salt cannot be null");
|
||||
}
|
||||
|
||||
int saltLength = salt.length();
|
||||
|
||||
if (saltLength < 28) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -163,7 +163,7 @@ public class SCryptPasswordEncoder implements PasswordEncoder {
|
||||
}
|
||||
|
||||
private String digest(CharSequence rawPassword, byte[] salt) {
|
||||
byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, 32);
|
||||
byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, keyLength);
|
||||
|
||||
String params = Long
|
||||
.toString(((int) (Math.log(cpuCost) / Math.log(2)) << 16L) | memoryCost << 8 | parallelization, 16);
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
|
||||
package org.springframework.security.crypto.bcrypt;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* JUnit unit tests for BCrypt routines
|
||||
@@ -271,6 +272,11 @@ public class BCryptTests {
|
||||
assertThat(BCrypt.gensalt(31).startsWith("$2a$31$")).isTrue();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void hashpwFailsWhenSaltIsNull() {
|
||||
BCrypt.hashpw("password", null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void hashpwFailsWhenSaltSpecifiesTooFewRounds() {
|
||||
BCrypt.hashpw("password", "$2a$03$......................");
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -65,7 +65,7 @@ public class SCryptPasswordEncoderTests {
|
||||
|
||||
@Test
|
||||
public void samePasswordWithDifferentParams() {
|
||||
SCryptPasswordEncoder oldEncoder = new SCryptPasswordEncoder(512, 8, 4, 64, 16);
|
||||
SCryptPasswordEncoder oldEncoder = new SCryptPasswordEncoder(16384, 8, 1, 32,64);
|
||||
SCryptPasswordEncoder newEncoder = new SCryptPasswordEncoder();
|
||||
|
||||
String password = "secret";
|
||||
|
||||
+3
-9
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-data</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>spring-security-data</name>
|
||||
<description>spring-security-data</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -51,7 +51,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -108,12 +108,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -162,12 +162,12 @@ Our existing configuration means that all we need to do is create a *login.html*
|
||||
.src/main/resources/views/login.html
|
||||
[source,xml]
|
||||
----
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title tiles:fragment="title">Messages : Create</title>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head th:include="layout :: head(title=~{::title},links=~{})">
|
||||
<title>Please Login</title>
|
||||
</head>
|
||||
<body>
|
||||
<div tiles:fragment="content">
|
||||
<body th:include="layout :: body" th:with="content=~{::content}">
|
||||
<div th:fragment="content">
|
||||
<form name="f" th:action="@{/login}" method="post"> <1>
|
||||
<fieldset>
|
||||
<legend>Please Login</legend>
|
||||
|
||||
@@ -431,7 +431,7 @@ To use JDBC instead, you can implement the interface yourself, using whatever SQ
|
||||
* prefix "ROLE_" to mark attributes which are supported by Spring Security's RoleVoter.
|
||||
*/
|
||||
public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return new GrantedAuthorityImpl("ROLE_" + rs.getString(1);
|
||||
return new SimpleGrantedAuthority("ROLE_" + rs.getString(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ To use it, register the `JacksonJacksonModules.getModules(ClassLoader)` as http:
|
||||
----
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
List<Module> modules = SecurityJacksonModules.getModules(loader);
|
||||
List<Module> modules = SecurityJackson2Modules.getModules(loader);
|
||||
mapper.registerModules(modules);
|
||||
|
||||
// ... use ObjectMapper as normally ...
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[[appendix-proxy-server]]
|
||||
== Proxy Server Configuration
|
||||
|
||||
When using a proxy server it is important to ensure that you have configured your application properly.
|
||||
For example, many applications will have a load balancer that responds to request for https://example.com/ by forwarding the request to an application server at http://192.168.1:8080
|
||||
Without proper configuration, the application server will not know that the load balancer exists and treat the request as though http://192.168.1:8080 was requested by the client.
|
||||
|
||||
To fix this you can use https://tools.ietf.org/html/rfc7239[RFC 7239] to specify that a load balancer is being used.
|
||||
To make the application aware of this, you need to either configure your application server aware of the X-Forwarded headers.
|
||||
For example Tomcat uses the https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html[RemoteIpValve] and Jetty uses http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/server/ForwardedRequestCustomizer.html[ForwardedRequestCustomizer].
|
||||
Alternatively, Spring 4.3+ users can leverage https://github.com/spring-projects/spring-framework/blob/v4.3.3.RELEASE/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java[ForwardedHeaderFilter].
|
||||
@@ -11,7 +11,7 @@ To use the Spring Security test support, you must include `spring-security-test-
|
||||
[[test-method]]
|
||||
== Testing Method Security
|
||||
|
||||
This section demonstrates how to use Spring Security's Test support to test method based security.
|
||||
This section demonstrates how to use Spring Security's Test support to test method based security.
|
||||
We first introduce a `MessageService` that requires the user to be authenticated in order to access it.
|
||||
|
||||
[source,java]
|
||||
@@ -49,13 +49,13 @@ public class WithMockUserTests {
|
||||
|
||||
This is a basic example of how to setup Spring Security Test. The highlights are:
|
||||
|
||||
<1> `@RunWith` instructs the spring-test module that it should create an ApplicationContext This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
|
||||
<1> `@RunWith` instructs the spring-test module that it should create an `ApplicationContext`. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard[Spring Reference]
|
||||
<2> `@ContextConfiguration` instructs the spring-test the configuration to use to create the `ApplicationContext`. Since no configuration is specified, the default configuration locations will be tried. This is no different than using the existing Spring Test support. For additional information, refer to the http://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#testcontext-ctx-management[Spring Reference]
|
||||
|
||||
NOTE: Spring Security hooks into Spring Test support using the `WithSecurityContextTestExecutionListener` which will ensure our tests are ran with the correct user.
|
||||
NOTE: Spring Security hooks into Spring Test support using the `WithSecurityContextTestExecutionListener` which will ensure our tests are ran with the correct user.
|
||||
It does this by populating the `SecurityContextHolder` prior to running our tests.
|
||||
After the test is done, it will clear out the `SecurityContextHolder`.
|
||||
If you only need Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityExecutionListeners`.
|
||||
If you only need Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityTestExecutionListeners`.
|
||||
|
||||
Remember we added the `@PreAuthorize` annotation to our `HelloMessageService` and so it requires an authenticated user to invoke it.
|
||||
If we ran the following test, we would expect the following test will pass:
|
||||
@@ -73,7 +73,7 @@ public void getMessageUnauthenticated() {
|
||||
|
||||
The question is "How could we most easily run the test as a specific user?"
|
||||
The answer is to use `@WithMockUser`.
|
||||
The following test will be ran as a user with the username "user", the password "password", and the roles "ROLE_USER".
|
||||
The following test will be run as a user with the username "user", the password "password", and the roles "ROLE_USER".
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -291,7 +291,7 @@ final class WithUserDetailsSecurityContextFactory
|
||||
|
||||
public SecurityContext createSecurityContext(WithUserDetails withUser) {
|
||||
String username = withUser.value();
|
||||
Assert.hasLength(username, "value() must be non empty String");
|
||||
Assert.hasLength(username, "value() must be non-empty String");
|
||||
UserDetails principal = userDetailsService.loadUserByUsername(username);
|
||||
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
@@ -386,7 +386,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock
|
||||
[[test-mockmvc-csrf]]
|
||||
==== Testing with CSRF Protection
|
||||
|
||||
When testing any non safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
|
||||
When testing any non-safe HTTP methods and using Spring Security's CSRF protection, you must be sure to include a valid CSRF Token in the request.
|
||||
To specify a valid CSRF token as a request parameter using the following:
|
||||
|
||||
[source,java]
|
||||
|
||||
@@ -93,7 +93,7 @@ public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBro
|
||||
|
||||
This will ensure that:
|
||||
|
||||
<1> Any message without a destination (i.e. anything other that Message type of MESSAGE or SUBSCRIBE) will require the user to be authenticated
|
||||
<1> Any message without a destination (i.e. anything other than Message type of MESSAGE or SUBSCRIBE) will require the user to be authenticated
|
||||
<2> Anyone can subscribe to /user/queue/errors
|
||||
<3> Any message that has a destination starting with "/app/" will be require the user to have the role ROLE_USER
|
||||
<4> Any message that starts with "/user/" or "/topic/friends/" that is of type SUBSCRIBE will require ROLE_USER
|
||||
@@ -162,7 +162,7 @@ It is also is important to understand how destinations are transformed.
|
||||
|
||||
Consider a chat application.
|
||||
|
||||
* User's can send messages to a specific user by sending a message to the destination of "/app/chat".
|
||||
* Users can send messages to a specific user by sending a message to the destination of "/app/chat".
|
||||
* The application sees the message, ensures that the "from" attribute is specified as the current user (we cannot trust the client).
|
||||
* The application then sends the message to the recipient using `SimpMessageSendingOperations.convertAndSendToUser("toUser", "/queue/messages", message)`.
|
||||
* The message gets turned into the destination of "/queue/user/messages-<sessionid>"
|
||||
@@ -200,7 +200,7 @@ The Same Origin Policy ensures that evil.com cannot read or write data to bank.c
|
||||
|
||||
With WebSockets the Same Origin Policy does not apply.
|
||||
In fact, unless bank.com explicitly forbids it, evil.com can read and write data on behalf of the user.
|
||||
This means that anything the user can do over the websocket (i.e. transfer money), evil.com can do on that users behalf.
|
||||
This means that anything the user can do over the webSocket (i.e. transfer money), evil.com can do on that users behalf.
|
||||
|
||||
Since SockJS tries to emulate WebSockets it also bypasses the Same Origin Policy.
|
||||
This means developers need to explicitly protect their applications from external domains when using SockJS.
|
||||
@@ -246,7 +246,7 @@ public class CsrfController {
|
||||
}
|
||||
----
|
||||
|
||||
The javascript can make a REST call to the endpoint and use the response to populate the headerName and the token.
|
||||
The JavaScript can make a REST call to the endpoint and use the response to populate the headerName and the token.
|
||||
|
||||
We can now include the token in our Stomp client.
|
||||
For example:
|
||||
@@ -397,4 +397,4 @@ For example:
|
||||
</b:bean>
|
||||
</b:constructor-arg>
|
||||
</b:bean>
|
||||
----
|
||||
----
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
version=4.2.0.M1
|
||||
version=4.2.2.RELEASE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apply plugin: 'spring-boot'
|
||||
apply plugin: 'org.springframework.boot'
|
||||
|
||||
sonarqube {
|
||||
skipProject = true
|
||||
|
||||
@@ -50,6 +50,8 @@ tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
|
||||
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
|
||||
tasks["eclipse"].dependsOn(eclipseCheckstyle, eclipseSettings, eclipseWstComponent)
|
||||
|
||||
task eclipseConfiguration(dependsOn: [eclipseCheckstyle, eclipseSettings, eclipseWstComponent]) {
|
||||
}
|
||||
|
||||
eclipse {
|
||||
classpath {
|
||||
|
||||
@@ -19,23 +19,27 @@ ext.ehcacheVersion = '2.9.0'
|
||||
ext.gebVersion = '0.10.0'
|
||||
ext.groovyVersion = '2.4.4'
|
||||
ext.hsqlVersion = '2.3.2'
|
||||
ext.jacksonDatavindVersion = '2.4.4'
|
||||
ext.hibernateVersion = '5.0.11.Final'
|
||||
ext.hibernateValidatorVersion = '5.2.4.Final'
|
||||
ext.jacksonDatabindVersion = '2.8.4'
|
||||
ext.javaPersistenceVersion = '2.1.1'
|
||||
ext.jettyVersion = '6.1.26'
|
||||
ext.jstlVersion = '1.2.1'
|
||||
ext.junitVersion = '4.12'
|
||||
ext.logbackVersion = '1.1.2'
|
||||
ext.powerMockVersion = '1.6.2'
|
||||
ext.seleniumVersion = '2.44.0'
|
||||
ext.servletApiVersion = '3.0.1'
|
||||
ext.servletApiVersion = '3.1.0'
|
||||
ext.slf4jVersion = '1.7.7'
|
||||
ext.spockVersion = '0.7-groovy-2.0'
|
||||
ext.springDataCommonsVersion = '1.12.2.RELEASE'
|
||||
ext.springDataJpaVersion = '1.10.2.RELEASE'
|
||||
ext.springDataRedisVersion = '1.7.2.RELEASE'
|
||||
ext.springSessionVersion = '1.2.1.RELEASE'
|
||||
ext.springBootVersion = '1.4.0.RELEASE'
|
||||
ext.thymeleafVersion = '2.1.5.RELEASE'
|
||||
ext.springBootVersion = '1.5.0.BUILD-SNAPSHOT'
|
||||
ext.thymeleafVersion = '3.0.2.RELEASE'
|
||||
ext.jsonassertVersion = '1.3.0'
|
||||
ext.validationApiVersion = '1.1.0.Final'
|
||||
|
||||
ext.spockDependencies = [
|
||||
dependencies.create("org.spockframework:spock-spring:$spockVersion") {
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS="-Xmx1024M -XX:MaxPermSize=512M"
|
||||
DEFAULT_JVM_OPTS="-Xmx2048M -XX:MaxPermSize=512M"
|
||||
export GRADLE_OPTS='-Dorg.gradle.daemon=false'
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
Vendored
+1
@@ -10,6 +10,7 @@ if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=-Xmx1024M
|
||||
set GRADLE_OPTS="-Dorg.gradle.daemon=false"
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
|
||||
+6
-12
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>itest-context</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>itest-context</name>
|
||||
<description>itest-context</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -57,7 +57,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -96,7 +96,7 @@
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -132,13 +132,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -152,12 +152,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -7,32 +7,18 @@ dependencies {
|
||||
|
||||
testCompile project(':spring-security-core'),
|
||||
project(':spring-security-web'),
|
||||
project(':spring-security-taglibs'),
|
||||
project(':spring-security-test'),
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-webmvc:$springVersion",
|
||||
"org.mortbay.jetty:jetty-util:$jettyVersion",
|
||||
"org.testng:testng:6.8.21"
|
||||
testCompile ("org.mortbay.jetty:jetty:$jettyVersion") {
|
||||
exclude group: 'org.mortbay.jetty', module: 'servlet-api'
|
||||
}
|
||||
testCompile ('net.sourceforge.jwebunit:jwebunit-core:2.2') {
|
||||
exclude group: 'javax.servlet', module: 'servlet-api'
|
||||
exclude group: 'regexp', module: 'regexp'
|
||||
}
|
||||
"org.springframework:spring-test:$springVersion"
|
||||
|
||||
testRuntime project(':spring-security-config'),
|
||||
project(':spring-security-ldap'),
|
||||
"org.mortbay.jetty:jsp-2.1-jetty:$jettyVersion",
|
||||
testRuntime ('net.sourceforge.jwebunit:jwebunit-htmlunit-plugin:2.2') {
|
||||
exclude group: 'javax.servlet', module: 'servlet-api'
|
||||
}
|
||||
project(':spring-security-ldap')
|
||||
}
|
||||
|
||||
integrationTest {
|
||||
useTestNG();
|
||||
options {
|
||||
jvmArgs = ["-ea", '-Xms128m', '-Xmx500m']
|
||||
systemProperties = ['webapp.dir': "$projectDir/src/main/webapp"]
|
||||
}
|
||||
maxParallelForks = 1
|
||||
}
|
||||
|
||||
+9
-73
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>itest-web</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<name>itest-web</name>
|
||||
<description>itest-web</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>4.3.2.RELEASE</version>
|
||||
<version>4.3.5.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -62,7 +62,7 @@
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -77,34 +77,6 @@
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jwebunit</groupId>
|
||||
<artifactId>jwebunit-core</artifactId>
|
||||
<version>2.2</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>regexp</artifactId>
|
||||
<groupId>regexp</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jwebunit</groupId>
|
||||
<artifactId>jwebunit-htmlunit-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
@@ -117,30 +89,6 @@
|
||||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty</artifactId>
|
||||
<version>6.1.26</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>6.1.26</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jsp-2.1-jetty</artifactId>
|
||||
<version>6.1.26</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
@@ -150,31 +98,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.2.0.M1</version>
|
||||
<version>4.2.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -192,19 +140,7 @@
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>6.8.21</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
+24
-138
@@ -15,26 +15,14 @@
|
||||
*/
|
||||
package org.springframework.security.integration;
|
||||
|
||||
import java.util.List;
|
||||
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import net.sourceforge.jwebunit.junit.WebTester;
|
||||
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.servlet.ServletHolder;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.junit.After;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
|
||||
/**
|
||||
* Base class which allows the application to be started with a particular Spring
|
||||
@@ -45,131 +33,29 @@ import org.testng.annotations.BeforeMethod;
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public abstract class AbstractWebServerIntegrationTests {
|
||||
private Server server;
|
||||
private final Object SERVER_LOCK = new Object();
|
||||
protected final WebTester tester = new WebTester();
|
||||
protected ConfigurableApplicationContext context;
|
||||
|
||||
/**
|
||||
* Override to set the application context files that should be loaded or return null
|
||||
* to use web.xml.
|
||||
*/
|
||||
protected abstract String getContextConfigLocations();
|
||||
|
||||
protected String getContextPath() {
|
||||
return "/testapp";
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public void startServer() throws Exception {
|
||||
synchronized (SERVER_LOCK) {
|
||||
if (server == null) {
|
||||
// System.setProperty("DEBUG", "true");
|
||||
// System.setProperty("VERBOSE", "true");
|
||||
// System.setProperty("IGNORED", "true");
|
||||
server = new Server(0);
|
||||
server.addHandler(createWebContext());
|
||||
server.start();
|
||||
}
|
||||
@After
|
||||
public void close() {
|
||||
if(context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private WebAppContext createWebContext() {
|
||||
String webappDir = System.getProperty("webapp.dir");
|
||||
|
||||
WebAppContext webCtx = new WebAppContext(webappDir == null ? "src/main/webapp"
|
||||
: webappDir, getContextPath());
|
||||
|
||||
if (StringUtils.hasText(getContextConfigLocations())) {
|
||||
webCtx.addEventListener(new ContextLoaderListener());
|
||||
webCtx.addEventListener(new HttpSessionEventPublisher());
|
||||
webCtx.getInitParams().put("contextConfigLocation",
|
||||
getContextConfigLocations());
|
||||
protected final MockMvc createMockMvc(String... configLocations) throws Exception {
|
||||
if(this.context != null) {
|
||||
throw new IllegalStateException("context is already loaded");
|
||||
}
|
||||
|
||||
ServletHolder servlet = new ServletHolder();
|
||||
servlet.setName("testapp");
|
||||
servlet.setClassName(DispatcherServlet.class.getName());
|
||||
webCtx.addServlet(servlet, "*.htm");
|
||||
XmlWebApplicationContext context = new XmlWebApplicationContext();
|
||||
context.setConfigLocations(configLocations);
|
||||
context.setServletContext(new MockServletContext());
|
||||
context.refresh();
|
||||
this.context = context;
|
||||
|
||||
return webCtx;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public void stopServer() throws Exception {
|
||||
synchronized (SERVER_LOCK) {
|
||||
if (server != null) {
|
||||
server.stop();
|
||||
}
|
||||
server = null;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeMethod
|
||||
public void initializeTester() {
|
||||
tester.getTestContext().setBaseUrl(getBaseUrl());
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
public void resetWebConversation() {
|
||||
tester.closeBrowser();
|
||||
tester.setTestContext(null);
|
||||
}
|
||||
|
||||
protected final String getBaseUrl() {
|
||||
int port = server.getConnectors()[0].getLocalPort();
|
||||
return "http://localhost:" + port + getContextPath() + "/";
|
||||
}
|
||||
|
||||
protected final Object getBean(String beanName) {
|
||||
return getAppContext().getBean(beanName);
|
||||
}
|
||||
|
||||
protected final WebApplicationContext getAppContext() {
|
||||
ServletContext servletCtx = ((WebAppContext) server.getHandler())
|
||||
.getServletContext();
|
||||
WebApplicationContext appCtx = WebApplicationContextUtils
|
||||
.getRequiredWebApplicationContext(servletCtx);
|
||||
return appCtx;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Cookie getRememberMeCookie() {
|
||||
List<Cookie> cookies = (List<Cookie>) tester.getTestingEngine().getCookies();
|
||||
for (Cookie c : cookies) {
|
||||
if (c.getName().equals("remember-me")) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final void submit() {
|
||||
tester.submit();
|
||||
}
|
||||
|
||||
protected final void beginAt(String url) {
|
||||
tester.beginAt(url);
|
||||
}
|
||||
|
||||
protected final void setTextField(String name, String value) {
|
||||
tester.setTextField(name, value);
|
||||
}
|
||||
|
||||
protected final void assertFormPresent() {
|
||||
tester.assertFormPresent();
|
||||
}
|
||||
|
||||
protected final void assertTextPresent(String text) {
|
||||
tester.assertTextPresent(text);
|
||||
}
|
||||
|
||||
// Security-specific utility methods
|
||||
|
||||
protected void login(String username, String password) {
|
||||
assertFormPresent();
|
||||
setTextField("username", username);
|
||||
setTextField("password", password);
|
||||
submit();
|
||||
return MockMvcBuilders
|
||||
.webAppContextSetup(context)
|
||||
.apply(springSecurity())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
+18
-14
@@ -15,25 +15,29 @@
|
||||
*/
|
||||
package org.springframework.security.integration;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
public class BasicAuthenticationTests extends AbstractWebServerIntegrationTests {
|
||||
|
||||
@Override
|
||||
protected String getContextConfigLocations() {
|
||||
return "/WEB-INF/http-security-basic.xml /WEB-INF/in-memory-provider.xml";
|
||||
@Test
|
||||
public void httpBasicWhenAuthenticationRequiredAndNotAuthenticatedThen401() throws Exception {
|
||||
MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml");
|
||||
mockMvc.perform(get("secure/index"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthenticationIsSuccessful() throws Exception {
|
||||
tester.setIgnoreFailingStatusCodes(true);
|
||||
beginAt("secure/index.html");
|
||||
// Ignore the 401
|
||||
tester.setIgnoreFailingStatusCodes(false);
|
||||
tester.assertHeaderEquals("WWW-Authenticate",
|
||||
"Basic realm=\"Spring Security Application\"");
|
||||
tester.getTestContext().setAuthorization("johnc", "johncspassword");
|
||||
beginAt("secure/index.html");
|
||||
public void httpBasicWhenProvidedThen200() throws Exception {
|
||||
MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml");
|
||||
MockHttpServletRequestBuilder request = get("/secure/index")
|
||||
.with(httpBasic("johnc", "johncspassword"));
|
||||
mockMvc.perform(request)
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user