Compare commits
145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48eb8788c4 | |||
| 23de257508 | |||
| 12ed990aa2 | |||
| d7d4ac9dc1 | |||
| 7c62164392 | |||
| eceb6a3587 | |||
| c4a1f1b4a8 | |||
| 7ecee8e733 | |||
| 63a334317b | |||
| 704b114842 | |||
| fcc9a34356 | |||
| 00042ff70b | |||
| fc1450f72c | |||
| a6cd1b6066 | |||
| 567b0ed030 | |||
| 4e6b12f8b4 | |||
| ae772294cb | |||
| c01f2d8501 | |||
| 28c6e9a8af | |||
| 13cb51c15f | |||
| b0ad8173b0 | |||
| ea27cb6593 | |||
| fe82c8ab4c | |||
| cf66f2f39e | |||
| 050407564c | |||
| 1374898cd8 | |||
| d5ed97eba6 | |||
| 8f29c2cc36 | |||
| 99d503f0a9 | |||
| 6c185f649b | |||
| 58be282f70 | |||
| 2df05ee2c3 | |||
| 72bc6bf539 | |||
| 1b26d03479 | |||
| dfaebfa63b | |||
| f794272bac | |||
| aa0a5b96ab | |||
| 27c7cd150b | |||
| b3d108fa44 | |||
| 975e4ec019 | |||
| 74f8534b17 | |||
| 478a9650aa | |||
| b79ba12502 | |||
| 72de17d79a | |||
| e27200a255 | |||
| c3f72f7b79 | |||
| b42cb9e3e1 | |||
| b40088b73d | |||
| 4116596a6c | |||
| 9de369c25f | |||
| bf2d2d4597 | |||
| c05f27af6c | |||
| cdac4d990b | |||
| db66843e0b | |||
| c36cc88ac4 | |||
| 7d82349b1e | |||
| b6ab9c85e9 | |||
| 29a8da4aa6 | |||
| b71989ecde | |||
| eeef91498a | |||
| 91bf099b01 | |||
| 137589325d | |||
| 0a184a8d79 | |||
| 2cb99f0791 | |||
| d85a0a20bc | |||
| 0a45d3170c | |||
| 89c5c56849 | |||
| 47acf17323 | |||
| 52c585aef1 | |||
| 89d80ed5c9 | |||
| 85a37bdc02 | |||
| fb1f2dc888 | |||
| d5842f949b | |||
| 3e3d819526 | |||
| 143c513f5c | |||
| 8eb89e3f12 | |||
| bdde468e7d | |||
| f574f2a2ac | |||
| 439a15b108 | |||
| 44fbf678bb | |||
| 9c94ef358d | |||
| 655ad90813 | |||
| a0ee80bc61 | |||
| 6b977d9b4b | |||
| 7ea79bacbc | |||
| fa177a22b1 | |||
| b9fbc568fb | |||
| 293e3e97ae | |||
| 08ec5797db | |||
| b20438562d | |||
| d4e26864d9 | |||
| 519d85877c | |||
| f31a5c5411 | |||
| 77b9209640 | |||
| ae39a4dcdd | |||
| f37e414442 | |||
| be687d6a84 | |||
| d6b81abcf2 | |||
| bf918df7a3 | |||
| dc7a3b30ea | |||
| 3be2f375f6 | |||
| 9146345673 | |||
| fb2cf96fa4 | |||
| 9a27f9f778 | |||
| e0b4945fad | |||
| d6f540fdee | |||
| 3f24210a2a | |||
| 13c5750f5d | |||
| 414289d466 | |||
| 5e88ebef2e | |||
| c074493f24 | |||
| 1337f99843 | |||
| cf721afc29 | |||
| 9133491da9 | |||
| 3632564972 | |||
| 7ea0d3d42f | |||
| d9e87d8222 | |||
| 3954e0b2c1 | |||
| 79fa1c70eb | |||
| fd6f9da184 | |||
| ea0466d666 | |||
| 2cc0d94481 | |||
| 32c767a30d | |||
| a11746a8d1 | |||
| a18265a163 | |||
| d7a2c0a98c | |||
| 9057fbe0ed | |||
| 537d8f974f | |||
| 783af4012b | |||
| 5f5b8052d8 | |||
| 7dbb8e777e | |||
| bb563967cc | |||
| 974105ed19 | |||
| 2cad2f401b | |||
| 3048e2c6e7 | |||
| 561f284718 | |||
| afc6a6ee0d | |||
| fa05e9c590 | |||
| 818be86d46 | |||
| 60704eb50e | |||
| f02b77794f | |||
| 1172d44397 | |||
| 49738e4588 | |||
| 3b13c1fdf4 | |||
| 8f6450ede1 |
+58
@@ -0,0 +1,58 @@
|
||||
= Spring Security
|
||||
|
||||
Spring Security provides security services for the http://docs.spring.io[Spring IO Platform]. Spring Security 3.1 requires Spring 3.0.3 as
|
||||
a minimum and also requires Java 5.
|
||||
|
||||
For a detailed list of features and access to the latest release, please visit http://spring.io/projects[Spring projects].
|
||||
|
||||
== Downloading Artifacts
|
||||
See https://github.com/spring-projects/spring-framework/wiki/Downloading-Spring-artifacts[downloading Spring artifacts] for Maven repository information.
|
||||
|
||||
== Documentation
|
||||
Be sure to read the http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/[Spring Security Reference].
|
||||
Extensive JavaDoc for the Spring Security code is also available in the http://docs.spring.io/spring-security/site/docs/current/apidocs/[Spring Security API Documentation].
|
||||
|
||||
== Quick Start
|
||||
We recommend you visit http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/[Spring Security Reference] and read the "Getting Started" page.
|
||||
|
||||
== Building from Source
|
||||
Spring Security uses a http://gradle.org[Gradle]-based build system.
|
||||
In the instructions below, http://vimeo.com/34436402[`./gradlew`] is invoked from the root of the source tree and serves as
|
||||
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].
|
||||
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.7.0` folder extracted from the JDK download.
|
||||
|
||||
=== Check out sources
|
||||
[indent=0]
|
||||
----
|
||||
git clone git@github.com:spring-projects/spring-security.git
|
||||
----
|
||||
|
||||
=== Install all spring-\* jars into your local Maven cache
|
||||
[indent=0]
|
||||
----
|
||||
./gradlew install
|
||||
----
|
||||
|
||||
=== Compile and test; build all jars, distribution zips, and docs
|
||||
[indent=0]
|
||||
----
|
||||
./gradlew build
|
||||
----
|
||||
|
||||
Discover more commands with `./gradlew tasks`.
|
||||
See also the https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ[Gradle build and release FAQ].
|
||||
|
||||
== Getting Support
|
||||
Check out the http://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow].
|
||||
http://spring.io/services[Commercial support] is available too.
|
||||
|
||||
== Contributing
|
||||
http://help.github.com/send-pull-requests[Pull requests] are welcome; see the https://github.com/spring-projects/spring-security/blob/master/CONTRIBUTING.md[contributor guidelines] for details.
|
||||
|
||||
== License
|
||||
Spring Security is Open Source software released under the
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
|
||||
+11
-17
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-acl</name>
|
||||
<description>spring-security-acl</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -88,13 +82,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -107,7 +101,7 @@
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>2.6.5</version>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -150,19 +144,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.security.acls;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -121,8 +122,9 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
try {
|
||||
p = permissionFactory.buildFromName(permString);
|
||||
} catch(IllegalArgumentException notfound) {
|
||||
p = permissionFactory.buildFromName(permString.toUpperCase());
|
||||
}
|
||||
catch (IllegalArgumentException notfound) {
|
||||
p = permissionFactory.buildFromName(permString.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
if (p != null) {
|
||||
|
||||
@@ -4,6 +4,8 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AclService;
|
||||
@@ -36,4 +38,26 @@ public class AclPermissionEvaluatorTests {
|
||||
|
||||
assertTrue(pe.hasPermission(mock(Authentication.class), new Object(), "READ"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePermissionNonEnglishLocale() {
|
||||
Locale systemLocale = Locale.getDefault();
|
||||
Locale.setDefault(new Locale("tr"));
|
||||
|
||||
AclService service = mock(AclService.class);
|
||||
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
||||
ObjectIdentity oid = mock(ObjectIdentity.class);
|
||||
ObjectIdentityRetrievalStrategy oidStrategy = mock(ObjectIdentityRetrievalStrategy.class);
|
||||
when(oidStrategy.getObjectIdentity(anyObject())).thenReturn(oid);
|
||||
pe.setObjectIdentityRetrievalStrategy(oidStrategy);
|
||||
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);
|
||||
|
||||
assertTrue(pe.hasPermission(mock(Authentication.class), new Object(), "write"));
|
||||
|
||||
Locale.setDefault(systemLocale);
|
||||
}
|
||||
}
|
||||
|
||||
-7
@@ -1,6 +1,5 @@
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.fest.assertions.Assertions.*;
|
||||
@@ -12,17 +11,12 @@ import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -43,7 +37,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Tests {@link EhCacheBasedAclCache}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
Implementation-Title: org.springframework.security.acls
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.acls
|
||||
Bundle-Name: Spring Security Acls
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.aopalliance.*;version="${aopAllianceRange}",
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.springframework.cache.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.access.*;version="${secRange}",
|
||||
org.springframework.security.util.*;version="${secRange}",
|
||||
org.springframework.context.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.dao.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.jdbc.core.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.transaction.support.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.util.*;version="${springRange}";resolution:=optional,
|
||||
net.sf.ehcache.*;version="${ehcacheRange}";resolution:=optional,
|
||||
javax.sql.*;version="0";resolution:=optional
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion"
|
||||
|
||||
|
||||
+7
-13
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-aspects</name>
|
||||
<description>spring-security-aspects</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,35 +42,29 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -132,13 +126,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
Implementation-Title: org.springframework.security.aspects
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.aspects
|
||||
Bundle-Name: Spring Security Aspects
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Version: ${version}
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.aspectj.*;version="${aspectjRange}";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.access.intercept.aspectj;version="${secRange}",
|
||||
org.springframework.beans.factory;version="${springRange}"
|
||||
+14
-7
@@ -6,6 +6,7 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.6")
|
||||
classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2")
|
||||
classpath("org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE")
|
||||
classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.3")
|
||||
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
||||
@@ -25,8 +26,10 @@ allprojects {
|
||||
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.springVersion = '4.1.0.RC2'
|
||||
ext.springLdapVersion = '2.0.1.RELEASE'
|
||||
ext.springVersion = '3.2.13.RELEASE'
|
||||
ext.spring4Version = '4.1.6.RELEASE'
|
||||
ext.springLdapVersion = '1.3.2.RELEASE'
|
||||
ext.springLdap2Version = '2.0.1.RELEASE'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
|
||||
@@ -37,7 +40,7 @@ allprojects {
|
||||
maven { url "http://repo.terracotta.org/maven2/" }
|
||||
}
|
||||
|
||||
eclipse.project.name = "${project.name}-4.0.x"
|
||||
eclipse.project.name = "${project.name}-3.2.x"
|
||||
}
|
||||
|
||||
sonarRunner {
|
||||
@@ -96,18 +99,22 @@ configure(javaProjects) {
|
||||
}
|
||||
|
||||
configure(coreModuleProjects) {
|
||||
apply plugin: 'bundlor'
|
||||
apply plugin: 'emma'
|
||||
apply plugin: 'spring-io'
|
||||
|
||||
ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : '1.1.0.BUILD-SNAPSHOT'
|
||||
ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : 'latest.integration'
|
||||
|
||||
bundlor.doFirst {
|
||||
def templateText = file("template.mf").text
|
||||
bundlor.manifestTemplate = new SimpleTemplateEngine().createTemplate(templateText).make(bundlorProperties).toString()
|
||||
}
|
||||
configurations {
|
||||
jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
|
||||
}
|
||||
|
||||
dependencies {
|
||||
springIoVersions "io.spring.platform:platform-versions:${springIoVersion}@properties"
|
||||
jacoco "org.jacoco:org.jacoco.agent:0.6.2.201302030002:runtime"
|
||||
springIoVersions "io.spring.platform:platform-versions:${springIoVersion}@properties"
|
||||
}
|
||||
test {
|
||||
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
|
||||
@@ -138,7 +145,7 @@ task dist(type: Zip) {
|
||||
def zipRootDir = "${project.name}-$version"
|
||||
into(zipRootDir) {
|
||||
from(rootDir) {
|
||||
include '*.txt'
|
||||
include '*.adoc'
|
||||
}
|
||||
into('docs') {
|
||||
with(project(':docs').apiSpec)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
project(':spring-security-web'),
|
||||
springCoreDependency,
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
|
||||
+9
-15
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-cas</name>
|
||||
<description>spring-security-cas</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -94,7 +88,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -107,7 +101,7 @@
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>2.6.5</version>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -150,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Implementation-Title: org.springframework.security.cas
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.cas
|
||||
Bundle-Name: Spring Security CAS
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.jasig.cas.client.*;version="${casRange}",
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.authentication.*;version="${secRange}",
|
||||
org.springframework.security.web.*;version="${secRange}",
|
||||
org.springframework.beans.*;version="${springRange}",
|
||||
org.springframework.cache.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.context.*;version="${springRange}",
|
||||
org.springframework.dao;version="${springRange}",
|
||||
org.springframework.util;version="${springRange}",
|
||||
net.sf.ehcache.*;version="${ehcacheRange}";resolution:=optional,
|
||||
javax.servlet.*;version="0"
|
||||
@@ -10,6 +10,7 @@ compileTestJava.dependsOn(':spring-security-core:compileTestJava')
|
||||
dependencies {
|
||||
// NB: Don't add other compile time dependencies to the config module as this breaks tooling
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
@@ -18,9 +19,8 @@ dependencies {
|
||||
optional project(':spring-security-web'),
|
||||
project(':spring-security-ldap'),
|
||||
project(':spring-security-openid'),
|
||||
project(':spring-security-messaging'),
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.springframework:spring-websocket:$springVersion",
|
||||
project(':spring-security-aspects'),
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.springframework:spring-webmvc:$springVersion",
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
@@ -30,7 +30,6 @@ dependencies {
|
||||
|
||||
testCompile project(':spring-security-cas'),
|
||||
project(':spring-security-core').sourceSets.test.output,
|
||||
project(':spring-security-aspects'),
|
||||
'javax.annotation:jsr250-api:1.0',
|
||||
"org.springframework.ldap:spring-ldap-core:$springLdapVersion",
|
||||
"org.springframework:spring-expression:$springVersion",
|
||||
@@ -56,7 +55,7 @@ dependencies {
|
||||
testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
}
|
||||
testCompile("org.springframework.data:spring-data-jpa:$springDataJpaVersion") {
|
||||
testCompile('org.springframework.data:spring-data-jpa:1.4.1.RELEASE') {
|
||||
exclude group: 'org.aspectj', module: 'aspectjrt'
|
||||
}
|
||||
|
||||
|
||||
+28
-47
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-config</name>
|
||||
<description>spring-security-config</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -107,64 +101,57 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-messaging</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-websocket</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -303,7 +290,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -315,31 +302,31 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-support</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-core</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4-common</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-reflect</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -375,7 +362,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.7.0.RC1</version>
|
||||
<version>1.4.1.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -387,37 +374,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap-core</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>1.3.2.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class AuthenticationConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
|
||||
public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
|
||||
return new EnableGlobalAuthenticationAutowiredConfigurer(context);
|
||||
}
|
||||
|
||||
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.aop.config.AopConfigUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
/**
|
||||
* Registers an
|
||||
* {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
|
||||
* AnnotationAwareAspectJAutoProxyCreator} against the current
|
||||
* {@link BeanDefinitionRegistry} as appropriate based on a given @
|
||||
* {@link EnableGlobalMethodSecurity} annotation.
|
||||
*
|
||||
* <p>
|
||||
* Note: This class is necessary because AspectJAutoProxyRegistrar only supports
|
||||
* EnableAspectJAutoProxy.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
class GlobalMethodSecurityAspectJAutoProxyRegistrar implements
|
||||
ImportBeanDefinitionRegistrar {
|
||||
|
||||
/**
|
||||
* Register, escalate, and configure the AspectJ auto proxy creator based on
|
||||
* the value of the @{@link EnableGlobalMethodSecurity#proxyTargetClass()}
|
||||
* attribute on the importing {@code @Configuration} class.
|
||||
*/
|
||||
public void registerBeanDefinitions(
|
||||
AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
BeanDefinition interceptor = registry.getBeanDefinition("methodSecurityInterceptor");
|
||||
|
||||
BeanDefinitionBuilder aspect =
|
||||
BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect");
|
||||
aspect.setFactoryMethod("aspectOf");
|
||||
aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
aspect.addPropertyValue("securityInterceptor", interceptor);
|
||||
|
||||
registry.registerBeanDefinition("annotationSecurityAspect$0", aspect.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||
import org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect;
|
||||
|
||||
/**
|
||||
* Creates the AnnotationSecurityAspect for use with AspectJ based security.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
class GlobalMethodSecurityAspectJConfiguration {
|
||||
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@Bean
|
||||
public AnnotationSecurityAspect annotationSecurityAspect(@Qualifier("methodSecurityInterceptor") MethodInterceptor methodSecurityInterceptor) {
|
||||
AnnotationSecurityAspect result = AnnotationSecurityAspect.aspectOf();
|
||||
result.setSecurityInterceptor((AspectJMethodSecurityInterceptor )methodSecurityInterceptor);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -24,6 +24,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -85,8 +86,8 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
private AuthenticationManagerBuilder auth;
|
||||
private boolean disableAuthenticationRegistry;
|
||||
private AnnotationAttributes enableMethodSecurity;
|
||||
private ApplicationContext context;
|
||||
private MethodSecurityExpressionHandler expressionHandler;
|
||||
private AuthenticationConfiguration authenticationConfiguration;
|
||||
|
||||
/**
|
||||
* Creates the default MethodInterceptor which is a MethodSecurityInterceptor using the following methods to
|
||||
@@ -351,14 +352,13 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluators.get(0));
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
|
||||
this.authenticationConfiguration = authenticationConfiguration;
|
||||
@Autowired
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private AuthenticationConfiguration getAuthenticationConfiguration() {
|
||||
Assert.notNull(authenticationConfiguration, "authenticationConfiguration cannot be null");
|
||||
return authenticationConfiguration;
|
||||
return context.getBean(AuthenticationConfiguration.class);
|
||||
}
|
||||
|
||||
private boolean prePostEnabled() {
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ final class GlobalMethodSecuritySelector implements ImportSelector {
|
||||
|
||||
AdviceMode mode = attributes.getEnum("mode");
|
||||
String autoProxyClassName = AdviceMode.PROXY == mode ? AutoProxyRegistrar.class.getName()
|
||||
: GlobalMethodSecurityAspectJAutoProxyRegistrar.class.getName();
|
||||
: GlobalMethodSecurityAspectJConfiguration.class.getName();
|
||||
if(skipMethodSecurityConfiguration) {
|
||||
return new String[] { autoProxyClassName };
|
||||
}
|
||||
|
||||
+2
-2
@@ -113,7 +113,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends S
|
||||
* been added using {@link #addFilterAfter(Filter, Class)} or
|
||||
* {@link #addFilterBefore(Filter, Class)}.
|
||||
*
|
||||
* @param filter the {@link Filter} to register before the type {@code afterFilter}
|
||||
* @param filter the {@link Filter} to register after the type {@code afterFilter}
|
||||
* @param afterFilter the Class of the known {@link Filter}.
|
||||
* @return the {@link HttpSecurity} for further customizations
|
||||
*/
|
||||
@@ -171,4 +171,4 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends S
|
||||
* @return the {@link HttpSecurity} for further customizations
|
||||
*/
|
||||
H addFilter(Filter filter);
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -40,6 +40,7 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.context.DelegatingApplicationListener;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
@@ -72,6 +73,11 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
@Bean
|
||||
public static DelegatingApplicationListener delegatingApplicationListener() {
|
||||
return new DelegatingApplicationListener();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
|
||||
public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
|
||||
|
||||
+2
-1
@@ -151,7 +151,8 @@ abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConf
|
||||
* @return the default {@code AccessDecisionManager}
|
||||
*/
|
||||
private AccessDecisionManager createDefaultAccessDecisionManager(H http) {
|
||||
return new AffirmativeBased(getDecisionVoters(http));
|
||||
AffirmativeBased result = new AffirmativeBased(getDecisionVoters(http));
|
||||
return postProcess(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>> extends Abst
|
||||
* @return the {@link CsrfConfigurer} for further customizations
|
||||
*/
|
||||
public CsrfConfigurer<H> requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher) {
|
||||
Assert.notNull(csrfTokenRepository, "requireCsrfProtectionMatcher cannot be null");
|
||||
Assert.notNull(requireCsrfProtectionMatcher, "requireCsrfProtectionMatcher cannot be null");
|
||||
this.requireCsrfProtectionMatcher = requireCsrfProtectionMatcher;
|
||||
return this;
|
||||
}
|
||||
|
||||
+6
-1
@@ -32,12 +32,13 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
@@ -167,6 +168,10 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
if(authenticationDetailsSource != null) {
|
||||
basicAuthenticationFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
}
|
||||
RememberMeServices rememberMeServices = http.getSharedObject(RememberMeServices.class);
|
||||
if(rememberMeServices != null) {
|
||||
basicAuthenticationFilter.setRememberMeServices(rememberMeServices);
|
||||
}
|
||||
basicAuthenticationFilter = postProcess(basicAuthenticationFilter);
|
||||
http.addFilter(basicAuthenticationFilter);
|
||||
}
|
||||
|
||||
+38
-6
@@ -22,10 +22,15 @@ import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.GenericApplicationListenerAdapter;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.context.DelegatingApplicationListener;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
@@ -83,11 +88,12 @@ import org.springframework.util.Assert;
|
||||
* @see ConcurrentSessionFilter
|
||||
*/
|
||||
public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<SessionManagementConfigurer<H>,H> {
|
||||
private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy();
|
||||
private final SessionAuthenticationStrategy DEFAULT_SESSION_FIXATION_STRATEGY = createDefaultSessionFixationProtectionStrategy();
|
||||
private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = DEFAULT_SESSION_FIXATION_STRATEGY;
|
||||
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
|
||||
private InvalidSessionStrategy invalidSessionStrategy;
|
||||
private List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<SessionAuthenticationStrategy>();
|
||||
private SessionRegistry sessionRegistry = new SessionRegistryImpl();
|
||||
private SessionRegistry sessionRegistry;
|
||||
private Integer maximumSessions;
|
||||
private String expiredUrl;
|
||||
private boolean maxSessionsPreventsLogin;
|
||||
@@ -367,14 +373,14 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
http.setSharedObject(RequestCache.class, new NullRequestCache());
|
||||
}
|
||||
}
|
||||
http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy());
|
||||
http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy(http));
|
||||
http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
||||
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository, getSessionAuthenticationStrategy());
|
||||
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository, getSessionAuthenticationStrategy(http));
|
||||
if(sessionAuthenticationErrorUrl != null) {
|
||||
sessionManagementFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(sessionAuthenticationErrorUrl));
|
||||
}
|
||||
@@ -389,7 +395,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
http.addFilter(sessionManagementFilter);
|
||||
if(isConcurrentSessionControlEnabled()) {
|
||||
ConcurrentSessionFilter concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry, expiredUrl);
|
||||
ConcurrentSessionFilter concurrentSessionFilter = new ConcurrentSessionFilter(getSessionRegistry(http), expiredUrl);
|
||||
concurrentSessionFilter = postProcess(concurrentSessionFilter);
|
||||
http.addFilter(concurrentSessionFilter);
|
||||
}
|
||||
@@ -444,12 +450,16 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
*
|
||||
* @return the {@link SessionAuthenticationStrategy} to use
|
||||
*/
|
||||
private SessionAuthenticationStrategy getSessionAuthenticationStrategy() {
|
||||
private SessionAuthenticationStrategy getSessionAuthenticationStrategy(H http) {
|
||||
if(sessionAuthenticationStrategy != null) {
|
||||
return sessionAuthenticationStrategy;
|
||||
}
|
||||
List<SessionAuthenticationStrategy> delegateStrategies = sessionAuthenticationStrategies;
|
||||
if(DEFAULT_SESSION_FIXATION_STRATEGY == sessionFixationAuthenticationStrategy) {
|
||||
sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy);
|
||||
}
|
||||
if(isConcurrentSessionControlEnabled()) {
|
||||
SessionRegistry sessionRegistry = getSessionRegistry(http);
|
||||
ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry);
|
||||
concurrentSessionControlStrategy.setMaximumSessions(maximumSessions);
|
||||
concurrentSessionControlStrategy.setExceptionIfMaximumExceeded(maxSessionsPreventsLogin);
|
||||
@@ -466,6 +476,28 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
return sessionAuthenticationStrategy;
|
||||
}
|
||||
|
||||
private SessionRegistry getSessionRegistry(H http) {
|
||||
if(sessionRegistry == null) {
|
||||
SessionRegistryImpl sessionRegistry = new SessionRegistryImpl();
|
||||
registerDelegateApplicationListener(http, sessionRegistry);
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
}
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
private void registerDelegateApplicationListener(H http, ApplicationListener<?> delegate) {
|
||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
||||
if(context == null) {
|
||||
return;
|
||||
}
|
||||
if(context.getBeansOfType(DelegatingApplicationListener.class).isEmpty()) {
|
||||
return;
|
||||
}
|
||||
DelegatingApplicationListener delegating = context.getBean(DelegatingApplicationListener.class);
|
||||
SmartApplicationListener smartListener = new GenericApplicationListenerAdapter(delegate);
|
||||
delegating.addListener(smartListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the number of concurrent sessions per user should be restricted.
|
||||
* @return
|
||||
|
||||
-303
@@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.messaging;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer;
|
||||
import org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory;
|
||||
import org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource;
|
||||
import org.springframework.security.messaging.util.matcher.MessageMatcher;
|
||||
import org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Allows mapping security constraints using {@link MessageMatcher} to the security expressions.
|
||||
*
|
||||
* @since 4.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class MessageSecurityMetadataSourceRegistry {
|
||||
private static final String permitAll = "permitAll";
|
||||
private static final String denyAll = "denyAll";
|
||||
private static final String anonymous = "anonymous";
|
||||
private static final String authenticated = "authenticated";
|
||||
private static final String fullyAuthenticated = "fullyAuthenticated";
|
||||
private static final String rememberMe = "rememberMe";
|
||||
|
||||
private final LinkedHashMap<MatcherBuilder,String> matcherToExpression = new LinkedHashMap<MatcherBuilder,String>();
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
/**
|
||||
* Maps any {@link Message} to a security expression.
|
||||
*
|
||||
* @return the Expression to associate
|
||||
*/
|
||||
public Constraint anyMessage() {
|
||||
return matchers(MessageMatcher.ANY_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a {@link List} of {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher} instances.
|
||||
*
|
||||
* @param patterns the patterns to create {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher}
|
||||
* from. Uses {@link MessageSecurityMetadataSourceRegistry#pathMatcher(PathMatcher)}.
|
||||
*
|
||||
* @return the {@link Constraint} that is associated to the {@link MessageMatcher}
|
||||
* @see {@link MessageSecurityMetadataSourceRegistry#pathMatcher(PathMatcher)}
|
||||
*/
|
||||
public Constraint destinationMatchers(String... patterns) {
|
||||
List<MatcherBuilder> matchers = new ArrayList<MatcherBuilder>(patterns.length);
|
||||
for(String pattern : patterns) {
|
||||
matchers.add(new PathMatcherMessageMatcherBuilder(pattern));
|
||||
}
|
||||
return new Constraint(matchers);
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link PathMatcher} to be used with the {@link MessageSecurityMetadataSourceRegistry#destinationMatchers(String...)}.
|
||||
* The default is to use the default constructor of {@link AntPathMatcher}.
|
||||
*
|
||||
* @param pathMatcher the {@link PathMatcher} to use. Cannot be null.
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization.
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry pathMatcher(PathMatcher pathMatcher) {
|
||||
Assert.notNull(pathMatcher, "pathMatcher cannot be null");
|
||||
this.pathMatcher = pathMatcher;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a {@link List} of {@link MessageMatcher} instances to a security expression.
|
||||
*
|
||||
* @param matchers the {@link MessageMatcher} instances to map.
|
||||
* @return The {@link Constraint} that is associated to the {@link MessageMatcher} instances
|
||||
*/
|
||||
public Constraint matchers(MessageMatcher<?>... matchers) {
|
||||
List<MatcherBuilder> builders = new ArrayList<MatcherBuilder>(matchers.length);
|
||||
for(MessageMatcher<?> matcher : matchers) {
|
||||
builders.add(new PreBuiltMatcherBuilder(matcher));
|
||||
}
|
||||
return new Constraint(builders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to create creating a {@link MessageSecurityMetadataSource}.
|
||||
*
|
||||
* <p>This is not exposed so as not to confuse users of the API, which should never invoke this method.</p>
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSource} to use
|
||||
*/
|
||||
protected MessageSecurityMetadataSource createMetadataSource() {
|
||||
LinkedHashMap<MessageMatcher<?>,String> matcherToExpression = new LinkedHashMap<MessageMatcher<?>,String>();
|
||||
for(Map.Entry<MatcherBuilder,String> entry : this.matcherToExpression.entrySet()) {
|
||||
matcherToExpression.put(entry.getKey().build(), entry.getValue());
|
||||
}
|
||||
return ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(matcherToExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the security constraint to be applied to the {@link MessageMatcher} instances.
|
||||
*/
|
||||
public class Constraint {
|
||||
private final List<MatcherBuilder> messageMatchers;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param messageMatchers the {@link MessageMatcher} instances to map to this constraint
|
||||
*/
|
||||
private Constraint(List<MatcherBuilder> messageMatchers) {
|
||||
Assert.notEmpty(messageMatchers, "messageMatchers cannot be null or empty");
|
||||
this.messageMatchers = messageMatchers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for specifying {@link Message} instances require a particular role. If you do not want to have "ROLE_" automatically
|
||||
* inserted see {@link #hasAuthority(String)}.
|
||||
*
|
||||
* @param role the role to require (i.e. USER, ADMIN, etc). Note, it should not start with "ROLE_" as
|
||||
* this is automatically inserted.
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry hasRole(String role) {
|
||||
return access(MessageSecurityMetadataSourceRegistry.hasRole(role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for specifying {@link Message} instances require any of a number of roles. If you
|
||||
* do not want to have "ROLE_" automatically inserted see
|
||||
* {@link #hasAnyAuthority(String...)}
|
||||
*
|
||||
* @param roles
|
||||
* the roles to require (i.e. USER, ADMIN, etc). Note, it
|
||||
* should not start with "ROLE_" as this is automatically
|
||||
* inserted.
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further
|
||||
* customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry hasAnyRole(String... roles) {
|
||||
return access(MessageSecurityMetadataSourceRegistry.hasAnyRole(roles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that {@link Message} instances require a particular authority.
|
||||
*
|
||||
* @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry hasAuthority(String authority) {
|
||||
return access(MessageSecurityMetadataSourceRegistry.hasAuthority(authority));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that {@link Message} instances requires any of a number authorities.
|
||||
*
|
||||
* @param authorities the requests require at least one of the authorities (i.e. "ROLE_USER","ROLE_ADMIN" would
|
||||
* mean either "ROLE_USER" or "ROLE_ADMIN" is required).
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry hasAnyAuthority(String... authorities) {
|
||||
return access(MessageSecurityMetadataSourceRegistry.hasAnyAuthority(authorities));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that Messages are allowed by anyone.
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry permitAll() {
|
||||
return access(permitAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that Messages are allowed by anonymous users.
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry anonymous() {
|
||||
return access(anonymous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that Messages are allowed by users that have been remembered.
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
* @see {@link RememberMeConfigurer}
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry rememberMe() {
|
||||
return access(rememberMe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that Messages are not allowed by anyone.
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry denyAll() {
|
||||
return access(denyAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that Messages are allowed by any authenticated user.
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry authenticated() {
|
||||
return access(authenticated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that Messages are allowed by users who have authenticated and were not "remembered".
|
||||
*
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
* @see {@link RememberMeConfigurer}
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry fullyAuthenticated() {
|
||||
return access(fullyAuthenticated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows specifying that Messages are secured by an arbitrary expression
|
||||
*
|
||||
* @param attribute the expression to secure the URLs (i.e. "hasRole('ROLE_USER') and hasRole('ROLE_SUPER')")
|
||||
* @return the {@link MessageSecurityMetadataSourceRegistry} for further customization
|
||||
*/
|
||||
public MessageSecurityMetadataSourceRegistry access(String attribute) {
|
||||
for(MatcherBuilder messageMatcher : messageMatchers) {
|
||||
matcherToExpression.put(messageMatcher, attribute);
|
||||
}
|
||||
return MessageSecurityMetadataSourceRegistry.this;
|
||||
}
|
||||
}
|
||||
|
||||
private static String hasAnyRole(String... authorities) {
|
||||
String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','ROLE_");
|
||||
return "hasAnyRole('ROLE_" + anyAuthorities + "')";
|
||||
}
|
||||
|
||||
private static String hasRole(String role) {
|
||||
Assert.notNull(role, "role cannot be null");
|
||||
if (role.startsWith("ROLE_")) {
|
||||
throw new IllegalArgumentException("role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'");
|
||||
}
|
||||
return "hasRole('ROLE_" + role + "')";
|
||||
}
|
||||
|
||||
private static String hasAuthority(String authority) {
|
||||
return "hasAuthority('" + authority + "')";
|
||||
}
|
||||
|
||||
private static String hasAnyAuthority(String... authorities) {
|
||||
String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','");
|
||||
return "hasAnyAuthority('" + anyAuthorities + "')";
|
||||
}
|
||||
|
||||
private class PreBuiltMatcherBuilder implements MatcherBuilder {
|
||||
private MessageMatcher<?> matcher;
|
||||
|
||||
private PreBuiltMatcherBuilder(MessageMatcher<?> matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageMatcher<?> build() {
|
||||
return matcher;
|
||||
}
|
||||
}
|
||||
|
||||
private class PathMatcherMessageMatcherBuilder implements MatcherBuilder {
|
||||
private final String pattern;
|
||||
|
||||
private PathMatcherMessageMatcherBuilder(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageMatcher<?> build() {
|
||||
return new SimpDestinationMessageMatcher(pattern, pathMatcher);
|
||||
}
|
||||
}
|
||||
|
||||
private interface MatcherBuilder {
|
||||
MessageMatcher<?> build();
|
||||
}
|
||||
}
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.socket;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.messaging.simp.config.ChannelRegistration;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
|
||||
import org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory;
|
||||
import org.springframework.security.messaging.access.expression.MessageExpressionVoter;
|
||||
import org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor;
|
||||
import org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource;
|
||||
import org.springframework.security.messaging.context.SecurityContextChannelInterceptor;
|
||||
import org.springframework.security.messaging.util.matcher.MessageMatcher;
|
||||
import org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher;
|
||||
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Allows configuring WebSocket Authorization.
|
||||
*
|
||||
* <p>For example:</p>
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
* public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(MessageSecurityMetadataSourceRegistry messages) {
|
||||
* messages
|
||||
* .destinationMatchers("/user/queue/errors").permitAll()
|
||||
* .destinationMatchers("/admin/**").hasRole("ADMIN")
|
||||
* .anyMessage().authenticated();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @since 4.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE + 100)
|
||||
public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends AbstractWebSocketMessageBrokerConfigurer {
|
||||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {}
|
||||
|
||||
@Override
|
||||
public void configureClientInboundChannel(ChannelRegistration registration) {
|
||||
registration.setInterceptors(securityContextChannelInterceptor(),channelSecurity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureClientOutboundChannel(ChannelRegistration registration) {
|
||||
registration.setInterceptors(securityContextChannelInterceptor(),channelSecurity());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ChannelSecurityInterceptor channelSecurity() {
|
||||
ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor(metadataSource());
|
||||
List<AccessDecisionVoter> voters = new ArrayList<AccessDecisionVoter>();
|
||||
voters.add(new MessageExpressionVoter());
|
||||
AffirmativeBased manager = new AffirmativeBased(voters);
|
||||
channelSecurityInterceptor.setAccessDecisionManager(manager);
|
||||
return channelSecurityInterceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityContextChannelInterceptor securityContextChannelInterceptor() {
|
||||
return new SecurityContextChannelInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageSecurityMetadataSource metadataSource() {
|
||||
WebSocketMessageSecurityMetadataSourceRegistry registry = new WebSocketMessageSecurityMetadataSourceRegistry();
|
||||
configure(registry);
|
||||
return registry.createMetadataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param messages
|
||||
*/
|
||||
protected abstract void configure(MessageSecurityMetadataSourceRegistry messages);
|
||||
|
||||
private class WebSocketMessageSecurityMetadataSourceRegistry extends MessageSecurityMetadataSourceRegistry {
|
||||
@Override
|
||||
public MessageSecurityMetadataSource createMetadataSource() {
|
||||
return super.createMetadataSource();
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -16,7 +16,12 @@
|
||||
package org.springframework.security.config.annotation.authentication.configuration;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactoryBean
|
||||
import org.springframework.beans.BeansException
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
@@ -325,4 +330,44 @@ class AuthenticationConfigurationTests extends BaseSpringSpec {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2822: Cannot Force Authentication already built"() {
|
||||
setup:
|
||||
loadConfig(Sec2822WebSecurity,Sec2822UseAuth,Sec2822Config)
|
||||
when:
|
||||
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
|
||||
config.getAuthenticationManager()
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(AuthenticationConfiguration)
|
||||
static class Sec2822Config {}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.inMemoryAuthentication()
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Sec2822UseAuth {
|
||||
@Autowired
|
||||
public void useAuthenticationManager(AuthenticationConfiguration auth) {
|
||||
auth.authenticationManager
|
||||
}
|
||||
|
||||
// Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
|
||||
// must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
|
||||
@Bean
|
||||
public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
|
||||
new BootGlobalAuthenticationConfigurerAdapter()
|
||||
}
|
||||
|
||||
static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
|
||||
}
|
||||
}
|
||||
+66
@@ -15,6 +15,13 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.method.configuration
|
||||
|
||||
import org.springframework.beans.BeansException
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
|
||||
import javax.sql.DataSource
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
@@ -339,4 +346,63 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2815: @EnableGlobalMethodSecurity does not trigger eager initialization of Beans in GlobalAuthenticationConfigurer"() {
|
||||
setup:
|
||||
Sec2815Config.dataSource = Mock(DataSource)
|
||||
when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
|
||||
loadConfig(Sec2815Config)
|
||||
then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
|
||||
context.getBean(MockBeanPostProcessor).beforeInit['dataSource']
|
||||
context.getBean(MockBeanPostProcessor).afterInit['dataSource']
|
||||
}
|
||||
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
static class Sec2815Config {
|
||||
static DataSource dataSource;
|
||||
|
||||
@Bean
|
||||
public MethodSecurityService service() {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MockBeanPostProcessor mockBeanPostProcessor() {
|
||||
new MockBeanPostProcessor()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
dataSource
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
|
||||
@Autowired
|
||||
DataSource dataSource
|
||||
|
||||
@Override
|
||||
void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class MockBeanPostProcessor implements BeanPostProcessor {
|
||||
Map<String,Object> beforeInit = new HashMap<String,Object>()
|
||||
Map<String,Object> afterInit = new HashMap<String,Object>()
|
||||
|
||||
@Override
|
||||
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
beforeInit[beanName] = bean
|
||||
bean
|
||||
}
|
||||
|
||||
@Override
|
||||
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
afterInit[beanName] = bean
|
||||
bean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -13,7 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
package org.springframework.security.config.annotation.web.configuration
|
||||
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
@@ -342,4 +344,9 @@ class WebSecurityConfigurationTests extends BaseSpringSpec {
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class ChildConfig extends WebSecurityConfigurerAdapter { }
|
||||
|
||||
def "SEC-2773: delegatingApplicationListener is static method"() {
|
||||
expect: 'delegatingApplicationListener to prevent premature instantiation of WebSecurityConfiguration'
|
||||
Modifier.isStatic(WebSecurityConfiguration.metaClass.methods.find { it.name == 'delegatingApplicationListener'}.modifiers)
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -237,6 +237,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
setup:
|
||||
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
|
||||
(1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfTokenRepositoryConfig.repo.generateToken(_) >> csrfToken
|
||||
loadConfig(CsrfTokenRepositoryConfig)
|
||||
request.method = "POST"
|
||||
request.getSession()
|
||||
@@ -391,6 +392,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
def "csrf disables POST requests from RequestCache"() {
|
||||
setup:
|
||||
CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
|
||||
loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
|
||||
request.servletPath = "/some-url"
|
||||
request.requestURI = "/some-url"
|
||||
@@ -417,6 +419,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
def "csrf enables GET requests with RequestCache"() {
|
||||
setup:
|
||||
CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
|
||||
loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
|
||||
request.servletPath = "/some-url"
|
||||
request.requestURI = "/some-url"
|
||||
@@ -464,6 +467,13 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def 'SEC-2749: requireCsrfProtectionMatcher null'() {
|
||||
when:
|
||||
new CsrfConfigurer<>().requireCsrfProtectionMatcher(null)
|
||||
then:
|
||||
thrown(IllegalArgumentException)
|
||||
}
|
||||
|
||||
def clearCsrfToken() {
|
||||
request.removeAllParameters()
|
||||
}
|
||||
|
||||
+49
-1
@@ -19,8 +19,12 @@ import static org.springframework.security.config.annotation.web.configurers.Exp
|
||||
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.springframework.beans.BeansException
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.security.access.AccessDecisionManager;
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.event.AuthorizedEvent
|
||||
import org.springframework.security.access.vote.AffirmativeBased
|
||||
@@ -31,7 +35,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
|
||||
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.ExpressionUrlAuthorizationConfigurerConfigs.CustomExpressionRootConfig;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurerConfigs.CustomExpressionRootConfig
|
||||
import org.springframework.security.core.authority.AuthorityUtils
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor
|
||||
|
||||
@@ -540,4 +544,48 @@ public class ExpressionUrlAuthorizationConfigurerTests extends BaseSpringSpec {
|
||||
then: "custom bean expression denies access"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
|
||||
def "SEC-3011: Default AccessDecisionManager postProcessed"() {
|
||||
when:
|
||||
loadConfig(Sec3011Config)
|
||||
then:
|
||||
context.getBean(MockBeanPostProcessor).beans.find { it instanceof AccessDecisionManager }
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class Sec3011Config extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication();
|
||||
}
|
||||
|
||||
@Bean
|
||||
static MockBeanPostProcessor mbpp() {
|
||||
return new MockBeanPostProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
static class MockBeanPostProcessor implements BeanPostProcessor {
|
||||
List<Object> beans = new ArrayList<Object>();
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
beans.add(bean);
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+26
@@ -24,6 +24,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
|
||||
|
||||
@@ -133,4 +134,29 @@ class HttpBasicConfigurerTests extends BaseSpringSpec {
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-3019: Basic Authentication uses RememberMe Config"() {
|
||||
when:
|
||||
loadConfig(BasicUsesRememberMeConfig)
|
||||
then:
|
||||
findFilter(BasicAuthenticationFilter).rememberMeServices == findFilter(RememberMeAuthenticationFilter).rememberMeServices
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class BasicUsesRememberMeConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.httpBasic().and()
|
||||
.rememberMe()
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
-9
@@ -15,19 +15,20 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers
|
||||
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.mock.web.MockHttpSession
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.core.session.SessionRegistry
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter
|
||||
import org.springframework.security.web.context.SecurityContextRepository
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter
|
||||
import org.springframework.security.web.session.SessionManagementFilter
|
||||
|
||||
@@ -141,6 +142,29 @@ class NamespaceSessionManagementTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2913: Default JavaConfig session fixation AuthenticationStrategy has NullEventPublisher"() {
|
||||
setup:
|
||||
loadConfig(SFPPostProcessedConfig)
|
||||
when:
|
||||
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).onSessionChange("id", new MockHttpSession(), new TestingAuthenticationToken("u","p","ROLE_USER"))
|
||||
then:
|
||||
context.getBean(MockEventListener).events
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MockEventListener eventListener() {
|
||||
new MockEventListener()
|
||||
}
|
||||
}
|
||||
|
||||
def "http/session-management@session-fixation-protection=newSession"() {
|
||||
when:
|
||||
loadConfig(SFPNewSessionSessionManagementConfig)
|
||||
@@ -163,4 +187,13 @@ class NamespaceSessionManagementTests extends BaseSpringSpec {
|
||||
.newSession()
|
||||
}
|
||||
}
|
||||
|
||||
static class MockEventListener implements ApplicationListener<SessionFixationProtectionEvent> {
|
||||
List<SessionFixationProtectionEvent> events = []
|
||||
|
||||
public void onApplicationEvent(SessionFixationProtectionEvent event) {
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -21,7 +21,7 @@ import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.mock.web.MockFilterChain
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver
|
||||
import org.springframework.security.config.annotation.AnyObjectPostProcessor
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
@@ -33,11 +33,13 @@ import org.springframework.security.web.access.ExceptionTranslationFilter
|
||||
import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy
|
||||
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy
|
||||
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy
|
||||
import org.springframework.security.web.context.NullSecurityContextRepository
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter
|
||||
import org.springframework.security.web.context.SecurityContextRepository
|
||||
import org.springframework.security.web.savedrequest.RequestCache
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter
|
||||
import org.springframework.security.web.session.HttpSessionDestroyedEvent
|
||||
import org.springframework.security.web.session.SessionManagementFilter
|
||||
|
||||
/**
|
||||
@@ -154,12 +156,14 @@ class SessionManagementConfigurerTests extends BaseSpringSpec {
|
||||
def 'session fixation and enable concurrency control'() {
|
||||
setup: "context where session fixation is disabled and concurrency control is enabled"
|
||||
loadConfig(ConcurrencyControlConfig)
|
||||
def authenticatedSession
|
||||
when: "authenticate successfully"
|
||||
request.servletPath = "/login"
|
||||
request.method = "POST"
|
||||
request.setParameter("username", "user");
|
||||
request.setParameter("password","password")
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
authenticatedSession = request.session
|
||||
then: "authentication is sucessful"
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/"
|
||||
@@ -173,6 +177,17 @@ class SessionManagementConfigurerTests extends BaseSpringSpec {
|
||||
then:
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == '/login?error'
|
||||
when: 'SEC-2574: When Session Expires and authentication attempted'
|
||||
context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession))
|
||||
super.setup()
|
||||
request.servletPath = "/login"
|
||||
request.method = "POST"
|
||||
request.setParameter("username", "user");
|
||||
request.setParameter("password","password")
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "authentication is successful"
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/"
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@@ -217,6 +232,8 @@ class SessionManagementConfigurerTests extends BaseSpringSpec {
|
||||
1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o}
|
||||
and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor"
|
||||
1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o}
|
||||
and: "SessionFixationProtectionStrategy is registered with ObjectPostProcessor"
|
||||
1 * opp.postProcess(_ as SessionFixationProtectionStrategy) >> {SessionFixationProtectionStrategy o -> o}
|
||||
}
|
||||
|
||||
def "use sharedObject trustResolver"() {
|
||||
|
||||
@@ -119,6 +119,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.servletPath = "/some-url"
|
||||
request.requestURI = "/some-url"
|
||||
@@ -153,6 +154,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.servletPath = "/some-url"
|
||||
request.requestURI = "/some-url"
|
||||
@@ -252,6 +254,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
|
||||
CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.method = "POST"
|
||||
request.setParameter("j_username","user")
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:org/springframework/security/config/sec-2508.xml" )
|
||||
public class Sec2508Tests {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationEntryPoint ep;
|
||||
|
||||
@Test
|
||||
public void loads() {}
|
||||
}
|
||||
-231
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.messaging;
|
||||
|
||||
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.messaging.Message;
|
||||
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource;
|
||||
import org.springframework.security.messaging.util.matcher.MessageMatcher;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MessageSecurityMetadataSourceRegistryTests {
|
||||
@Mock
|
||||
private MessageMatcher<Object> matcher;
|
||||
|
||||
private MessageSecurityMetadataSourceRegistry messages;
|
||||
|
||||
private Message<String> message;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
messages = new MessageSecurityMetadataSourceRegistry();
|
||||
message = MessageBuilder
|
||||
.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "location")
|
||||
.build();
|
||||
}
|
||||
|
||||
// See https://github.com/spring-projects/spring-security/commit/3f30529039c76facf335d6ca69d18d8ae287f3f9#commitcomment-7412712
|
||||
// https://jira.spring.io/browse/SPR-11660
|
||||
@Test
|
||||
public void destinationMatcherCustom() {
|
||||
message = MessageBuilder
|
||||
.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
messages
|
||||
.pathMatcher(new AntPathMatcher("."))
|
||||
.destinationMatchers("price.stock.*").permitAll();
|
||||
|
||||
assertThat(getAttribute()).isNull();
|
||||
|
||||
message = MessageBuilder
|
||||
.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
messages
|
||||
.pathMatcher(new AntPathMatcher("."))
|
||||
.destinationMatchers("price.stock.**").permitAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherCustomSetAfterMatchersDoesNotMatter() {
|
||||
message = MessageBuilder
|
||||
.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
messages
|
||||
.destinationMatchers("price.stock.*").permitAll()
|
||||
.pathMatcher(new AntPathMatcher("."));
|
||||
|
||||
assertThat(getAttribute()).isNull();
|
||||
|
||||
message = MessageBuilder
|
||||
.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
messages
|
||||
.destinationMatchers("price.stock.**").permitAll()
|
||||
.pathMatcher(new AntPathMatcher("."));
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void pathMatcherNull() {
|
||||
messages.pathMatcher(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchersFalse() {
|
||||
messages
|
||||
.matchers(matcher).permitAll();
|
||||
|
||||
assertThat(getAttribute()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchersTrue() {
|
||||
when(matcher.matches(message)).thenReturn(true);
|
||||
messages
|
||||
.matchers(matcher).permitAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherExact() {
|
||||
messages
|
||||
.destinationMatchers("location").permitAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherMulti() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","api/**").hasRole("ADMIN")
|
||||
.destinationMatchers("location").permitAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherRole() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").hasRole("ADMIN")
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("hasRole('ROLE_ADMIN')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherAnyRole() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").hasAnyRole("ADMIN", "ROOT")
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("hasAnyRole('ROLE_ADMIN','ROLE_ROOT')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherAuthority() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").hasAuthority("ROLE_ADMIN")
|
||||
.anyMessage().fullyAuthenticated();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("hasAuthority('ROLE_ADMIN')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherAccess() {
|
||||
String expected = "hasRole('ROLE_ADMIN') and fullyAuthenticated";
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").access(expected)
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherAnyAuthority() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT")
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("hasAnyAuthority('ROLE_ADMIN','ROLE_ROOT')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherRememberMe() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").rememberMe()
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("rememberMe");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherAnonymous() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").anonymous()
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("anonymous");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherFullyAuthenticated() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").fullyAuthenticated()
|
||||
.anyMessage().denyAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("fullyAuthenticated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destinationMatcherDenyAll() {
|
||||
messages
|
||||
.destinationMatchers("admin/**","location/**").denyAll()
|
||||
.anyMessage().permitAll();
|
||||
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
private String getAttribute() {
|
||||
MessageSecurityMetadataSource source = messages.createMetadataSource();
|
||||
Collection<ConfigAttribute> attrs = source.getAttributes(message);
|
||||
if(attrs == null) {
|
||||
return null;
|
||||
}
|
||||
assertThat(attrs.size()).isEqualTo(1);
|
||||
return attrs.iterator().next().toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
|
||||
<constructor-arg>
|
||||
<map>
|
||||
<entry>
|
||||
<key>
|
||||
<bean class="org.springframework.security.web.util.AntPathRequestMatcher">
|
||||
<constructor-arg value="/**"/>
|
||||
</bean>
|
||||
</key>
|
||||
<bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
|
||||
</entry>
|
||||
</map>
|
||||
</constructor-arg>
|
||||
<property name="defaultEntryPoint">
|
||||
<bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,47 @@
|
||||
Implementation-Title: org.springframework.security.config
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.config
|
||||
Bundle-Name: Spring Security Namespace Configuration
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.aopalliance.*;version="${aopAllianceRange}",
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.aopalliance.*;version="${aopAllianceRange}";resolution:=optional,
|
||||
org.aspectj.*;version="${aspectjRange}";resolution:=optional,
|
||||
org.openid4java.*;version="${openid4javaRange}";resolution:=optional,
|
||||
org.springframework.security.access.*;version="${secRange}",
|
||||
org.springframework.security.authentication.*;version="${secRange}",
|
||||
org.springframework.security.context.*;version="${secRange}";resolution:=optional,
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.crypto.bcrypt.*;version="${secRange}",
|
||||
org.springframework.security.crypto.password.*;version="${secRange}",
|
||||
org.springframework.security.crypto.*;version="${secRange}",
|
||||
org.springframework.security.util;version="${secRange}",
|
||||
org.springframework.security.provisioning;version="${secRange}",
|
||||
org.springframework.security.ldap.*;version="${secRange}",
|
||||
org.springframework.security.openid.*;version="${secRange}";resolution:=optional,
|
||||
org.springframework.security.web.*;version="${secRange}";resolution:=optional,
|
||||
org.springframework.security.ldap.*;version="${secRange}";resolution:=optional,
|
||||
org.springframework.security.openid.*;version="${secRange}";resolution:=optional,
|
||||
org.springframework.ldap.*;version="${springLdapRange}";resolution:=optional,
|
||||
org.springframework.aop.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.jdbc.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.http.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.beans.*;version="${springRange}",
|
||||
org.springframework.context.*;version="${springRange}",
|
||||
org.springframework.core.*;version="${springRange}",
|
||||
org.springframework.http.*;version="${springRange}",
|
||||
org.springframework.ldap.*;version="${springLdapRange}",
|
||||
org.springframework.jdbc.*;version="${springRange}",
|
||||
org.springframework.web.*;version="${springRange}",
|
||||
org.springframework.util.*;version="${springRange}",
|
||||
javax.servlet.*;version="0";resolution:=optional,
|
||||
org.openid4java.*;version="${openid4javaRange}",
|
||||
javax.sql.*;version="0";resolution:=optional,
|
||||
javax.naming.directory;version="0";resolution:=optional,
|
||||
org.w3c.dom;version="0";resolution:=optional
|
||||
+2
-1
@@ -13,7 +13,8 @@ configurations {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'aopalliance:aopalliance:1.0',
|
||||
compile springCoreDependency,
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
|
||||
+16
-22
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-core</name>
|
||||
<description>spring-security-core</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -88,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -108,7 +102,7 @@
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>2.6.5</version>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -122,14 +116,14 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -196,7 +190,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -208,7 +202,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-support</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -220,7 +214,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-core</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -232,7 +226,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -244,7 +238,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4-common</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -256,7 +250,7 @@
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-reflect</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -280,7 +274,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
||||
+1
-11
@@ -38,9 +38,7 @@ import org.springframework.security.access.event.AuthorizedEvent;
|
||||
import org.springframework.security.access.event.PublicInvocationEvent;
|
||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -107,7 +105,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
private AccessDecisionManager accessDecisionManager;
|
||||
private AfterInvocationManager afterInvocationManager;
|
||||
private AuthenticationManager authenticationManager = new NoOpAuthenticationManager();
|
||||
private AuthenticationManager authenticationManager;
|
||||
private RunAsManager runAsManager = new NullRunAsManager();
|
||||
|
||||
private boolean alwaysReauthenticate = false;
|
||||
@@ -462,12 +460,4 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, A
|
||||
this.eventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoOpAuthenticationManager implements AuthenticationManager {
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
throw new AuthenticationServiceException("Cannot authenticate " + authentication);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -46,8 +46,14 @@ public abstract class AbstractMethodSecurityMetadataSource implements MethodSecu
|
||||
if (target != null) {
|
||||
targetClass = target instanceof Class<?> ? (Class<?>)target : AopProxyUtils.ultimateTargetClass(target);
|
||||
}
|
||||
|
||||
return getAttributes(mi.getMethod(), targetClass);
|
||||
Collection<ConfigAttribute> attrs = getAttributes(mi.getMethod(), targetClass);
|
||||
if(attrs != null && !attrs.isEmpty()) {
|
||||
return attrs;
|
||||
}
|
||||
if(target != null && !(target instanceof Class<?>)) {
|
||||
attrs = getAttributes(mi.getMethod(), target.getClass());
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Object must be a non-null MethodInvocation");
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
if (isAuthenticated) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
|
||||
"Once created you cannot set this token to authenticated. Create a new instance using the constructor which takes a GrantedAuthority list will mark this as authenticated.");
|
||||
}
|
||||
|
||||
super.setAuthenticated(false);
|
||||
|
||||
-10
@@ -52,14 +52,4 @@ public class SystemWideSaltSource implements SaltSource, InitializingBean {
|
||||
public void setSystemWideSalt(String systemWideSalt) {
|
||||
this.systemWideSalt = systemWideSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the system wide salt
|
||||
* @since 4.0
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return systemWideSalt;
|
||||
}
|
||||
}
|
||||
|
||||
+40
-2
@@ -19,8 +19,17 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Wraps a delegate {@link Callable} with logic for setting up a {@link SecurityContext} before invoking the delegate
|
||||
* {@link Callable} and then removing the {@link SecurityContext} after the delegate has completed.
|
||||
* <p>
|
||||
* Wraps a delegate {@link Callable} with logic for setting up a
|
||||
* {@link SecurityContext} before invoking the delegate {@link Callable} and
|
||||
* then removing the {@link SecurityContext} after the delegate has completed.
|
||||
* </p>
|
||||
* <p>
|
||||
* By default the {@link SecurityContext} is only setup if {@link #call()} is
|
||||
* invoked on a separate {@link Thread} than the
|
||||
* {@link DelegatingSecurityContextCallable} was created on. This can be
|
||||
* overridden by setting {@link #setEnableOnOriginalThread(boolean)} to true.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
@@ -31,6 +40,10 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
||||
|
||||
private final SecurityContext securityContext;
|
||||
|
||||
private final Thread originalThread;
|
||||
|
||||
private boolean enableOnOriginalThread;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DelegatingSecurityContextCallable} with a specific {@link SecurityContext}.
|
||||
* @param delegate the delegate {@link DelegatingSecurityContextCallable} to run with the specified
|
||||
@@ -43,6 +56,7 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
||||
Assert.notNull(securityContext, "securityContext cannot be null");
|
||||
this.delegate = delegate;
|
||||
this.securityContext = securityContext;
|
||||
this.originalThread = Thread.currentThread();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +68,27 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
||||
this(delegate, SecurityContextHolder.getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the SecurityContext should be transfered if {@link #call()}
|
||||
* is invoked on the same {@link Thread} the
|
||||
* {@link DelegatingSecurityContextCallable} was created on.
|
||||
*
|
||||
* @param enableOnOriginalThread
|
||||
* if false (default), will only transfer the
|
||||
* {@link SecurityContext} if {@link #call()} is invoked on a
|
||||
* different {@link Thread} than the
|
||||
* {@link DelegatingSecurityContextCallable} was created on.
|
||||
*
|
||||
* @since 4.0.2
|
||||
*/
|
||||
public void setEnableOnOriginalThread(boolean enableOnOriginalThread) {
|
||||
this.enableOnOriginalThread = enableOnOriginalThread;
|
||||
}
|
||||
|
||||
public V call() throws Exception {
|
||||
if(!enableOnOriginalThread && originalThread == Thread.currentThread()) {
|
||||
return delegate.call();
|
||||
}
|
||||
try {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
return delegate.call();
|
||||
@@ -64,6 +98,10 @@ public final class DelegatingSecurityContextCallable<V> implements Callable<V> {
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DelegatingSecurityContextCallable} and with the given {@link Callable} and
|
||||
* {@link SecurityContext}, but if the securityContext is null will defaults to the current {@link SecurityContext}
|
||||
|
||||
+40
-2
@@ -17,8 +17,17 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Wraps a delegate {@link Runnable} with logic for setting up a {@link SecurityContext} before invoking the delegate
|
||||
* {@link Runnable} and then removing the {@link SecurityContext} after the delegate has completed.
|
||||
* <p>
|
||||
* Wraps a delegate {@link Runnable} with logic for setting up a {@link SecurityContext}
|
||||
* before invoking the delegate {@link Runnable} and then removing the
|
||||
* {@link SecurityContext} after the delegate has completed.
|
||||
* </p>
|
||||
* <p>
|
||||
* By default the {@link SecurityContext} is only setup if {@link #run()} is
|
||||
* invoked on a separate {@link Thread} than the
|
||||
* {@link DelegatingSecurityContextRunnable} was created on. This can be
|
||||
* overridden by setting {@link #setEnableOnOriginalThread(boolean)} to true.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
@@ -29,6 +38,10 @@ public final class DelegatingSecurityContextRunnable implements Runnable {
|
||||
|
||||
private final SecurityContext securityContext;
|
||||
|
||||
private final Thread originalThread;
|
||||
|
||||
private boolean enableOnOriginalThread;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DelegatingSecurityContextRunnable} with a specific {@link SecurityContext}.
|
||||
* @param delegate the delegate {@link Runnable} to run with the specified {@link SecurityContext}. Cannot be null.
|
||||
@@ -40,6 +53,7 @@ public final class DelegatingSecurityContextRunnable implements Runnable {
|
||||
Assert.notNull(securityContext, "securityContext cannot be null");
|
||||
this.delegate = delegate;
|
||||
this.securityContext = securityContext;
|
||||
this.originalThread = Thread.currentThread();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +65,27 @@ public final class DelegatingSecurityContextRunnable implements Runnable {
|
||||
this(delegate, SecurityContextHolder.getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the SecurityContext should be transfered if {@link #call()}
|
||||
* is invoked on the same {@link Thread} the
|
||||
* {@link DelegatingSecurityContextCallable} was created on.
|
||||
*
|
||||
* @param enableOnOriginalThread
|
||||
* if false (default), will only transfer the
|
||||
* {@link SecurityContext} if {@link #call()} is invoked on a
|
||||
* different {@link Thread} than the
|
||||
* {@link DelegatingSecurityContextCallable} was created on.
|
||||
* @since 4.0.2
|
||||
*/
|
||||
public void setEnableOnOriginalThread(boolean enableOnOriginalThread) {
|
||||
this.enableOnOriginalThread = enableOnOriginalThread;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if(!enableOnOriginalThread && originalThread == Thread.currentThread()) {
|
||||
delegate.run();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
delegate.run();
|
||||
@@ -61,6 +95,10 @@ public final class DelegatingSecurityContextRunnable implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for creating a {@link DelegatingSecurityContextRunnable}.
|
||||
*
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.context;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used for delegating to a number of SmartApplicationListener instances. This is useful when needing to register an
|
||||
* SmartApplicationListener with the ApplicationContext programmatically.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public final class DelegatingApplicationListener implements ApplicationListener<ApplicationEvent> {
|
||||
private List<SmartApplicationListener> listeners = new ArrayList<SmartApplicationListener>();
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if(event == null) {
|
||||
return;
|
||||
}
|
||||
for(SmartApplicationListener listener : listeners) {
|
||||
Object source = event.getSource();
|
||||
if(source != null && listener.supportsEventType(event.getClass()) && listener.supportsSourceType(source.getClass())) {
|
||||
listener.onApplicationEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new SmartApplicationListener to use.
|
||||
*
|
||||
* @param smartApplicationListener the SmartApplicationListener to use. Cannot be null.
|
||||
*/
|
||||
public void addListener(SmartApplicationListener smartApplicationListener) {
|
||||
Assert.notNull(smartApplicationListener, "smartApplicationListener cannot be null");
|
||||
listeners.add(smartApplicationListener);
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ public class SpringSecurityCoreVersion {
|
||||
* N.B. Classes are not intended to be serializable between different versions.
|
||||
* See SEC-1709 for why we still need a serial version.
|
||||
*/
|
||||
public static final long SERIAL_VERSION_UID = 400L;
|
||||
public static final long SERIAL_VERSION_UID = 320L;
|
||||
|
||||
static final String MIN_SPRING_VERSION = "4.1.0.RC2";
|
||||
static final String MIN_SPRING_VERSION = "3.2.13.RELEASE";
|
||||
|
||||
static {
|
||||
performVersionChecks();
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Zugriff verweigert
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Ung\u00FCltige Benutzerberechtigungen
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Ung\u00FCltige Anmeldedaten
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Im SecurityContext wurde keine Authentifikation gefunden
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Ung\u00FCltige Benutzerberechtigungen
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Benutzerberechtigungen ist abgelaufen
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Ung\u00FCltige Anmeldedaten
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Anmeldedaten ist abgelaufen
|
||||
AbstractUserDetailsAuthenticationProvider.disabled=Der Benutzer ist deaktiviert
|
||||
AbstractUserDetailsAuthenticationProvider.expired=Die G\u00FCltigkeit des Benutzerkontos ist abgelaufen
|
||||
AbstractUserDetailsAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt
|
||||
AbstractUserDetailsAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterst\u00FCtzt
|
||||
AccountStatusUserDetailsChecker.credentialsExpired=Die G\u00FCltigkeit der Benutzerberechtigungen ist abgelaufen
|
||||
AccountStatusUserDetailsChecker.credentialsExpired=Die G\u00FCltigkeit der Anmeldedaten ist abgelaufen
|
||||
AccountStatusUserDetailsChecker.disabled=Der Benutzer ist deaktiviert
|
||||
AccountStatusUserDetailsChecker.expired=Die G\u00FCltigkeit des Benutzerkontos ist abgelaufen
|
||||
AccountStatusUserDetailsChecker.locked=Das Benutzerkonto ist gesperrt
|
||||
AclEntryAfterInvocationProvider.noPermission=Authentifikation {0} hat KEINE Berechtigungen bez\u00FCglich des Dom\u00E4nen-Objekts {1}
|
||||
AnonymousAuthenticationProvider.incorrectKey=Das angegebene AnonymousAuthenticationToken enth\u00E4lt nicht den erwarteten Schl\u00FCssel
|
||||
BindAuthenticator.badCredentials=Ung\u00FCltige Benutzerberechtigungen
|
||||
BindAuthenticator.emptyPassword=Ung\u00FCltige Benutzerberechtigungen
|
||||
BindAuthenticator.badCredentials=Ung\u00FCltige Anmeldedaten
|
||||
BindAuthenticator.emptyPassword=Ung\u00FCltige Anmeldedaten
|
||||
CasAuthenticationProvider.incorrectKey=Das angegebene CasAuthenticationToken enth\u00E4lt nicht den erwarteten Schl\u00FCssel
|
||||
CasAuthenticationProvider.noServiceTicket=Es konnte kein CAS Service-Ticket zur Pr\u00FCfung geliefert werden
|
||||
ConcurrentSessionControlStrategy.exceededAllowed=Die maximale Sitzungs-Anzahl von {0} f\u00FCr diesen Nutzer wurde \u00FCberschritten
|
||||
@@ -30,14 +30,14 @@ DigestAuthenticationFilter.nonceNotTwoTokens=Nonce sollte zwei Elemente beinhalt
|
||||
DigestAuthenticationFilter.usernameNotFound=Benutzername {0} wurde nicht gefunden
|
||||
#JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
|
||||
#JdbcDaoImpl.notFound=User {0} not found
|
||||
LdapAuthenticationProvider.badCredentials=Ung\u00FCltige Benutzerberechtigungen
|
||||
LdapAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Benutzerberechtigungen ist abgelaufen
|
||||
LdapAuthenticationProvider.badCredentials=Ung\u00FCltige Anmeldedaten
|
||||
LdapAuthenticationProvider.credentialsExpired=Die G\u00FCltigkeit der Anmeldedaten ist abgelaufen
|
||||
LdapAuthenticationProvider.disabled=Der Benutzer ist deaktiviert
|
||||
LdapAuthenticationProvider.expired=Die G\u00FCltigkeit des Benutzerkontos ist abgelaufen
|
||||
LdapAuthenticationProvider.locked=Das Benutzerkonto ist gesperrt
|
||||
LdapAuthenticationProvider.emptyUsername=Ein leerer Benutzername ist nicht erlaubt
|
||||
LdapAuthenticationProvider.onlySupports=Nur UsernamePasswordAuthenticationToken wird unterst\u00FCtzt
|
||||
PasswordComparisonAuthenticator.badCredentials=Ung\u00FCltige Benutzerberechtigungen
|
||||
PasswordComparisonAuthenticator.badCredentials=Ung\u00FCltige Anmeldedaten
|
||||
#PersistentTokenBasedRememberMeServices.cookieStolen=Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
|
||||
ProviderManager.providerNotFound=F\u00FCr {0} wurde kein AuthenticationProvider gefunden
|
||||
RememberMeAuthenticationProvider.incorrectKey=Das angegebene RememberMeAuthenticationToken enth\u00E4lt nicht den erwarteten Schl\u00FCssel
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Access is denied
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Empty Password
|
||||
AbstractSecurityInterceptor.authenticationNotFound=An Authentication object was not found in the SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Bad credentials
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=User credentials have expired
|
||||
AbstractUserDetailsAuthenticationProvider.disabled=User is disabled
|
||||
AbstractUserDetailsAuthenticationProvider.expired=User account has expired
|
||||
AbstractUserDetailsAuthenticationProvider.locked=User account is locked
|
||||
AbstractUserDetailsAuthenticationProvider.onlySupports=Only UsernamePasswordAuthenticationToken is supported
|
||||
AccountStatusUserDetailsChecker.credentialsExpired=User credentials have expired
|
||||
AccountStatusUserDetailsChecker.disabled=User is disabled
|
||||
AccountStatusUserDetailsChecker.expired=User account has expired
|
||||
AccountStatusUserDetailsChecker.locked=User account is locked
|
||||
AclEntryAfterInvocationProvider.noPermission=Authentication {0} has NO permissions to the domain object {1}
|
||||
AnonymousAuthenticationProvider.incorrectKey=The presented AnonymousAuthenticationToken does not contain the expected key
|
||||
BindAuthenticator.badCredentials=Bad credentials
|
||||
BindAuthenticator.emptyPassword=Empty Password
|
||||
CasAuthenticationProvider.incorrectKey=The presented CasAuthenticationToken does not contain the expected key
|
||||
CasAuthenticationProvider.noServiceTicket=Failed to provide a CAS service ticket to validate
|
||||
ConcurrentSessionControlStrategy.exceededAllowed=Maximum sessions of {0} for this principal exceeded
|
||||
DigestAuthenticationFilter.incorrectRealm=Response realm name {0} does not match system realm name of {1}
|
||||
DigestAuthenticationFilter.incorrectResponse=Incorrect response
|
||||
DigestAuthenticationFilter.missingAuth=Missing mandatory digest value for 'auth' QOP; received header {0}
|
||||
DigestAuthenticationFilter.missingMandatory=Missing mandatory digest value; received header {0}
|
||||
DigestAuthenticationFilter.nonceCompromised=Nonce token compromised {0}
|
||||
DigestAuthenticationFilter.nonceEncoding=Nonce is not encoded in Base64; received nonce {0}
|
||||
DigestAuthenticationFilter.nonceExpired=Nonce has expired/timed out
|
||||
DigestAuthenticationFilter.nonceNotNumeric=Nonce token should have yielded a numeric first token, but was {0}
|
||||
DigestAuthenticationFilter.nonceNotTwoTokens=Nonce should have yielded two tokens but was {0}
|
||||
DigestAuthenticationFilter.usernameNotFound=Username {0} not found
|
||||
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
|
||||
JdbcDaoImpl.notFound=User {0} not found
|
||||
LdapAuthenticationProvider.badCredentials=Bad credentials
|
||||
LdapAuthenticationProvider.credentialsExpired=User credentials have expired
|
||||
LdapAuthenticationProvider.disabled=User is disabled
|
||||
LdapAuthenticationProvider.expired=User account has expired
|
||||
LdapAuthenticationProvider.locked=User account is locked
|
||||
LdapAuthenticationProvider.emptyUsername=Empty username not allowed
|
||||
LdapAuthenticationProvider.onlySupports=Only UsernamePasswordAuthenticationToken is supported
|
||||
PasswordComparisonAuthenticator.badCredentials=Bad credentials
|
||||
PersistentTokenBasedRememberMeServices.cookieStolen=Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
|
||||
ProviderManager.providerNotFound=No AuthenticationProvider found for {0}
|
||||
RememberMeAuthenticationProvider.incorrectKey=The presented RememberMeAuthenticationToken does not contain the expected key
|
||||
RunAsImplAuthenticationProvider.incorrectKey=The presented RunAsUserToken does not contain the expected key
|
||||
SubjectDnX509PrincipalExtractor.noMatching=No matching pattern was found in subjectDN: {0}
|
||||
SwitchUserFilter.noCurrentUser=No current user associated with this request
|
||||
SwitchUserFilter.noOriginalAuthentication=Could not find original Authentication object
|
||||
@@ -1,47 +1,47 @@
|
||||
AbstractAccessDecisionManager.accessDenied = \uc811\uadfc\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
AbstractLdapAuthenticationProvider.emptyPassword = \ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
AbstractSecurityInterceptor.authenticationNotFound = SecurityContext\uc5d0\uc11c Authentication \uac1d\uccb4\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials = \uc790\uaca9 \uc99d\uba85\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired = \uc790\uaca9 \uc99d\uba85 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
AbstractUserDetailsAuthenticationProvider.disabled = \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc0ac\uc6a9\uc790\uc785\ub2c8\ub2e4.
|
||||
AbstractUserDetailsAuthenticationProvider.expired = \uc0ac\uc6a9\uc790 \uacc4\uc815\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc \ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
AbstractUserDetailsAuthenticationProvider.locked = \uc0ac\uc6a9\uc790 \uacc4\uc815\uc774 \uc7a0\uaca8 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
AbstractUserDetailsAuthenticationProvider.onlySupports = UsernamePasswordAuthenticationToken\ub9cc \uc9c0\uc6d0\ud569\ub2c8\ub2e4.
|
||||
AccountStatusUserDetailsChecker.credentialsExpired = \uc790\uaca9 \uc99d\uba85 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
AccountStatusUserDetailsChecker.disabled = \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc0ac\uc6a9\uc790\uc785\ub2c8\ub2e4.
|
||||
AccountStatusUserDetailsChecker.expired = \uc0ac\uc6a9\uc790 \uacc4\uc815\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc \ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
AccountStatusUserDetailsChecker.locked = \uc0ac\uc6a9\uc790 \uacc4\uc815\uc774 \uc7a0\uaca8 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
AclEntryAfterInvocationProvider.noPermission = domain object {1}\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 Authentication {0}\uc5d0 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
AnonymousAuthenticationProvider.incorrectKey = \uc81c\uacf5\ub41c AnonymousAuthenticationToken\uc5d0\ub294 \ud544\uc694\ub85c\ud558\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
BindAuthenticator.badCredentials = \uc790\uaca9 \uc99d\uba85\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
BindAuthenticator.emptyPassword = \ube44\ubc00\ubc88\ud638 \ud56d\ubaa9\uc774 \ube44\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
CasAuthenticationProvider.incorrectKey = \uc81c\uacf5\ub41c CasAuthenticationToken\uc5d0\ub294 \ud544\uc694\ub85c \ud558\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
CasAuthenticationProvider.noServiceTicket = \uac80\uc99d\uc744 \uc704\ud55c CAS \uc11c\ube44\uc2a4 \ud2f0\ucf13\uc744 \uc81c\uacf5\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
ConcurrentSessionControlStrategy.exceededAllowed = \ucd5c\ub300 \uc138\uc158 \ud5c8\uc6a9 \uc218 {0}\uac1c\ub97c \ucd08\uacfc\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.incorrectRealm = \uc751\ub2f5 realm \uc774\ub984 {0}\uacfc \uc2dc\uc2a4\ud15c realm \uc774\ub984 {1}\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.incorrectResponse = \uc751\ub2f5\uc774 \uc815\ud655\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.missingAuth = 'auth' QOP(quality of protection)\ub97c \uc704\ud55c digest \uac12\uc740 \ud544\uc218 \ud56d\ubaa9\uc785\ub2c8\ub2e4. \ud604\uc7ac header \uac12\uc740 {0}\uc785\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.missingMandatory = digest \uac12\uc740 \ud544\uc218 \ud56d\ubaa9\uc785\ub2c8\ub2e4. \ud604\uc7ac header \uac12\uc740 {0}\uc785\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.nonceCompromised = Nonce \ud1a0\ud070\uc774 \uc190\uc0c1\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud604\uc7ac nonce \uac12\uc740 {0}\uc785\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.nonceEncoding = Nonce \uac12\uc774 Base64\ub85c \uc778\ucf54\ub529 \ub418\uc5b4\uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \ud604\uc7ac nonce \uac12\uc740 {0}\uc785\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.nonceExpired = Nonce\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uac70\ub098 \uc2dc\uac04\uc774 \ucd08\uacfc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.nonceNotNumeric = Nonce \ud1a0\ud070\uc758 \uccab \uae00\uc790\ub294 \uc22b\uc790\ub85c \uc2dc\uc791\ud574\uc57c \ud569\ub2c8\ub2e4. \ud604\uc7ac nonce \uac12\uc740 {0}\uc785\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.nonceNotTwoTokens = Nonce\ub294 \ub450 \uac1c\uc758 \ud1a0\ud070\uc744 \ub9cc\ub4e4\uc5b4\uc57c \ud569\ub2c8\ub2e4. \ud604\uc7ac nonce \uac12\uc740 {0}\uc785\ub2c8\ub2e4.
|
||||
DigestAuthenticationFilter.usernameNotFound = {0} ID\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
JdbcDaoImpl.noAuthority = {0} \uc0ac\uc6a9\uc790\ub294 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
JdbcDaoImpl.notFound = {0} \uc0ac\uc6a9\uc790\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.badCredentials = \uc790\uaca9 \uc99d\uba85\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.credentialsExpired = \uc790\uaca9 \uc99d\uba85 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.disabled = \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc0ac\uc6a9\uc790\uc785\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.expired = \uc0ac\uc6a9\uc790 \uacc4\uc815\uc758 \uc720\ud6a8 \uae30\uac04\uc774 \ub9cc\ub8cc \ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.locked = \uc0ac\uc6a9\uc790 \uacc4\uc815\uc774 \uc7a0\uaca8 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.emptyUsername = ID\uc5d0 \uacf5\ubc31\uc740 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
LdapAuthenticationProvider.onlySupports = UsernamePasswordAuthenticationToken\ub9cc \uc9c0\uc6d0\ud569\ub2c8\ub2e4.
|
||||
PasswordComparisonAuthenticator.badCredentials = \uc790\uaca9 \uc99d\uba85\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
PersistentTokenBasedRememberMeServices.cookieStolen = \ub85c\uadf8\uc778 \uc0c1\ud0dc \uc720\uc9c0\ub97c \uc704\ud55c \ud1a0\ud070\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc774\uc804\uc5d0 \uc0ac\uc6a9\ud55c \ud1a0\ud070\uc774 \ud0c0\uc778\uc73c\ub85c\ubd80\ud130 \ud0c8\ucde8 \ub2f9\ud588\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
ProviderManager.providerNotFound = {0}\uc744 \uc704\ud55c AuthenticationProvider\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
RememberMeAuthenticationProvider.incorrectKey = \uc81c\uacf5\ub41c RememberMeAuthenticationToken\uc5d0\ub294 \ud544\uc694\ub85c \ud558\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
RunAsImplAuthenticationProvider.incorrectKey = \uc81c\uacf5\ub41c RunAsUserToken\uc5d0\ub294 \ud544\uc694\ub85c \ud558\ub294 key\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
SubjectDnX509PrincipalExtractor.noMatching = subjectDN\: {0} \ub0b4\uc5d0 \ub9e4\uce6d\ub418\ub294 \ud328\ud134\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
SwitchUserFilter.noCurrentUser = \uc694\uccad\ud55c \uc0ac\uc6a9\uc790\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
SwitchUserFilter.noOriginalAuthentication = Authentication \uac1d\uccb4\uc758 \uc6d0\ubcf8\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
AbstractAccessDecisionManager.accessDenied=\uC811\uADFC\uC774 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
AbstractLdapAuthenticationProvider.badCredentials=\uBE44\uBC00\uBC88\uD638\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
AbstractSecurityInterceptor.authenticationNotFound=SecurityContext\uC5D0\uC11C Authentication \uAC1D\uCCB4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=\uBE44\uBC00\uBC88\uD638(credential)\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\uBE44\uBC00\uBC88\uD638(credential)\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
AbstractUserDetailsAuthenticationProvider.disabled=\uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uC0AC\uC6A9\uC790 \uC785\uB2C8\uB2E4.
|
||||
AbstractUserDetailsAuthenticationProvider.expired=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC \uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
AbstractUserDetailsAuthenticationProvider.locked=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC774 \uC7A0\uACA8 \uC788\uC2B5\uB2C8\uB2E4.
|
||||
AbstractUserDetailsAuthenticationProvider.onlySupports=UsernamePasswordAuthenticationToken\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4.
|
||||
AccountStatusUserDetailsChecker.credentialsExpired=\uBE44\uBC00\uBC88\uD638\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
AccountStatusUserDetailsChecker.disabled=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
AccountStatusUserDetailsChecker.expired=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC \uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
AccountStatusUserDetailsChecker.locked=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC774 \uC7A0\uACA8 \uC788\uC2B5\uB2C8\uB2E4.
|
||||
AclEntryAfterInvocationProvider.noPermission=Authentication {0}\uC740/\uB294 domain object {1}\uC5D0 \uB300\uD55C \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
AnonymousAuthenticationProvider.incorrectKey=\uC81C\uACF5\uB41C AnonymousAuthenticationToken\uC5D0\uB294 \uCC3E\uB294 key\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
BindAuthenticator.badCredentials=\uBE44\uBC00\uBC88\uD638\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
BindAuthenticator.emptyPassword=\uBE44\uBC00\uBC88\uD638(credential)\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
CasAuthenticationProvider.incorrectKey=\uC81C\uACF5\uB41C CasAuthenticationToken\uC5D0\uB294 \uCC3E\uB294 key\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
CasAuthenticationProvider.noServiceTicket=\uAC80\uC99D\uC744 \uC704\uD55C CAS \uC11C\uBE44\uC2A4 \uD2F0\uCF13\uC744 \uC81C\uACF5\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
ConcurrentSessionControlStrategy.exceededAllowed={0}\uC758 \uCD5C\uB300 \uC138\uC158 \uD5C8\uC6A9 \uC218\uB97C \uCD08\uACFC\uD558\uC600\uC2B5\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.incorrectRealm=\uC751\uB2F5 realm \uC774\uB984 {0}\uC774 \uC2DC\uC2A4\uD15C realm \uC774\uB984 {1}\uACFC \uC77C\uCE58 \uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.incorrectResponse=\uC751\uB2F5\uC774 \uC815\uD655\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.missingAuth='auth' QOP\uB97C \uC704\uD55C \uD544\uC218 digest \uD30C\uB77C\uBBF8\uD130 \uAC12\uC774 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uD604\uC7AC header\uB294 {0}\uC785\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.missingMandatory=\uD544\uC218 digest \uD30C\uB77C\uBBF8\uD130 \uAC12\uC774 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uD604\uC7AC header\uB294 {0}\uC785\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.nonceCompromised=Nonce \uD1A0\uD070\uC774 \uD6FC\uC190\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uD604\uC7AC nonce\uB294 {0}\uC785\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.nonceEncoding=Nonce\uAC00 Base64\uB85C \uC778\uCF54\uB529 \uB418\uC5B4\uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uD604\uC7AC nonce\uB294 {0}\uC785\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.nonceExpired=Nonce\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.nonceNotNumeric=Nonce \uD1A0\uD070\uC758 \uCCAB \uAE00\uC790\uB294 \uC22B\uC790\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4. \uD604\uC7AC nonce\uB294 {0}\uC785\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.nonceNotTwoTokens=Nonce\uB294 2\uAC1C\uC758 \uD1A0\uD070\uC744 \uB9CC\uB4E4\uC5B4\uC57C \uD569\uB2C8\uB2E4. \uD604\uC7AC nonce\uB294 {0}\uC785\uB2C8\uB2E4.
|
||||
DigestAuthenticationFilter.usernameNotFound=\uC0AC\uC6A9\uC790 {0}\uC744/\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
JdbcDaoImpl.noAuthority=\uC0AC\uC6A9\uC790 {0}\uC740/\uB294 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
JdbcDaoImpl.notFound=\uC0AC\uC6A9\uC790 {0}\uC744/\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.badCredentials=\uBE44\uBC00\uBC88\uD638\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.credentialsExpired=\uBE44\uBC00\uBC88\uD638(credential)\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.disabled=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.expired=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC758 \uC720\uD6A8 \uAE30\uAC04\uC774 \uB9CC\uB8CC \uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.locked=\uC0AC\uC6A9\uC790 \uACC4\uC815\uC774 \uC7A0\uACA8 \uC788\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.emptyUsername=\uC0AC\uC6A9\uC790\uBA85(username)\uC5D0 \uACF5\uBC31\uC740 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
LdapAuthenticationProvider.onlySupports=UsernamePasswordAuthenticationToken\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4.
|
||||
PasswordComparisonAuthenticator.badCredentials=\uBE44\uBC00\uBC88\uD638\uAC00 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
#PersistentTokenBasedRememberMeServices.cookieStolen=Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
|
||||
ProviderManager.providerNotFound={0}\uC744 \uC704\uD55C AuthenticationProvider\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
RememberMeAuthenticationProvider.incorrectKey=\uC81C\uACF5\uB41C RememberMeAuthenticationToken\uC5D0\uB294 \uCC3E\uB294 key\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
RunAsImplAuthenticationProvider.incorrectKey=\uC81C\uACF5\uB41C RunAsUserToken\uC5D0\uB294 \uCC3E\uB294 key\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
SubjectDnX509PrincipalExtractor.noMatching=subjectDN\: {0}\uC5D0\uC11C \uB9E4\uCE6D\uB418\uB294 \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
SwitchUserFilter.noCurrentUser=\uC0AC\uC6A9\uC790\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
||||
SwitchUserFilter.noOriginalAuthentication=Authentication\uC758 \uC6D0\uBCF8\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
||||
|
||||
+124
-3
@@ -1,5 +1,21 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.access.annotation;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -7,10 +23,10 @@ import java.util.Collection;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.intercept.method.MockMethodInvocation;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
@@ -58,7 +74,87 @@ public class Jsr250MethodDefinitionSourceTests {
|
||||
assertEquals("ADMIN", accessAttributes.toArray()[0].toString());
|
||||
}
|
||||
|
||||
//~ Inner Classes ======================================================================================================
|
||||
// JSR-250 Spec Tests
|
||||
|
||||
/**
|
||||
* Class-level annotations only affect the class they annotate and their members, that
|
||||
* is, its methods and fields. They never affect a member declared by a superclass,
|
||||
* even if it is not hidden or overridden by the class in question.
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembers() throws Exception {
|
||||
Child target = new Child();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "notOverriden");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertThat(accessAttributes).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembersOverriden() throws Exception {
|
||||
Child target = new Child();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "overriden");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertEquals(1, accessAttributes.size());
|
||||
assertEquals("DERIVED", accessAttributes.toArray()[0].toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classLevelAnnotationsImpactMemberLevel() throws Exception {
|
||||
Child target = new Child();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "defaults");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertEquals(1, accessAttributes.size());
|
||||
assertEquals("DERIVED", accessAttributes.toArray()[0].toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classLevelAnnotationsIgnoredByExplicitMemberAnnotation() throws Exception {
|
||||
Child target = new Child();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "explicitMethod");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertEquals(1, accessAttributes.size());
|
||||
assertEquals("EXPLICIT", accessAttributes.toArray()[0].toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* The interfaces implemented by a class never contribute annotations to the class
|
||||
* itself or any of its members.
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void interfacesNeverContributeAnnotationsMethodLevel() throws Exception {
|
||||
Parent target = new Parent();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "interfaceMethod");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertThat(accessAttributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interfacesNeverContributeAnnotationsClassLevel() throws Exception {
|
||||
Parent target = new Parent();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "notOverriden");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertThat(accessAttributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationsOnOverriddenMemberIgnored() throws Exception {
|
||||
Child target = new Child();
|
||||
MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "overridenIgnored");
|
||||
|
||||
Collection<ConfigAttribute> accessAttributes = mds.getAttributes(mi);
|
||||
assertEquals(1, accessAttributes.size());
|
||||
assertEquals("DERIVED", accessAttributes.toArray()[0].toString());
|
||||
}
|
||||
|
||||
//~ Inner Classes ======================================================================================================
|
||||
|
||||
public static class A {
|
||||
|
||||
@@ -78,4 +174,29 @@ public class Jsr250MethodDefinitionSourceTests {
|
||||
@RolesAllowed("ADMIN")
|
||||
public void adminMethod() {}
|
||||
}
|
||||
|
||||
// JSR-250 Spec
|
||||
|
||||
@RolesAllowed("IPARENT")
|
||||
interface IParent {
|
||||
@RolesAllowed("INTERFACEMETHOD")
|
||||
void interfaceMethod();
|
||||
}
|
||||
|
||||
static class Parent implements IParent {
|
||||
public void interfaceMethod() {}
|
||||
public void notOverriden() {}
|
||||
public void overriden() {}
|
||||
@RolesAllowed("OVERRIDENIGNORED")
|
||||
public void overridenIgnored() {}
|
||||
}
|
||||
|
||||
@RolesAllowed("DERIVED")
|
||||
class Child extends Parent {
|
||||
public void overriden() {}
|
||||
public void overridenIgnored() {}
|
||||
public void defaults() {}
|
||||
@RolesAllowed("EXPLICIT")
|
||||
public void explicitMethod() {}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-8
@@ -14,13 +14,11 @@
|
||||
*/
|
||||
package org.springframework.security.access.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.*;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.intercept.method.MockMethodInvocation;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
@@ -28,7 +26,17 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.access.annotation.sec2150.MethodInvocationFactory;
|
||||
import org.springframework.security.access.intercept.method.MockMethodInvocation;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
|
||||
/**
|
||||
@@ -178,6 +186,14 @@ public class SecuredAnnotationSecurityMetadataSourceTests {
|
||||
assertEquals("CUSTOM", attrs[0].getAttribute());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyFactoryInterfaceAttributesFound() throws Exception {
|
||||
MockMethodInvocation mi = MethodInvocationFactory.createSec2150MethodInvocation();
|
||||
Collection<ConfigAttribute> attributes = mds.getAttributes(mi);
|
||||
assertThat(attributes.size()).isEqualTo(1);
|
||||
assertThat(attributes).onProperty("attribute").containsOnly("ROLE_PERSON");
|
||||
}
|
||||
|
||||
// Inner classes
|
||||
class Department extends Entity {
|
||||
public Department(String name) {
|
||||
@@ -190,6 +206,7 @@ public class SecuredAnnotationSecurityMetadataSourceTests {
|
||||
Department someUserMethod3(Department dept);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class DepartmentServiceImpl extends BusinessServiceImpl<Department> implements DepartmentService {
|
||||
@Secured({"ROLE_ADMIN"})
|
||||
public Department someUserMethod3(final Department dept) {
|
||||
|
||||
+4
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,19 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.pages;
|
||||
package org.springframework.security.access.annotation.sec2150;
|
||||
|
||||
import geb.*
|
||||
public interface CrudRepository {
|
||||
|
||||
/**
|
||||
* The home page
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class HomePage extends Page {
|
||||
static url = ''
|
||||
static at = { assert driver.title == 'Hello World'; true}
|
||||
static content = {
|
||||
message { $('p').text() }
|
||||
}
|
||||
Iterable<Object> findAll();
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.access.annotation.sec2150;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.security.access.intercept.method.MockMethodInvocation;
|
||||
|
||||
public class MethodInvocationFactory {
|
||||
|
||||
/**
|
||||
* In order to reproduce the bug for SEC-2150, we must have a proxy object
|
||||
* that implements TargetSourceAware and implements our annotated interface.
|
||||
*
|
||||
* @return
|
||||
* @throws NoSuchMethodException
|
||||
*/
|
||||
public static MockMethodInvocation createSec2150MethodInvocation() throws NoSuchMethodException {
|
||||
ProxyFactory factory = new ProxyFactory(new Class[] {PersonRepository.class});
|
||||
factory.setTargetClass(CrudRepository.class);
|
||||
PersonRepository repository = (PersonRepository) factory.getProxy();
|
||||
return new MockMethodInvocation(repository, PersonRepository.class , "findAll");
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,20 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.pages;
|
||||
package org.springframework.security.access.annotation.sec2150;
|
||||
|
||||
import geb.*
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
/**
|
||||
* The home page
|
||||
* Note that JSR-256 states that annotations have no impact when placed on
|
||||
* interfaces, so SEC-2150 is not impacted by JSR-256 support.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
class HomePage extends Page {
|
||||
static url = ''
|
||||
static at = { assert driver.title == 'Hello Security'; true}
|
||||
static content = {
|
||||
message { $('p').text() }
|
||||
logout { $('input', type: 'submit').click() }
|
||||
}
|
||||
}
|
||||
@Secured("ROLE_PERSON")
|
||||
@PreAuthorize("hasRole('ROLE_PERSON')")
|
||||
public interface PersonRepository extends CrudRepository {}
|
||||
+18
-1
@@ -1,23 +1,31 @@
|
||||
package org.springframework.security.access.expression.method;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.annotation.sec2150.MethodInvocationFactory;
|
||||
import org.springframework.security.access.intercept.method.MockMethodInvocation;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -148,6 +156,15 @@ public class PrePostAnnotationSecurityMetadataSourceTests {
|
||||
assertEquals(1, attrs.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyFactoryInterfaceAttributesFound() throws Exception {
|
||||
MockMethodInvocation mi = MethodInvocationFactory.createSec2150MethodInvocation();
|
||||
Collection<ConfigAttribute> attributes = mds.getAttributes(mi);
|
||||
assertThat(attributes.size()).isEqualTo(1);
|
||||
Expression expression = (Expression) ReflectionTestUtils.getField(attributes.iterator().next(),"authorizeExpression");
|
||||
assertThat(expression.getExpressionString()).isEqualTo("hasRole('ROLE_PERSON')");
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
public static interface ReturnVoid {
|
||||
|
||||
+3
@@ -15,6 +15,7 @@
|
||||
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -58,6 +59,8 @@ public class UsernamePasswordAuthenticationTokenTests {
|
||||
token.setAuthenticated(true);
|
||||
fail("Should have prohibited setAuthenticated(true)");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// SEC-2540
|
||||
assertThat(expected).hasMessage("Once created you cannot set this token to authenticated. Create a new instance using the constructor which takes a GrantedAuthority list will mark this as authenticated.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-10
@@ -15,8 +15,6 @@
|
||||
|
||||
package org.springframework.security.authentication.dao.salt;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
import org.springframework.security.authentication.dao.SystemWideSaltSource;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
@@ -71,12 +69,4 @@ public class SystemWideSaltSourceTests extends TestCase {
|
||||
saltSource.afterPropertiesSet();
|
||||
assertEquals("helloWorld", saltSource.getSalt(null));
|
||||
}
|
||||
|
||||
// SEC-2173
|
||||
public void testToString() {
|
||||
String systemWideSalt = "helloWorld";
|
||||
SystemWideSaltSource saltSource = new SystemWideSaltSource();
|
||||
saltSource.setSystemWideSalt(systemWideSalt);
|
||||
assertThat(saltSource.toString()).isEqualTo(systemWideSalt);
|
||||
}
|
||||
}
|
||||
|
||||
+50
-9
@@ -17,6 +17,9 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -45,6 +48,8 @@ public class DelegatingSecurityContextCallableTests {
|
||||
|
||||
private Callable<Object> callable;
|
||||
|
||||
private ExecutorService executor;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("serial")
|
||||
public void setUp() throws Exception {
|
||||
@@ -55,6 +60,7 @@ public class DelegatingSecurityContextCallableTests {
|
||||
return super.answer(invocation);
|
||||
}
|
||||
});
|
||||
executor = Executors.newFixedThreadPool(1);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -88,15 +94,34 @@ public class DelegatingSecurityContextCallableTests {
|
||||
|
||||
@Test
|
||||
public void call() throws Exception {
|
||||
callable = new DelegatingSecurityContextCallable<Object>(delegate, securityContext);
|
||||
assertWrapped(callable.call());
|
||||
callable = new DelegatingSecurityContextCallable<Object>(delegate,
|
||||
securityContext);
|
||||
assertWrapped(callable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callDefaultSecurityContext() throws Exception {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
callable = new DelegatingSecurityContextCallable<Object>(delegate);
|
||||
SecurityContextHolder.clearContext(); // ensure callable is what sets up the SecurityContextHolder
|
||||
SecurityContextHolder.clearContext(); // ensure callable is what sets up the
|
||||
// SecurityContextHolder
|
||||
assertWrapped(callable);
|
||||
}
|
||||
|
||||
// SEC-3031
|
||||
@Test
|
||||
public void callOnSameThread() throws Exception {
|
||||
callable = new DelegatingSecurityContextCallable<Object>(delegate,
|
||||
securityContext);
|
||||
securityContext = SecurityContextHolder.createEmptyContext();
|
||||
assertWrapped(callable.call());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callOnSameThreadExplicitlyEnabled() throws Exception {
|
||||
DelegatingSecurityContextCallable<Object> callable = new DelegatingSecurityContextCallable<Object>(delegate,
|
||||
securityContext);
|
||||
callable.setEnableOnOriginalThread(true);
|
||||
assertWrapped(callable.call());
|
||||
}
|
||||
|
||||
@@ -116,19 +141,35 @@ public class DelegatingSecurityContextCallableTests {
|
||||
public void createNullSecurityContext() throws Exception {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
callable = DelegatingSecurityContextCallable.create(delegate, null);
|
||||
SecurityContextHolder.clearContext(); // ensure callable is what sets up the SecurityContextHolder
|
||||
assertWrapped(callable.call());
|
||||
SecurityContextHolder.clearContext(); // ensure callable is what sets up the
|
||||
// SecurityContextHolder
|
||||
assertWrapped(callable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws Exception {
|
||||
callable = DelegatingSecurityContextCallable.create(delegate, securityContext);
|
||||
assertWrapped(callable.call());
|
||||
assertWrapped(callable);
|
||||
}
|
||||
|
||||
private void assertWrapped(Object actualResult) throws Exception {
|
||||
assertThat(actualResult).isEqualTo(callableResult);
|
||||
// --- toString
|
||||
|
||||
// SEC-2682
|
||||
@Test
|
||||
public void toStringDelegates() {
|
||||
callable = new DelegatingSecurityContextCallable<Object>(delegate,
|
||||
securityContext);
|
||||
assertThat(callable.toString()).isEqualTo(delegate.toString());
|
||||
}
|
||||
|
||||
private void assertWrapped(Callable<Object> callable) throws Exception {
|
||||
Future<Object> submit = executor.submit(callable);
|
||||
assertWrapped(submit.get());
|
||||
}
|
||||
|
||||
private void assertWrapped(Object callableResult) throws Exception {
|
||||
verify(delegate).call();
|
||||
assertThat(SecurityContextHolder.getContext()).isEqualTo(SecurityContextHolder.createEmptyContext());
|
||||
assertThat(SecurityContextHolder.getContext()).isEqualTo(
|
||||
SecurityContextHolder.createEmptyContext());
|
||||
}
|
||||
}
|
||||
+58
-16
@@ -16,6 +16,10 @@ import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -24,6 +28,8 @@ import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.support.ExecutorServiceAdapter;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
@@ -43,6 +49,8 @@ public class DelegatingSecurityContextRunnableTests {
|
||||
|
||||
private Runnable runnable;
|
||||
|
||||
private ExecutorService executor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
doAnswer(new Answer<Object>() {
|
||||
@@ -50,8 +58,9 @@ public class DelegatingSecurityContextRunnableTests {
|
||||
assertThat(SecurityContextHolder.getContext()).isEqualTo(securityContext);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.when(delegate).run();
|
||||
}).when(delegate).run();
|
||||
|
||||
executor = Executors.newFixedThreadPool(1);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -86,17 +95,35 @@ public class DelegatingSecurityContextRunnableTests {
|
||||
@Test
|
||||
public void call() throws Exception {
|
||||
runnable = new DelegatingSecurityContextRunnable(delegate, securityContext);
|
||||
runnable.run();
|
||||
assertWrapped();
|
||||
assertWrapped(runnable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callDefaultSecurityContext() throws Exception {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
runnable = new DelegatingSecurityContextRunnable(delegate);
|
||||
SecurityContextHolder.clearContext(); // ensure runnable is what sets up the SecurityContextHolder
|
||||
runnable.run();
|
||||
assertWrapped();
|
||||
SecurityContextHolder.clearContext(); // ensure runnable is what sets up the
|
||||
// SecurityContextHolder
|
||||
assertWrapped(runnable);
|
||||
}
|
||||
|
||||
// SEC-3031
|
||||
@Test
|
||||
public void callOnSameThread() throws Exception {
|
||||
executor = synchronousExecutor();
|
||||
runnable = new DelegatingSecurityContextRunnable(delegate,
|
||||
securityContext);
|
||||
securityContext = SecurityContextHolder.createEmptyContext();
|
||||
assertWrapped(runnable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callOnSameThreadExplicitlyEnabled() throws Exception {
|
||||
executor = synchronousExecutor();
|
||||
DelegatingSecurityContextRunnable runnable = new DelegatingSecurityContextRunnable(delegate,
|
||||
securityContext);
|
||||
runnable.setEnableOnOriginalThread(true);
|
||||
assertWrapped(runnable);
|
||||
}
|
||||
|
||||
// --- create ---
|
||||
@@ -112,23 +139,38 @@ public class DelegatingSecurityContextRunnableTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNullSecurityContext() {
|
||||
public void createNullSecurityContext() throws Exception {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
runnable = DelegatingSecurityContextRunnable.create(delegate, null);
|
||||
SecurityContextHolder.clearContext(); // ensure runnable is what sets up the SecurityContextHolder
|
||||
runnable.run();
|
||||
assertWrapped();
|
||||
SecurityContextHolder.clearContext(); // ensure runnable is what sets up the
|
||||
// SecurityContextHolder
|
||||
assertWrapped(runnable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() {
|
||||
public void create() throws Exception {
|
||||
runnable = DelegatingSecurityContextRunnable.create(delegate, securityContext);
|
||||
runnable.run();
|
||||
assertWrapped();
|
||||
assertWrapped(runnable);
|
||||
}
|
||||
|
||||
private void assertWrapped() {
|
||||
// --- toString
|
||||
|
||||
// SEC-2682
|
||||
@Test
|
||||
public void toStringDelegates() {
|
||||
runnable = new DelegatingSecurityContextRunnable(delegate, securityContext);
|
||||
assertThat(runnable.toString()).isEqualTo(delegate.toString());
|
||||
}
|
||||
|
||||
private void assertWrapped(Runnable runnable) throws Exception {
|
||||
Future<?> submit = executor.submit(runnable);
|
||||
submit.get();
|
||||
verify(delegate).run();
|
||||
assertThat(SecurityContextHolder.getContext()).isEqualTo(SecurityContextHolder.createEmptyContext());
|
||||
assertThat(SecurityContextHolder.getContext()).isEqualTo(
|
||||
SecurityContextHolder.createEmptyContext());
|
||||
}
|
||||
|
||||
private static ExecutorService synchronousExecutor() {
|
||||
return new ExecutorServiceAdapter(new SyncTaskExecutor());
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package org.springframework.security.context;
|
||||
|
||||
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.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
import org.springframework.security.core.session.SessionDestroyedEvent;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DelegatingApplicationListenerTests {
|
||||
@Mock
|
||||
SmartApplicationListener delegate;
|
||||
|
||||
ApplicationEvent event;
|
||||
|
||||
DelegatingApplicationListener listener;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
event = new ApplicationEvent(this) {};
|
||||
listener = new DelegatingApplicationListener();
|
||||
listener.addListener(delegate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEventNull() {
|
||||
listener.onApplicationEvent(null);
|
||||
|
||||
verify(delegate,never()).onApplicationEvent(any(ApplicationEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEventSuccess() {
|
||||
when(delegate.supportsEventType(event.getClass())).thenReturn(true);
|
||||
when(delegate.supportsSourceType(event.getSource().getClass())).thenReturn(true);
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
verify(delegate).onApplicationEvent(event);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEventEventTypeNotSupported() {
|
||||
when(delegate.supportsSourceType(event.getSource().getClass())).thenReturn(true);
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
verify(delegate,never()).onApplicationEvent(any(ApplicationEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEventSourceTypeNotSupported() {
|
||||
when(delegate.supportsEventType(event.getClass())).thenReturn(true);
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
verify(delegate,never()).onApplicationEvent(any(ApplicationEvent.class));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void addNull() {
|
||||
listener.addListener(null);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -121,7 +121,7 @@ public class SpringSecurityCoreVersionTests {
|
||||
public void noWarnIfSpringVersionLarger() throws Exception {
|
||||
spy(SpringSecurityCoreVersion.class);
|
||||
spy(SpringVersion.class);
|
||||
when(SpringSecurityCoreVersion.getVersion()).thenReturn("4.0.0.RELEASE");
|
||||
when(SpringSecurityCoreVersion.getVersion()).thenReturn("3.2.0.RELEASE");
|
||||
when(SpringVersion.getVersion()).thenReturn("4.0.0.RELEASE");
|
||||
|
||||
performChecks();
|
||||
|
||||
+24
-5
@@ -23,16 +23,18 @@ import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link org.springframework.security.core.SpringSecurityMessageSource}.
|
||||
*/
|
||||
public class SpringSecurityMessageSourceTests extends TestCase {
|
||||
//~ Methods ========================================================================================================
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public void testOperation() {
|
||||
SpringSecurityMessageSource msgs = new SpringSecurityMessageSource();
|
||||
assertEquals("\u4E0D\u5141\u8BB8\u8BBF\u95EE", msgs.getMessage("AbstractAccessDecisionManager.accessDenied", null, Locale.SIMPLIFIED_CHINESE));
|
||||
assertEquals("\u4E0D\u5141\u8BB8\u8BBF\u95EE", msgs.getMessage(
|
||||
"AbstractAccessDecisionManager.accessDenied", null,
|
||||
Locale.SIMPLIFIED_CHINESE));
|
||||
}
|
||||
|
||||
public void testReplacableLookup() {
|
||||
@@ -42,11 +44,28 @@ public class SpringSecurityMessageSourceTests extends TestCase {
|
||||
|
||||
// Cause a message to be generated
|
||||
MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
assertEquals("Le jeton nonce est compromis FOOBAR",
|
||||
messages.getMessage("DigestAuthenticationFilter.nonceCompromised", new Object[] {"FOOBAR"},
|
||||
assertEquals("Le jeton nonce est compromis FOOBAR", messages.getMessage(
|
||||
"DigestAuthenticationFilter.nonceCompromised", new Object[] { "FOOBAR" },
|
||||
"ERROR - FAILED TO LOOKUP"));
|
||||
|
||||
// Revert to original Locale
|
||||
LocaleContextHolder.setLocale(before);
|
||||
}
|
||||
|
||||
// SEC-3013
|
||||
public void germanSystemLocaleWithEnglishLocaleContextHolder() {
|
||||
Locale beforeSystem = Locale.getDefault();
|
||||
Locale.setDefault(Locale.GERMAN);
|
||||
|
||||
Locale beforeHolder = LocaleContextHolder.getLocale();
|
||||
LocaleContextHolder.setLocale(Locale.US);
|
||||
|
||||
MessageSourceAccessor msgs = SpringSecurityMessageSource.getAccessor();
|
||||
assertEquals("Access is denied", msgs.getMessage(
|
||||
"AbstractAccessDecisionManager.accessDenied", "Ooops"));
|
||||
|
||||
// Revert to original Locale
|
||||
Locale.setDefault(beforeSystem);
|
||||
LocaleContextHolder.setLocale(beforeHolder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
Implementation-Title: org.springframework.security.core
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.core
|
||||
Bundle-Name: Spring Security Core
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.aopalliance.*;version="${aopAllianceRange}",
|
||||
org.aspectj.*;version="${aspectjRange}";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
org.springframework.aop.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.beans.*;version="${springRange}",
|
||||
org.springframework.cache.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.context.*;version="${springRange}",
|
||||
org.springframework.core.*;version="${springRange}",
|
||||
org.springframework.expression.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.dao.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.jdbc.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.scheduling.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.transaction.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.util;version="${springRange}",
|
||||
net.sf.ehcache.*;version="${ehcacheRange}";resolution:=optional,
|
||||
javax.annotation.security.*;version="0";resolution:=optional,
|
||||
javax.crypto.*;version="0";resolution:=optional,
|
||||
javax.security.auth.*;version="0";resolution:=optional,
|
||||
javax.naming.*;version="0";resolution:=optional
|
||||
+2
-20
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-crypto</name>
|
||||
<description>spring-security-crypto</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,25 +42,7 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
@@ -101,7 +83,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+73
-18
@@ -22,19 +22,24 @@ import static org.springframework.security.crypto.encrypt.CipherUtils.newSecretK
|
||||
import static org.springframework.security.crypto.util.EncodingUtils.concatenate;
|
||||
import static org.springframework.security.crypto.util.EncodingUtils.subArray;
|
||||
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.springframework.security.crypto.codec.Hex;
|
||||
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
|
||||
import org.springframework.security.crypto.keygen.KeyGenerators;
|
||||
|
||||
/**
|
||||
* Encryptor that uses 256-bit AES encryption.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Dave Syer
|
||||
*/
|
||||
final class AesBytesEncryptor implements BytesEncryptor {
|
||||
|
||||
@@ -46,58 +51,108 @@ final class AesBytesEncryptor implements BytesEncryptor {
|
||||
|
||||
private final BytesKeyGenerator ivGenerator;
|
||||
|
||||
private CipherAlgorithm alg;
|
||||
|
||||
private static final String AES_CBC_ALGORITHM = "AES/CBC/PKCS5Padding";
|
||||
|
||||
private static final String AES_GCM_ALGORITHM = "AES/GCM/NoPadding";
|
||||
|
||||
public enum CipherAlgorithm {
|
||||
|
||||
CBC(AES_CBC_ALGORITHM, NULL_IV_GENERATOR), GCM(AES_GCM_ALGORITHM, KeyGenerators
|
||||
.secureRandom(16));
|
||||
|
||||
private BytesKeyGenerator ivGenerator;
|
||||
private String name;
|
||||
|
||||
private CipherAlgorithm(String name, BytesKeyGenerator ivGenerator) {
|
||||
this.name = name;
|
||||
this.ivGenerator = ivGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public AlgorithmParameterSpec getParameterSpec(byte[] iv) {
|
||||
return this == CBC ? new IvParameterSpec(iv) : new GCMParameterSpec(128, iv);
|
||||
}
|
||||
|
||||
public Cipher createCipher() {
|
||||
return newCipher(this.toString());
|
||||
}
|
||||
|
||||
public BytesKeyGenerator defaultIvGenerator() {
|
||||
return this.ivGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
public AesBytesEncryptor(String password, CharSequence salt) {
|
||||
this(password, salt, null);
|
||||
}
|
||||
|
||||
public AesBytesEncryptor(String password, CharSequence salt, BytesKeyGenerator ivGenerator) {
|
||||
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt), 1024, 256);
|
||||
public AesBytesEncryptor(String password, CharSequence salt,
|
||||
BytesKeyGenerator ivGenerator) {
|
||||
this(password, salt, ivGenerator, CipherAlgorithm.CBC);
|
||||
}
|
||||
|
||||
public AesBytesEncryptor(String password, CharSequence salt,
|
||||
BytesKeyGenerator ivGenerator, CipherAlgorithm alg) {
|
||||
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt),
|
||||
1024, 256);
|
||||
SecretKey secretKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec);
|
||||
this.secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");
|
||||
encryptor = newCipher(AES_ALGORITHM);
|
||||
decryptor = newCipher(AES_ALGORITHM);
|
||||
this.ivGenerator = ivGenerator != null ? ivGenerator : NULL_IV_GENERATOR;
|
||||
this.alg = alg;
|
||||
this.encryptor = alg.createCipher();
|
||||
this.decryptor = alg.createCipher();
|
||||
this.ivGenerator = ivGenerator != null ? ivGenerator : alg.defaultIvGenerator();
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] bytes) {
|
||||
synchronized (encryptor) {
|
||||
byte[] iv = ivGenerator.generateKey();
|
||||
initCipher(encryptor, Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
|
||||
byte[] encrypted = doFinal(encryptor, bytes);
|
||||
return ivGenerator != NULL_IV_GENERATOR ? concatenate(iv, encrypted) : encrypted;
|
||||
synchronized (this.encryptor) {
|
||||
byte[] iv = this.ivGenerator.generateKey();
|
||||
initCipher(this.encryptor, Cipher.ENCRYPT_MODE, this.secretKey,
|
||||
this.alg.getParameterSpec(iv));
|
||||
byte[] encrypted = doFinal(this.encryptor, bytes);
|
||||
return this.ivGenerator != NULL_IV_GENERATOR ? concatenate(iv, encrypted)
|
||||
: encrypted;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] encryptedBytes) {
|
||||
synchronized (decryptor) {
|
||||
synchronized (this.decryptor) {
|
||||
byte[] iv = iv(encryptedBytes);
|
||||
initCipher(decryptor, Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
|
||||
return doFinal(decryptor, ivGenerator != NULL_IV_GENERATOR ? encrypted(encryptedBytes, iv.length) : encryptedBytes);
|
||||
initCipher(this.decryptor, Cipher.DECRYPT_MODE, this.secretKey,
|
||||
this.alg.getParameterSpec(iv));
|
||||
return doFinal(
|
||||
this.decryptor,
|
||||
this.ivGenerator != NULL_IV_GENERATOR ? encrypted(encryptedBytes,
|
||||
iv.length) : encryptedBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private byte[] iv(byte[] encrypted) {
|
||||
return ivGenerator != NULL_IV_GENERATOR ? subArray(encrypted, 0, ivGenerator.getKeyLength()) : NULL_IV_GENERATOR.generateKey();
|
||||
return this.ivGenerator != NULL_IV_GENERATOR ? subArray(encrypted, 0,
|
||||
this.ivGenerator.getKeyLength()) : NULL_IV_GENERATOR.generateKey();
|
||||
}
|
||||
|
||||
private byte[] encrypted(byte[] encryptedBytes, int ivLength) {
|
||||
return subArray(encryptedBytes, ivLength, encryptedBytes.length);
|
||||
}
|
||||
|
||||
private static final String AES_ALGORITHM = "AES/CBC/PKCS5Padding";
|
||||
|
||||
private static final BytesKeyGenerator NULL_IV_GENERATOR = new BytesKeyGenerator() {
|
||||
|
||||
private final byte[] VALUE = new byte[16];
|
||||
|
||||
public int getKeyLength() {
|
||||
return VALUE.length;
|
||||
return this.VALUE.length;
|
||||
}
|
||||
|
||||
public byte[] generateKey() {
|
||||
return VALUE;
|
||||
return this.VALUE;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -15,57 +15,100 @@
|
||||
*/
|
||||
package org.springframework.security.crypto.encrypt;
|
||||
|
||||
import org.springframework.security.crypto.encrypt.AesBytesEncryptor.CipherAlgorithm;
|
||||
import org.springframework.security.crypto.keygen.KeyGenerators;
|
||||
|
||||
/**
|
||||
* Factory for commonly used encryptors.
|
||||
* Defines the public API for constructing {@link BytesEncryptor} and {@link TextEncryptor} implementations.
|
||||
* Factory for commonly used encryptors. Defines the public API for constructing
|
||||
* {@link BytesEncryptor} and {@link TextEncryptor} implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class Encryptors {
|
||||
|
||||
/**
|
||||
* Creates a standard password-based bytes encryptor using 256 bit AES encryption.
|
||||
* Derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
|
||||
* Salts the password to prevent dictionary attacks against the key.
|
||||
* The provided salt is expected to be hex-encoded; it should be random and at least 8 bytes in length.
|
||||
* Also applies a random 16 byte initialization vector to ensure each encrypted message will be unique.
|
||||
* Requires Java 6.
|
||||
* Creates a standard password-based bytes encryptor using 256 bit AES encryption with
|
||||
* Galois Counter Mode (GCM). Derives the secret key using PKCS #5's PBKDF2
|
||||
* (Password-Based Key Derivation Function #2). Salts the password to prevent
|
||||
* dictionary attacks against the key. The provided salt is expected to be
|
||||
* hex-encoded; it should be random and at least 8 bytes in length. Also applies a
|
||||
* random 16 byte initialization vector to ensure each encrypted message will be
|
||||
* unique. Requires Java 6.
|
||||
*
|
||||
* @param password the password used to generate the encryptor's secret key; should not be shared
|
||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the key
|
||||
* @param password the password used to generate the encryptor's secret key; should
|
||||
* not be shared
|
||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||
* key
|
||||
*
|
||||
* @see #standard(CharSequence, CharSequence) which uses the slightly weaker CBC mode
|
||||
* (instead of GCM)
|
||||
*/
|
||||
public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
|
||||
return new AesBytesEncryptor(password.toString(), salt, KeyGenerators.secureRandom(16));
|
||||
public static BytesEncryptor stronger(CharSequence password, CharSequence salt) {
|
||||
return new AesBytesEncryptor(password.toString(), salt,
|
||||
KeyGenerators.secureRandom(16), CipherAlgorithm.GCM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text encryptor that uses standard password-based encryption.
|
||||
* Encrypted text is hex-encoded.
|
||||
* Creates a standard password-based bytes encryptor using 256 bit AES encryption.
|
||||
* Derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation
|
||||
* Function #2). Salts the password to prevent dictionary attacks against the key. The
|
||||
* provided salt is expected to be hex-encoded; it should be random and at least 8
|
||||
* bytes in length. Also applies a random 16 byte initialization vector to ensure each
|
||||
* encrypted message will be unique. Requires Java 6.
|
||||
*
|
||||
* @param password the password used to generate the encryptor's secret key; should not be shared
|
||||
* @param password the password used to generate the encryptor's secret key; should
|
||||
* not be shared
|
||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||
* key
|
||||
*/
|
||||
public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
|
||||
return new AesBytesEncryptor(password.toString(), salt,
|
||||
KeyGenerators.secureRandom(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text encryptor that uses "stronger" password-based encryption. Encrypted
|
||||
* text is hex-encoded.
|
||||
*
|
||||
* @param password the password used to generate the encryptor's secret key; should
|
||||
* not be shared
|
||||
* @see Encryptors#stronger(CharSequence, CharSequence)
|
||||
*/
|
||||
public static TextEncryptor delux(CharSequence password, CharSequence salt) {
|
||||
return new HexEncodingTextEncryptor(stronger(password, salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text encryptor that uses "standard" password-based encryption. Encrypted
|
||||
* text is hex-encoded.
|
||||
*
|
||||
* @param password the password used to generate the encryptor's secret key; should
|
||||
* not be shared
|
||||
* @see Encryptors#standard(CharSequence, CharSequence)
|
||||
*/
|
||||
public static TextEncryptor text(CharSequence password, CharSequence salt) {
|
||||
return new HexEncodingTextEncryptor(standard(password, salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an encryptor for queryable text strings that uses standard password-based encryption.
|
||||
* Uses a 16-byte all-zero initialization vector so encrypting the same data results in the same encryption result.
|
||||
* This is done to allow encrypted data to be queried against.
|
||||
* Encrypted text is hex-encoded.
|
||||
* Creates an encryptor for queryable text strings that uses standard password-based
|
||||
* encryption. Uses a 16-byte all-zero initialization vector so encrypting the same
|
||||
* data results in the same encryption result. This is done to allow encrypted data to
|
||||
* be queried against. Encrypted text is hex-encoded.
|
||||
*
|
||||
* @param password the password used to generate the encryptor's secret key; should not be shared
|
||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the secret key
|
||||
* @param password the password used to generate the encryptor's secret key; should
|
||||
* not be shared
|
||||
* @param salt a hex-encoded, random, site-global salt value to use to generate the
|
||||
* secret key
|
||||
*/
|
||||
public static TextEncryptor queryableText(CharSequence password, CharSequence salt) {
|
||||
return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(), salt));
|
||||
return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(),
|
||||
salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text encryptor that performs no encryption.
|
||||
* Useful for developer testing environments where working with plain text strings is desired for simplicity.
|
||||
* Creates a text encryptor that performs no encryption. Useful for developer testing
|
||||
* environments where working with plain text strings is desired for simplicity.
|
||||
*/
|
||||
public static TextEncryptor noOpText() {
|
||||
return NO_OP_TEXT_INSTANCE;
|
||||
|
||||
+43
-2
@@ -5,10 +5,28 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EncryptorsTests {
|
||||
|
||||
@Test
|
||||
public void stronger() throws Exception {
|
||||
Assume.assumeTrue("GCM must be available for this test", isAesGcmAvailable());
|
||||
|
||||
BytesEncryptor encryptor = Encryptors.stronger("password", "5c0744940b5c369b");
|
||||
byte[] result = encryptor.encrypt("text".getBytes("UTF-8"));
|
||||
assertNotNull(result);
|
||||
assertFalse(new String(result).equals("text"));
|
||||
assertEquals("text", new String(encryptor.decrypt(result)));
|
||||
assertFalse(new String(result).equals(new String(encryptor.encrypt("text"
|
||||
.getBytes()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standard() throws Exception {
|
||||
BytesEncryptor encryptor = Encryptors.standard("password", "5c0744940b5c369b");
|
||||
@@ -16,7 +34,20 @@ public class EncryptorsTests {
|
||||
assertNotNull(result);
|
||||
assertFalse(new String(result).equals("text"));
|
||||
assertEquals("text", new String(encryptor.decrypt(result)));
|
||||
assertFalse(new String(result).equals(new String(encryptor.encrypt("text".getBytes()))));
|
||||
assertFalse(new String(result).equals(new String(encryptor.encrypt("text"
|
||||
.getBytes()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferred() {
|
||||
Assume.assumeTrue("GCM must be available for this test", isAesGcmAvailable());
|
||||
|
||||
TextEncryptor encryptor = Encryptors.delux("password", "5c0744940b5c369b");
|
||||
String result = encryptor.encrypt("text");
|
||||
assertNotNull(result);
|
||||
assertFalse(result.equals("text"));
|
||||
assertEquals("text", encryptor.decrypt(result));
|
||||
assertFalse(result.equals(encryptor.encrypt("text")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -31,7 +62,8 @@ public class EncryptorsTests {
|
||||
|
||||
@Test
|
||||
public void queryableText() {
|
||||
TextEncryptor encryptor = Encryptors.queryableText("password", "5c0744940b5c369b");
|
||||
TextEncryptor encryptor = Encryptors
|
||||
.queryableText("password", "5c0744940b5c369b");
|
||||
String result = encryptor.encrypt("text");
|
||||
assertNotNull(result);
|
||||
assertFalse(result.equals("text"));
|
||||
@@ -45,4 +77,13 @@ public class EncryptorsTests {
|
||||
assertEquals("text", encryptor.encrypt("text"));
|
||||
assertEquals("text", encryptor.decrypt("text"));
|
||||
}
|
||||
|
||||
private boolean isAesGcmAvailable() {
|
||||
try {
|
||||
Cipher.getInstance("AES/GCM/NoPadding");
|
||||
return true;
|
||||
} catch (GeneralSecurityException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
Implementation-Title: org.springframework.security.crypto
|
||||
Implementation-Version: ${version}
|
||||
Bundle-SymbolicName: org.springframework.security.crypto
|
||||
Bundle-Name: Spring Security Crypto
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-Version: ${version}
|
||||
Bundle-ManifestVersion: 2
|
||||
Ignored-Existing-Headers:
|
||||
Import-Package,
|
||||
Export-Package
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="${cloggingRange}",
|
||||
javax.crypto.*;version="0"
|
||||
@@ -1,5 +0,0 @@
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
"org.springframework.data:spring-data-commons:$springDataCommonsVersion"
|
||||
|
||||
}
|
||||
-120
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-data</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<name>spring-security-data</name>
|
||||
<description>spring-security-data</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<version>1.9.0.RC1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>0.9.29</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.data.repository.query;
|
||||
|
||||
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
|
||||
import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport;
|
||||
import org.springframework.data.repository.query.spi.Function;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* By defining this object as a Bean, Spring Security is exposed as SpEL expressions for creating Spring Data
|
||||
* queries.
|
||||
* </p>
|
||||
*
|
||||
* <p>With Java based configuration, we can define the bean using the following:</p>
|
||||
*
|
||||
* <p>For example, if you return a UserDetails that extends the following User object:</p>
|
||||
*
|
||||
* <pre>
|
||||
* @Entity
|
||||
* public class User {
|
||||
* @GeneratedValue(strategy = GenerationType.AUTO)
|
||||
* @Id
|
||||
* private Long id;
|
||||
*
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* <p>And you have a Message object that looks like the following:</p>
|
||||
*
|
||||
* <pre>
|
||||
* @Entity
|
||||
* public class Message {
|
||||
* @Id
|
||||
* @GeneratedValue(strategy = GenerationType.AUTO)
|
||||
* private Long id;
|
||||
*
|
||||
* @OneToOne
|
||||
* private User to;
|
||||
*
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* You can use the following {@code Query} annotation to search for only messages that are to the current user:
|
||||
*
|
||||
* <pre>
|
||||
* @Repository
|
||||
* public interface SecurityMessageRepository extends MessageRepository {
|
||||
*
|
||||
* @Query("select m from Message m where m.to.id = ?#{ principal?.id }")
|
||||
* List<Message> findAll();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* This works because the principal in this instance is a User which has an id field on it.
|
||||
*
|
||||
* @since 4.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class SecurityEvaluationContextExtension extends EvaluationContextExtensionSupport {
|
||||
private Authentication authentication;
|
||||
|
||||
/**
|
||||
* Creates a new instance that uses the current {@link Authentication} found on the
|
||||
* {@link org.springframework.security.core.context.SecurityContextHolder}.
|
||||
*/
|
||||
public SecurityEvaluationContextExtension() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance that always uses the same {@link Authentication} object.
|
||||
*
|
||||
* @param authentication the {@link Authentication} to use
|
||||
*/
|
||||
public SecurityEvaluationContextExtension(Authentication authentication) {
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtensionId() {
|
||||
return "security";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRootObject() {
|
||||
Authentication authentication = getAuthentication();
|
||||
return new SecurityExpressionRoot(authentication) {};
|
||||
}
|
||||
|
||||
private Authentication getAuthentication() {
|
||||
if(authentication != null) {
|
||||
return authentication;
|
||||
}
|
||||
|
||||
SecurityContext context = SecurityContextHolder.getContext();
|
||||
return context.getAuthentication();
|
||||
}
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.data.repository.query;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
public class SecurityEvaluationContextExtensionTests {
|
||||
SecurityEvaluationContextExtension securityExtension;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
securityExtension = new SecurityEvaluationContextExtension();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getRootObjectSecurityContextHolderAuthenticationNull() {
|
||||
getRoot().getAuthentication();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRootObjectSecurityContextHolderAuthentication() {
|
||||
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER");
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
assertThat(getRoot().getAuthentication()).isSameAs(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRootObjectExplicitAuthenticationOverridesSecurityContextHolder() {
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT");
|
||||
securityExtension = new SecurityEvaluationContextExtension(explicit);
|
||||
|
||||
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER");
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
assertThat(getRoot().getAuthentication()).isSameAs(explicit);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRootObjectExplicitAuthentication() {
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT");
|
||||
securityExtension = new SecurityEvaluationContextExtension(explicit);
|
||||
|
||||
assertThat(getRoot().getAuthentication()).isSameAs(explicit);
|
||||
}
|
||||
|
||||
private SecurityExpressionRoot getRoot() {
|
||||
return (SecurityExpressionRoot) securityExtension.getRootObject();
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ project('manual') {
|
||||
numbered: '',
|
||||
'spring-security-version' : project.version,
|
||||
'spring-version' : springVersion,
|
||||
'spring4-version' : spring4Version,
|
||||
revnumber : project.version
|
||||
]
|
||||
]
|
||||
|
||||
@@ -111,7 +111,7 @@ We can view the user name, but how are we able to log out? Below you can see how
|
||||
</form>
|
||||
----
|
||||
|
||||
If you try to log out right now the request will fail. The reason is that Spring Security is protecting against CSRF attakcks and there is no CSRF token include in our request. Update our configuration to use the `@EnableWebMvcSecurity` annotation which will do the same as `@EnableWebMvcSecurity` and provide integration with Spring MVC. Among other things, it will ensure our CSRF Token is included in our forms automatically when using Thymleaf 2.1+ or Spring MVC taglibs.
|
||||
If you try to log out right now the request will fail. The reason is that Spring Security is protecting against CSRF attacks and there is no CSRF token include in our request. Update our configuration to use the `@EnableWebMvcSecurity` annotation which will do the same as `@EnableWebSecurity` and provide integration with Spring MVC. Among other things, it will ensure our CSRF Token is included in our forms automatically when using Thymleaf 2.1+ or Spring MVC taglibs.
|
||||
|
||||
.src/main/java/org/springframework/security/samples/config/SecurityConfig.java
|
||||
[source,java]
|
||||
|
||||
@@ -198,9 +198,9 @@ If you are using a milestone or release candidate version, you will need to ensu
|
||||
----
|
||||
|
||||
[[maven-bom]]
|
||||
===== Spring Framework Bom
|
||||
===== Using Spring 4 and Maven
|
||||
|
||||
Spring Security builds against Spring Framework {spring-version}, but should work with 4.0.x. The problem that many users will have is that Spring Security's transitive dependencies resolve Spring Framework {spring-version} which can cause strange classpath problems.
|
||||
Spring Security builds against Spring Framework {spring-version}, but is also tested against Spring Framework {spring4-version}. This means you can use Spring Security {spring-security-version} with Spring Framework {spring4-version}. The problem that many users will have is that Spring Security's transitive dependencies resolve Spring Framework {spring-version} causing all sorts of strange classpath problems.
|
||||
|
||||
One (tedious) way to circumvent this issue would be to include all the Spring Framework modules in a http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management[<dependencyManagement>] section of your pom. An alternative approach is to include the `spring-framework-bom` within your `<dependencyManagement>` section of your `pom.xml` as shown below:
|
||||
|
||||
@@ -213,7 +213,7 @@ One (tedious) way to circumvent this issue would be to include all the Spring Fr
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>{spring-version}</version>
|
||||
<version>{spring4-version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -221,7 +221,7 @@ One (tedious) way to circumvent this issue would be to include all the Spring Fr
|
||||
</dependencyManagement>
|
||||
----
|
||||
|
||||
This will ensure that all the transitive dependencies of Spring Security use the Spring {spring-version} modules.
|
||||
This will ensure that all the transitive dependencies of Spring Security use the Spring {spring4-version} modules.
|
||||
|
||||
NOTE: This approach uses Maven's "bill of materials" (BOM) concept and is only available in Maven 2.0.9+. For additional details about how dependencies are resolved refer to http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html[Maven's Introduction to the Dependency Mechanism documentation].
|
||||
|
||||
@@ -274,9 +274,9 @@ repositories {
|
||||
----
|
||||
|
||||
[[gradle-resolutionStrategy]]
|
||||
===== Using Spring 4.0.x and Gradle
|
||||
===== Using Spring 4 and Gradle
|
||||
|
||||
By default Gradle will use the newest version when resolving transitive versions. This means that often times no additional work is necessary when running Spring Security {spring-security-version} with Spring Framework {spring-version}. However, at times there can be issues that come up so it is best to mitigate this using http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html[Gradle's ResolutionStrategy] as shown below:
|
||||
By default Gradle will use the newest version when resolving transitive versions. This means that often times no additional work is necessary when running Spring Security {spring-security-version} with Spring Framework {spring4-version}. However, at times there can be issues that come up so it is best to mitigate this using http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html[Gradle's ResolutionStrategy] as shown below:
|
||||
|
||||
.build.gradle
|
||||
[source,groovy]
|
||||
@@ -285,13 +285,13 @@ By default Gradle will use the newest version when resolving transitive versions
|
||||
configurations.all {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.springframework') {
|
||||
details.useVersion '{spring-version}'
|
||||
details.useVersion '{spring4-version}'
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
This will ensure that all the transitive dependencies of Spring Security use the Spring {spring-version} modules.
|
||||
This will ensure that all the transitive dependencies of Spring Security use the Spring {spring4-version} modules.
|
||||
|
||||
NOTE: This example uses Gradle 1.9, but may need modifications to work in future versions of Gradle since this is an incubating feature within Gradle.
|
||||
|
||||
@@ -809,7 +809,7 @@ public class MultiHttpSecurityConfig {
|
||||
[[jc-method]]
|
||||
=== Method Security
|
||||
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods. It provides support for JSR-250 annotation security as well as the framework���s original @Secured annotation. From 3.0 you can also make use of new <<el-access,expression-based annotations>>. You can apply security to a single bean, using the intercept-methods element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods. It provides support for JSR-250 annotation security as well as the framework’s original @Secured annotation. From 3.0 you can also make use of new <<el-access,expression-based annotations>>. You can apply security to a single bean, using the intercept-methods element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
|
||||
|
||||
==== EnableGlobalMethodSecurity
|
||||
|
||||
@@ -824,7 +824,7 @@ public class MethodSecurityConfig {
|
||||
}
|
||||
----
|
||||
|
||||
Adding an annotation to a method (on an class or interface) would then limit the access to that method accordingly. Spring Security���s native annotation support defines a set of attributes for the method. These will be passed to the AccessDecisionManager for it to make the actual decision:
|
||||
Adding an annotation to a method (on an class or interface) would then limit the access to that method accordingly. Spring Security’s native annotation support defines a set of attributes for the method. These will be passed to the AccessDecisionManager for it to make the actual decision:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -852,7 +852,7 @@ public class MethodSecurityConfig {
|
||||
}
|
||||
----
|
||||
|
||||
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security���s native annotations. To use the new expression-based syntax, you would use
|
||||
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security’s native annotations. To use the new expression-based syntax, you would use
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -2320,7 +2320,7 @@ Notice that the filter is actually a `DelegatingFilterProxy`, and not the class
|
||||
|
||||
[[filter-chain-proxy]]
|
||||
=== FilterChainProxy
|
||||
Spring Security's web infrastructure should only be used by delegating to an instance of `FilterChainProxy`. The security filters should not be used by themselves. In theory you could declare each Spring Security filter bean that you require in your application context file and add a corresponding `DelegatingFilterProxy` entry to `web.xml` for each filter, making sure that they are ordered correctly, but this would be cumbersome and would clutter up the `web.xml` file quickly if you have a lot of filters. `FilterChainProxy` lets us add a single entry to `web.xml` and deal entirely with the application context file for managing our web security beans. It is wired using a`DelegatingFilterProxy`, just like in the example above, but with the `filter-name` set to the bean name "filterChainProxy". The filter chain is then declared in the application context with the same bean name. Here's an example:
|
||||
Spring Security's web infrastructure should only be used by delegating to an instance of `FilterChainProxy`. The security filters should not be used by themselves. In theory you could declare each Spring Security filter bean that you require in your application context file and add a corresponding `DelegatingFilterProxy` entry to `web.xml` for each filter, making sure that they are ordered correctly, but this would be cumbersome and would clutter up the `web.xml` file quickly if you have a lot of filters. `FilterChainProxy` lets us add a single entry to `web.xml` and deal entirely with the application context file for managing our web security beans. It is wired using a `DelegatingFilterProxy`, just like in the example above, but with the `filter-name` set to the bean name "filterChainProxy". The filter chain is then declared in the application context with the same bean name. Here's an example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -2902,7 +2902,10 @@ create table persistent_logins (username varchar(64) not null,
|
||||
|
||||
[[remember-me-impls]]
|
||||
=== Remember-Me Interfaces and Implementations
|
||||
Remember-me authentication is not used with basic authentication, given it is often not used with `HttpSession` s. Remember-me is used with `UsernamePasswordAuthenticationFilter`, and is implemented via hooks in the `AbstractAuthenticationProcessingFilter` superclass. The hooks will invoke a concrete `RememberMeServices` at the appropriate times. The interface looks like this:
|
||||
Remember-me is used with `UsernamePasswordAuthenticationFilter`, and is implemented via hooks in the `AbstractAuthenticationProcessingFilter` superclass.
|
||||
It is also used within `BasicAuthenticationFilter`.
|
||||
The hooks will invoke a concrete `RememberMeServices` at the appropriate times.
|
||||
The interface looks like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -2936,7 +2939,7 @@ The beans required in an application context to enable remember-me services are
|
||||
</bean>
|
||||
|
||||
<bean id="rememberMeAuthenticationProvider" class=
|
||||
"org.springframework.security.authentication.RememberMeAuthenticationProvider">
|
||||
"org.springframework.security.authentication.rememberme.RememberMeAuthenticationProvider">
|
||||
<property name="key" value="springRocks"/>
|
||||
</bean>
|
||||
----
|
||||
@@ -3559,14 +3562,14 @@ public class WebSecurityConfig extends
|
||||
http
|
||||
// ...
|
||||
.headers()
|
||||
.hsts();
|
||||
.httpStrictTransportSecurity();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[headers-frame-options]]
|
||||
==== X-Frame-Options
|
||||
Allowing your website to be added to a frame can be a security issue. For example, using clever CSS styling users could be tricked into clicking on something that they were not intending (http://www.youtube.com/watch?v=3mk0RySeNsU[video demo]). For example, a user that is logged into their bank might click a button that grants access to other users. This sort of attack is known ashttp://en.wikipedia.org/wiki/Clickjacking[Clickjacking].
|
||||
Allowing your website to be added to a frame can be a security issue. For example, using clever CSS styling users could be tricked into clicking on something that they were not intending (http://www.youtube.com/watch?v=3mk0RySeNsU[video demo]). For example, a user that is logged into their bank might click a button that grants access to other users. This sort of attack is known as http://en.wikipedia.org/wiki/Clickjacking[Clickjacking].
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
@@ -3701,8 +3704,8 @@ public class WebSecurityConfig extends
|
||||
http
|
||||
// ...
|
||||
.headers()
|
||||
.addHeaderWriter(new StaticHeaderWriter("X-Content-Security-Policy","default-src 'self'"))
|
||||
.addHeaderWriter(new StaticHeaderWriter("X-WebKit-CSP","default-src 'self'"));
|
||||
.addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy","default-src 'self'"))
|
||||
.addHeaderWriter(new StaticHeadersWriter("X-WebKit-CSP","default-src 'self'"));
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -3764,7 +3767,7 @@ At times you may want to only write a header for certain requests. For example,
|
||||
<!-- ... -->
|
||||
|
||||
<headers>
|
||||
<header header-ref="headerWriter"/>
|
||||
<header ref="headerWriter"/>
|
||||
</headers>
|
||||
</http>
|
||||
|
||||
@@ -4857,7 +4860,7 @@ Often a more complicated strategy than simple DN-matching is required to locate
|
||||
|
||||
[[ldap-searchobjects-filter]]
|
||||
===== FilterBasedLdapUserSearch
|
||||
This bean uses an LDAP filter to match the user object in the directory. The process is explained in the Javadoc for the corresponding search method on thehttp://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)[JDK DirContext class]. As explained there, the search filter can be supplied with parameters. For this class, the only valid parameter is `{0}` which will be replaced with the user's login name.
|
||||
This bean uses an LDAP filter to match the user object in the directory. The process is explained in the Javadoc for the corresponding search method on the http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)[JDK DirContext class]. As explained there, the search filter can be supplied with parameters. For this class, the only valid parameter is `{0}` which will be replaced with the user's login name.
|
||||
|
||||
|
||||
[[ldap-authorities]]
|
||||
@@ -6061,7 +6064,9 @@ public Callable<String> processUpload(final MultipartFile file) {
|
||||
More technically speaking, Spring Security integrates with `WebAsyncManager`. The `SecurityContext` that is used to process the `Callable` is the `SecurityContext` that exists on the `SecurityContextHolder` at the time `startCallableProcessing` is invoked.
|
||||
====
|
||||
|
||||
There is no automatic integration with a `DeferredResult` that is returned by controllers. This is because `DeferredResult` is processed by the users and thus there is no way of automatically integrating with it. However, you can still use <<concurrency-support>> to provide transparent integration with Spring Security.
|
||||
There is no automatic integration with a `DeferredResult` that is returned by controllers.
|
||||
This is because `DeferredResult` is processed by the users and thus there is no way of automatically integrating with it.
|
||||
However, you can still use <<concurrency,Concurrency Support>> to provide transparent integration with Spring Security.
|
||||
|
||||
[[mvc-csrf]]
|
||||
=== Spring MVC and CSRF Integration
|
||||
@@ -6804,12 +6809,12 @@ The `name` of the header.
|
||||
|
||||
|
||||
[[nsa-header-value]]
|
||||
* **header-value**
|
||||
* **value**
|
||||
The `value` of the header to add.
|
||||
|
||||
|
||||
[[nsa-header-ref]]
|
||||
* **header-ref**
|
||||
* **ref**
|
||||
Reference to a custom implementation of the `HeaderWriter` interface.
|
||||
|
||||
|
||||
@@ -7083,6 +7088,8 @@ Lists the access attributes which will be stored in the `FilterInvocationSecurit
|
||||
* **filters**
|
||||
Can only take the value "none". This will cause any matching request to bypass the Spring Security filter chain entirely. None of the rest of the `<http>` configuration will have any effect on the request and there will be no security context available for its duration. Access to secured methods during the request will fail.
|
||||
|
||||
NOTE: This property is invalid for <<nsa-filter-security-metadata-source,filter-security-metadata-source>>
|
||||
|
||||
|
||||
[[nsa-intercept-url-method]]
|
||||
* **method**
|
||||
@@ -7100,6 +7107,8 @@ Can be "http" or "https" depending on whether a particular URL pattern should be
|
||||
|
||||
If a `<port-mappings>` configuration is added, this will be used to by the `SecureChannelProcessor` and `InsecureChannelProcessor` beans to determine the ports used for redirecting to HTTP/HTTPS.
|
||||
|
||||
NOTE: This property is invalid for <<nsa-filter-security-metadata-source,filter-security-metadata-source>>
|
||||
|
||||
|
||||
[[nsa-jee]]
|
||||
==== <jee>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.0.0.M2
|
||||
version=3.2.8.RELEASE
|
||||
|
||||
+25
-16
@@ -12,7 +12,7 @@ apply plugin: 'propdeps-eclipse'
|
||||
sourceCompatibility = 1.5
|
||||
targetCompatibility = 1.5
|
||||
|
||||
ext.ehcacheVersion = '2.6.5'
|
||||
ext.ehcacheVersion = '1.7.2'
|
||||
ext.aspectjVersion = '1.6.10'
|
||||
ext.apacheDsVersion = '1.5.5'
|
||||
ext.jstlVersion = '1.2.1'
|
||||
@@ -21,15 +21,13 @@ ext.hsqlVersion = '2.3.1'
|
||||
ext.slf4jVersion = '1.7.5'
|
||||
ext.logbackVersion = '0.9.29'
|
||||
ext.cglibVersion = '2.2'
|
||||
ext.powerMockVersion = '1.5.1'
|
||||
ext.powerMockVersion = '1.6.1'
|
||||
ext.servletApiVersion = '3.0.1'
|
||||
ext.seleniumVersion = '2.33.0'
|
||||
ext.groovyVersion = '2.0.5'
|
||||
ext.spockVersion = '0.7-groovy-2.0'
|
||||
ext.gebVersion = '0.9.0'
|
||||
ext.thymeleafVersion = '2.1.3.RELEASE'
|
||||
ext.springDataJpaVersion = '1.7.0.RC1'
|
||||
ext.springDataCommonsVersion = '1.9.0.RC1'
|
||||
ext.thymeleafVersion = '2.1.2.RELEASE'
|
||||
|
||||
ext.spockDependencies = [
|
||||
dependencies.create("org.spockframework:spock-spring:$spockVersion") {
|
||||
@@ -40,13 +38,6 @@ ext.spockDependencies = [
|
||||
}
|
||||
]
|
||||
|
||||
ext.gebDependencies = spockDependencies + [
|
||||
"org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion",
|
||||
"org.gebish:geb-spock:$gebVersion",
|
||||
'commons-httpclient:commons-httpclient:3.1',
|
||||
"org.codehaus.groovy:groovy:$groovyVersion"
|
||||
]
|
||||
|
||||
ext.powerMockDependencies = [
|
||||
"org.powermock:powermock-core:$powerMockVersion",
|
||||
"org.powermock:powermock-api-support:$powerMockVersion",
|
||||
@@ -58,6 +49,12 @@ ext.powerMockDependencies = [
|
||||
"org.powermock:powermock-reflect:$powerMockVersion"
|
||||
]
|
||||
|
||||
ext.springCoreDependency = [
|
||||
dependencies.create("org.springframework:spring-core:$springVersion") {
|
||||
exclude(group: 'commons-logging', module: 'commons-logging')
|
||||
}
|
||||
]
|
||||
|
||||
ext.jstlDependencies = [
|
||||
"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
|
||||
"org.apache.taglibs:taglibs-standard-jstlel:1.2.1"
|
||||
@@ -72,6 +69,22 @@ ext.apachedsDependencies = [
|
||||
'org.apache.directory.shared:shared-ldap:0.9.15'
|
||||
]
|
||||
|
||||
ext.bundlorProperties = [
|
||||
version: version,
|
||||
secRange: "[$version, 3.3.0)",
|
||||
springRange: "[$springVersion, 5)",
|
||||
aspectjRange: '[1.6.0, 1.8.0)',
|
||||
casRange: '[3.1.1, 3.2.0)',
|
||||
cloggingRange: '[1.0.4, 2.0.0)',
|
||||
ehcacheRange: '[1.4.1, 2.5.0)',
|
||||
openid4javaRange: '[0.9.5, 1.0.0)',
|
||||
springLdapRange: '[1.3.0,1.4.0)',
|
||||
apacheDSRange: '[1.5.5, 1.6)',
|
||||
apacheDSSharedRange: '[0.9.15, 1.0)',
|
||||
ldapSdkRange: '[4.1, 5.0)',
|
||||
aopAllianceRange: '[1.0.0, 2.0.0)'
|
||||
]
|
||||
|
||||
// Integration test setup
|
||||
configurations {
|
||||
integrationTestCompile {
|
||||
@@ -109,10 +122,6 @@ check.dependsOn integrationTest
|
||||
dependencies {
|
||||
optional 'commons-logging:commons-logging:1.1.1'
|
||||
|
||||
compile ("org.springframework:spring-core:$springVersion") {
|
||||
exclude(group: 'commons-logging', module: 'commons-logging')
|
||||
}
|
||||
|
||||
testCompile 'junit:junit:4.11',
|
||||
'org.mockito:mockito-core:1.9.5',
|
||||
"org.springframework:spring-test:$springVersion",
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.gradle.api.plugins:gradle-tomcat-plugin:1.2.3")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'tomcat'
|
||||
|
||||
dependencies {
|
||||
@@ -16,52 +7,4 @@ dependencies {
|
||||
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
|
||||
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
|
||||
}
|
||||
}
|
||||
|
||||
task integrationTomcatRun(type: org.gradle.api.plugins.tomcat.tasks.TomcatRun) {
|
||||
onlyIf { !sourceSets.integrationTest.allSource.empty }
|
||||
buildscriptClasspath = tomcatRun.buildscriptClasspath
|
||||
contextPath = tomcatRun.contextPath
|
||||
daemon = true
|
||||
tomcatClasspath = tomcatRun.tomcatClasspath
|
||||
webAppClasspath = tomcatRun.webAppClasspath
|
||||
webAppSourceDirectory = tomcatRun.webAppSourceDirectory
|
||||
doFirst {
|
||||
def mainOutputDir = project.sourceSets.main.output.classesDir
|
||||
if(mainOutputDir) {
|
||||
classesDirectory = mainOutputDir
|
||||
}
|
||||
// delay reserving ports to ensure they are still available
|
||||
def ports = reservePorts(3)
|
||||
httpPort = ports[0]
|
||||
ajpPort = ports[1]
|
||||
stopPort = ports[2]
|
||||
}
|
||||
}
|
||||
|
||||
task integrationTomcatStop(type: org.gradle.api.plugins.tomcat.tasks.TomcatStop) {
|
||||
onlyIf { !sourceSets.integrationTest.allSource.empty }
|
||||
doFirst {
|
||||
stopPort = integrationTomcatRun.stopPort
|
||||
}
|
||||
}
|
||||
|
||||
integrationTest {
|
||||
dependsOn integrationTomcatRun
|
||||
doFirst {
|
||||
def host = 'localhost:' + integrationTomcatRun.httpPort
|
||||
systemProperties['geb.build.baseUrl'] = 'http://'+host+'/' + integrationTomcatRun.contextPath + '/'
|
||||
systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
|
||||
}
|
||||
finalizedBy integrationTomcatStop
|
||||
}
|
||||
|
||||
def reservePorts(int count) {
|
||||
def sockets = []
|
||||
for(int i in 1..count) {
|
||||
sockets << new ServerSocket(0)
|
||||
}
|
||||
def result = sockets*.localPort
|
||||
sockets*.close()
|
||||
result
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Fri Jun 13 11:14:37 CDT 2014
|
||||
#Wed Jun 11 13:57:21 CDT 2014
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
|
||||
|
||||
+10
-28
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>itest-context</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>itest-context</name>
|
||||
<description>itest-context</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -64,43 +58,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -155,25 +137,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -30,9 +30,7 @@ dependencies {
|
||||
|
||||
integrationTest {
|
||||
useTestNG();
|
||||
options {
|
||||
jvmArgs = ["-ea", '-Xms128m', '-Xmx500m']
|
||||
systemProperties = ['webapp.dir': "$projectDir/src/main/webapp"]
|
||||
}
|
||||
jvmArgs = ["-ea", '-Xms128m', '-Xmx500m']
|
||||
systemProperty 'webapp.dir', "$projectDir/src/main/webapp"
|
||||
maxParallelForks = 1
|
||||
}
|
||||
|
||||
+11
-29
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>itest-web</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>itest-web</name>
|
||||
<description>itest-web</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,35 +42,17 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -171,49 +153,49 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
+1
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion"
|
||||
@@ -19,7 +20,6 @@ dependencies {
|
||||
exclude(group: 'org.springframework', module: 'spring-core')
|
||||
exclude(group: 'org.springframework', module: 'spring-tx')
|
||||
exclude(group: 'org.springframework', module: 'spring-beans')
|
||||
exclude(group: 'org.springframework.data', module: 'spring-data-commons')
|
||||
}
|
||||
|
||||
testCompile "org.slf4j:slf4j-api:$slf4jVersion",
|
||||
|
||||
+8
-18
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<name>spring-security-ldap</name>
|
||||
<description>spring-security-ldap</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,17 +42,11 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap-core</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>1.3.2.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -63,10 +57,6 @@
|
||||
<artifactId>spring-core</artifactId>
|
||||
<groupId>org.springframework</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
@@ -80,25 +70,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>4.0.0.M2</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -110,7 +100,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -208,7 +198,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>4.1.0.RC2</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
-65
@@ -17,8 +17,6 @@ package org.springframework.security.ldap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.Context;
|
||||
@@ -101,69 +99,6 @@ public class SpringSecurityLdapTemplateITests extends AbstractLdapIntegrationTes
|
||||
assertTrue(values.contains("submanager"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiAttributeRetrievalWithNullAttributeNames() {
|
||||
Set<Map<String, List<String>>> values =
|
||||
template.searchForMultipleAttributeValues(
|
||||
"ou=people",
|
||||
"(uid={0})",
|
||||
new String[]{"bob"},
|
||||
null);
|
||||
assertEquals(1, values.size());
|
||||
Map<String, List<String>> record = values.iterator().next();
|
||||
assertAttributeValue(record, "uid", "bob");
|
||||
assertAttributeValue(record, "objectclass", "top", "person", "organizationalPerson", "inetOrgPerson");
|
||||
assertAttributeValue(record, "cn", "Bob Hamilton");
|
||||
assertAttributeValue(record, "sn", "Hamilton");
|
||||
assertFalse(record.containsKey("userPassword"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiAttributeRetrievalWithZeroLengthAttributeNames() {
|
||||
Set<Map<String, List<String>>> values =
|
||||
template.searchForMultipleAttributeValues(
|
||||
"ou=people",
|
||||
"(uid={0})",
|
||||
new String[]{"bob"},
|
||||
new String[0]);
|
||||
assertEquals(1, values.size());
|
||||
Map<String, List<String>> record = values.iterator().next();
|
||||
assertAttributeValue(record, "uid", "bob");
|
||||
assertAttributeValue(record, "objectclass", "top", "person", "organizationalPerson", "inetOrgPerson");
|
||||
assertAttributeValue(record, "cn", "Bob Hamilton");
|
||||
assertAttributeValue(record, "sn", "Hamilton");
|
||||
assertFalse(record.containsKey("userPassword"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiAttributeRetrievalWithSpecifiedAttributeNames() {
|
||||
Set<Map<String, List<String>>> values =
|
||||
template.searchForMultipleAttributeValues(
|
||||
"ou=people",
|
||||
"(uid={0})",
|
||||
new String[]{"bob"},
|
||||
new String[]{
|
||||
"uid",
|
||||
"cn",
|
||||
"sn"
|
||||
});
|
||||
assertEquals(1, values.size());
|
||||
Map<String, List<String>> record = values.iterator().next();
|
||||
assertAttributeValue(record, "uid", "bob");
|
||||
assertAttributeValue(record, "cn", "Bob Hamilton");
|
||||
assertAttributeValue(record, "sn", "Hamilton");
|
||||
assertFalse(record.containsKey("userPassword"));
|
||||
assertFalse(record.containsKey("objectclass"));
|
||||
}
|
||||
|
||||
protected void assertAttributeValue(Map<String, List<String>> record, String attributeName, String... values) {
|
||||
assertTrue(record.containsKey(attributeName));
|
||||
assertEquals(values.length, record.get(attributeName).size());
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
assertEquals(values[i], record.get(attributeName).get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoleSearchForMissingAttributeFailsGracefully() {
|
||||
String param = "uid=ben,ou=people,dc=springframework,dc=org";
|
||||
|
||||
+10
-11
@@ -15,13 +15,12 @@
|
||||
|
||||
package org.springframework.security.ldap.search;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
|
||||
|
||||
@@ -33,7 +32,7 @@ import org.springframework.security.ldap.AbstractLdapIntegrationTests;
|
||||
public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void basicSearchSucceeds() throws Exception {
|
||||
public void basicSearchSucceeds() {
|
||||
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", getContextSource());
|
||||
locator.setSearchSubtree(false);
|
||||
locator.setSearchTimeLimit(0);
|
||||
@@ -42,25 +41,25 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
|
||||
DirContextOperations bob = locator.searchForUser("bob");
|
||||
assertEquals("bob", bob.getStringAttribute("uid"));
|
||||
|
||||
assertEquals(new LdapName("uid=bob,ou=people"), bob.getDn());
|
||||
assertEquals(new DistinguishedName("uid=bob,ou=people"), bob.getDn());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchForNameWithCommaSucceeds() throws Exception {
|
||||
public void searchForNameWithCommaSucceeds() {
|
||||
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", getContextSource());
|
||||
locator.setSearchSubtree(false);
|
||||
|
||||
DirContextOperations jerry = locator.searchForUser("jerry");
|
||||
assertEquals("jerry", jerry.getStringAttribute("uid"));
|
||||
|
||||
assertEquals(new LdapName("cn=mouse\\, jerry,ou=people"), jerry.getDn());
|
||||
assertEquals(new DistinguishedName("cn=mouse\\, jerry,ou=people"), jerry.getDn());
|
||||
}
|
||||
|
||||
// Try some funny business with filters.
|
||||
@Test
|
||||
public void extraFilterPartToExcludeBob() throws Exception {
|
||||
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people",
|
||||
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry)(uid=slashguy)(uid=javadude)(uid=groovydude)(uid=closuredude)(uid=scaladude))))", getContextSource());
|
||||
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry)(uid=slashguy))))", getContextSource());
|
||||
|
||||
// Search for bob, get back ben...
|
||||
DirContextOperations ben = locator.searchForUser("bob");
|
||||
@@ -80,7 +79,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subTreeSearchSucceeds() throws Exception {
|
||||
public void subTreeSearchSucceeds() {
|
||||
// Don't set the searchBase, so search from the root.
|
||||
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("", "(cn={0})", getContextSource());
|
||||
locator.setSearchSubtree(true);
|
||||
@@ -88,7 +87,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
|
||||
DirContextOperations ben = locator.searchForUser("Ben Alex");
|
||||
assertEquals("ben", ben.getStringAttribute("uid"));
|
||||
|
||||
assertEquals(new LdapName("uid=ben,ou=people"), ben.getDn());
|
||||
assertEquals(new DistinguishedName("uid=ben,ou=people"), ben.getDn());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
/* 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.ldap.userdetails;
|
||||
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Filip Hanik
|
||||
*/
|
||||
public class NestedLdapAuthoritiesPopulatorTests extends AbstractLdapIntegrationTests {
|
||||
|
||||
private NestedLdapAuthoritiesPopulator populator;
|
||||
private LdapAuthority javaDevelopers;
|
||||
private LdapAuthority groovyDevelopers;
|
||||
private LdapAuthority scalaDevelopers;
|
||||
private LdapAuthority closureDevelopers;
|
||||
private LdapAuthority jDevelopers;
|
||||
private LdapAuthority circularJavaDevelopers;
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
populator = new NestedLdapAuthoritiesPopulator(getContextSource(), "ou=jdeveloper");
|
||||
populator.setGroupSearchFilter("(member={0})");
|
||||
populator.setIgnorePartialResultException(false);
|
||||
populator.setRolePrefix("");
|
||||
populator.setSearchSubtree(true);
|
||||
populator.setConvertToUpperCase(false);
|
||||
jDevelopers = new LdapAuthority("j-developers", "cn=j-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
javaDevelopers = new LdapAuthority("java-developers", "cn=java-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
groovyDevelopers = new LdapAuthority("groovy-developers", "cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
scalaDevelopers = new LdapAuthority("scala-developers", "cn=scala-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
closureDevelopers = new LdapAuthority("closure-developers", "cn=closure-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
circularJavaDevelopers = new LdapAuthority("circular-java-developers", "cn=circular-java-developers,ou=jdeveloper,dc=springframework,dc=org");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScalaDudeJDevelopersAuthorities() {
|
||||
DirContextAdapter ctx = new DirContextAdapter("uid=scaladude,ou=people,dc=springframework,dc=org");
|
||||
Collection<GrantedAuthority> authorities = populator.getGrantedAuthorities(ctx, "scaladude");
|
||||
assertEquals(5, authorities.size());
|
||||
assertEquals(Arrays.asList(javaDevelopers, scalaDevelopers, circularJavaDevelopers, jDevelopers, groovyDevelopers), authorities);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJavaDudeJDevelopersAuthorities() {
|
||||
DirContextAdapter ctx = new DirContextAdapter("uid=javadude,ou=people,dc=springframework,dc=org");
|
||||
Collection<GrantedAuthority> authorities = populator.getGrantedAuthorities(ctx, "javadude");
|
||||
assertEquals(3, authorities.size());
|
||||
assertEquals(Arrays.asList(javaDevelopers, circularJavaDevelopers, jDevelopers), authorities);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScalaDudeJDevelopersAuthoritiesWithSearchLimit() {
|
||||
populator.setMaxSearchDepth(1);
|
||||
DirContextAdapter ctx = new DirContextAdapter("uid=scaladude,ou=people,dc=springframework,dc=org");
|
||||
Collection<GrantedAuthority> authorities = populator.getGrantedAuthorities(ctx, "scaladude");
|
||||
assertEquals(1, authorities.size());
|
||||
assertEquals(Arrays.asList(scalaDevelopers), authorities);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroovyDudeJDevelopersAuthorities() {
|
||||
DirContextAdapter ctx = new DirContextAdapter("uid=groovydude,ou=people,dc=springframework,dc=org");
|
||||
Collection<GrantedAuthority> authorities = populator.getGrantedAuthorities(ctx, "groovydude");
|
||||
assertEquals(4, authorities.size());
|
||||
assertEquals(Arrays.asList(javaDevelopers, circularJavaDevelopers, jDevelopers, groovyDevelopers), authorities);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClosureDudeJDevelopersWithMembershipAsAttributeValues() {
|
||||
populator.setAttributeNames(new HashSet(Arrays.asList("member")));
|
||||
|
||||
DirContextAdapter ctx = new DirContextAdapter("uid=closuredude,ou=people,dc=springframework,dc=org");
|
||||
Collection<GrantedAuthority> authorities = populator.getGrantedAuthorities(ctx, "closuredude");
|
||||
assertEquals(5, authorities.size());
|
||||
assertEquals(Arrays.asList(closureDevelopers, javaDevelopers, circularJavaDevelopers, jDevelopers, groovyDevelopers), authorities);
|
||||
|
||||
LdapAuthority[] ldapAuthorities = authorities.toArray(new LdapAuthority[0]);
|
||||
assertEquals(5, ldapAuthorities.length);
|
||||
//closure group
|
||||
assertTrue(ldapAuthorities[0].getAttributes().containsKey("member"));
|
||||
assertNotNull(ldapAuthorities[0].getAttributes().get("member"));
|
||||
assertEquals(1, ldapAuthorities[0].getAttributes().get("member").size());
|
||||
assertEquals("uid=closuredude,ou=people,dc=springframework,dc=org", ldapAuthorities[0].getFirstAttributeValue("member"));
|
||||
|
||||
//java group
|
||||
assertTrue(ldapAuthorities[1].getAttributes().containsKey("member"));
|
||||
assertNotNull(ldapAuthorities[1].getAttributes().get("member"));
|
||||
assertEquals(3, ldapAuthorities[1].getAttributes().get("member").size());
|
||||
assertEquals(groovyDevelopers.getDn(), ldapAuthorities[1].getFirstAttributeValue("member"));
|
||||
assertEquals(
|
||||
new String[]{
|
||||
groovyDevelopers.getDn(),
|
||||
scalaDevelopers.getDn(),
|
||||
"uid=javadude,ou=people,dc=springframework,dc=org"
|
||||
},
|
||||
ldapAuthorities[1].getAttributes().get("member")
|
||||
);
|
||||
|
||||
//test non existent attribute
|
||||
assertNull(ldapAuthorities[2].getFirstAttributeValue("test"));
|
||||
assertNotNull(ldapAuthorities[2].getAttributeValues("test"));
|
||||
assertEquals(0, ldapAuthorities[2].getAttributeValues("test").size());
|
||||
//test role name
|
||||
assertEquals(jDevelopers.getAuthority(), ldapAuthorities[3].getAuthority());
|
||||
}
|
||||
}
|
||||
@@ -122,109 +122,3 @@ objectclass: groupOfNames
|
||||
cn: submanagers
|
||||
ou: submanager
|
||||
member: uid=ben,ou=people,dc=springframework,dc=org
|
||||
|
||||
#Nested groups data
|
||||
###################
|
||||
|
||||
dn: ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: jdeveloper
|
||||
|
||||
|
||||
# javadude is part of (in a nested search)
|
||||
# circular-java-developers, java-developers, j-developers
|
||||
dn: uid=javadude,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Java Dude
|
||||
sn: Dude
|
||||
uid: javadude
|
||||
userPassword: javadudespassword
|
||||
|
||||
# groovydude is part of (in a nested search)
|
||||
# groovy-developers, java-developers, circular-java-developers, j-developers
|
||||
dn: uid=groovydude,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Groovy Dude
|
||||
sn: Dude
|
||||
uid: groovydude
|
||||
userPassword: groovydudespassword
|
||||
|
||||
# closuredude is part of (in a nested search)
|
||||
# closure-developers, groovy-developers, java-developers, circular-java-developers, j-developers
|
||||
dn: uid=closuredude,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Closure Dude
|
||||
sn: Dude
|
||||
uid: closuredude
|
||||
userPassword: closuredudespassword
|
||||
|
||||
# scaladude is part of (in a nested search)
|
||||
# scala-developers, groovy-developers, java-developers, circular-java-developers, j-developers
|
||||
dn: uid=scaladude,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Scala Dude
|
||||
sn: Dude
|
||||
uid: scaladude
|
||||
userPassword: scaladudespassword
|
||||
|
||||
dn: cn=j-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: j-developers
|
||||
ou: jdeveloper
|
||||
member: cn=java-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
|
||||
dn: cn=java-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: java-developers
|
||||
ou: jdeveloper
|
||||
member: cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
member: cn=scala-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
member: uid=javadude,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=circular-java-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: circular-java-developers
|
||||
ou: jdeveloper
|
||||
member: cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
member: cn=scala-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
member: uid=javadude,ou=people,dc=springframework,dc=org
|
||||
|
||||
|
||||
dn: cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: groovy-developers
|
||||
ou: jdeveloper
|
||||
member: cn=closure-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
member: uid=groovydude,ou=people,dc=springframework,dc=org
|
||||
member: cn=circular-java-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
|
||||
dn: cn=closure-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: closure-developers
|
||||
ou: jdeveloper
|
||||
member: uid=closuredude,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=scala-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: scala-developers
|
||||
ou: jdeveloper
|
||||
member: uid=scaladude,ou=people,dc=springframework,dc=org
|
||||
|
||||
+7
-104
@@ -30,18 +30,13 @@ import org.springframework.util.Assert;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.PartialResultException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -50,7 +45,6 @@ import java.util.Set;
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @author Filip Hanik
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
@@ -58,13 +52,6 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
private static final Log logger = LogFactory.getLog(SpringSecurityLdapTemplate.class);
|
||||
|
||||
public static final String[] NO_ATTRS = new String[0];
|
||||
|
||||
/**
|
||||
* Every search results where a record is defined by a Map<String,String[]>
|
||||
* contains at least this key - the DN of the record itself.
|
||||
*/
|
||||
public static final String DN_KEY = "spring.security.ldap.dn";
|
||||
|
||||
private static final boolean RETURN_OBJECT = true;
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
@@ -152,124 +139,40 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
|
||||
*/
|
||||
public Set<String> searchForSingleAttributeValues(final String base, final String filter, final Object[] params,
|
||||
final String attributeName) {
|
||||
String[] attributeNames = new String[]{attributeName};
|
||||
Set<Map<String, List<String>>> multipleAttributeValues = searchForMultipleAttributeValues(base, filter, params, attributeNames);
|
||||
Set<String> result = new HashSet<String>();
|
||||
for (Map<String, List<String>> map : multipleAttributeValues) {
|
||||
List<String> values = map.get(attributeName);
|
||||
if (values != null) {
|
||||
result.addAll(values);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search using the supplied filter and returns the values of each named attribute
|
||||
* found in all entries matched by the search. Note that one directory entry may have several values for the
|
||||
* attribute. Intended for role searches and similar scenarios.
|
||||
*
|
||||
* @param base the DN to search in
|
||||
* @param filter search filter to use
|
||||
* @param params the parameters to substitute in the search filter
|
||||
* @param attributeNames the attributes' values that are to be retrieved.
|
||||
*
|
||||
* @return the set of String values for each attribute found in all the matching entries.
|
||||
* The attribute name is the key for each set of values. In addition each map contains the DN as a String
|
||||
* with the key predefined key {@link #DN_KEY}.
|
||||
*/
|
||||
public Set<Map<String, List<String>>> searchForMultipleAttributeValues(final String base, final String filter, final Object[] params,
|
||||
final String[] attributeNames) {
|
||||
// Escape the params acording to RFC2254
|
||||
Object[] encodedParams = new String[params.length];
|
||||
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
for (int i=0; i < params.length; i++) {
|
||||
encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
|
||||
}
|
||||
|
||||
String formattedFilter = MessageFormat.format(filter, encodedParams);
|
||||
logger.debug("Using filter: " + formattedFilter);
|
||||
|
||||
final HashSet<Map<String, List<String>>> set = new HashSet<Map<String, List<String>>>();
|
||||
final HashSet<String> set = new HashSet<String>();
|
||||
|
||||
ContextMapper roleMapper = new ContextMapper() {
|
||||
public Object mapFromContext(Object ctx) {
|
||||
DirContextAdapter adapter = (DirContextAdapter) ctx;
|
||||
Map<String, List<String>> record = new HashMap<String, List<String>>();
|
||||
if (attributeNames == null || attributeNames.length == 0) {
|
||||
try {
|
||||
for (NamingEnumeration ae = adapter.getAttributes().getAll(); ae.hasMore(); ) {
|
||||
Attribute attr = (Attribute) ae.next();
|
||||
extractStringAttributeValues(adapter, record, attr.getID());
|
||||
}
|
||||
} catch (NamingException x) {
|
||||
org.springframework.ldap.support.LdapUtils.convertLdapException(x);
|
||||
}
|
||||
String[] values = adapter.getStringAttributes(attributeName);
|
||||
if (values == null || values.length == 0) {
|
||||
logger.debug("No attribute value found for '" + attributeName + "'");
|
||||
} else {
|
||||
for (String attributeName : attributeNames) {
|
||||
extractStringAttributeValues(adapter, record, attributeName);
|
||||
}
|
||||
set.addAll(Arrays.asList(values));
|
||||
}
|
||||
record.put(DN_KEY, Arrays.asList(getAdapterDN(adapter)));
|
||||
set.add(record);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
SearchControls ctls = new SearchControls();
|
||||
ctls.setSearchScope(searchControls.getSearchScope());
|
||||
ctls.setReturningAttributes(attributeNames != null && attributeNames.length > 0 ? attributeNames : null);
|
||||
ctls.setReturningAttributes(new String[] {attributeName});
|
||||
|
||||
search(base, formattedFilter, ctls, roleMapper);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DN for the context representing this LDAP record.
|
||||
* By default this is using {@link javax.naming.Context#getNameInNamespace()}
|
||||
* instead of {@link org.springframework.ldap.core.DirContextAdapter#getDn()} since the
|
||||
* latter returns a partial DN if a base has been specified.
|
||||
* @param adapter - the Context to extract the DN from
|
||||
* @return - the String representing the full DN
|
||||
*/
|
||||
private String getAdapterDN(DirContextAdapter adapter) {
|
||||
//returns the full DN rather than the sub DN if a base is specified
|
||||
return adapter.getNameInNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts String values for a specified attribute name and places them in the map representing the ldap record If
|
||||
* a value is not of type String, it will derive it's value from the {@link Object#toString()}
|
||||
*
|
||||
* @param adapter - the adapter that contains the values
|
||||
* @param record - the map holding the attribute names and values
|
||||
* @param attributeName - the name for which to fetch the values from
|
||||
*/
|
||||
private void extractStringAttributeValues(DirContextAdapter adapter, Map<String, List<String>> record, String attributeName) {
|
||||
Object[] values = adapter.getObjectAttributes(attributeName);
|
||||
if (values == null || values.length == 0) {
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("No attribute value found for '" + attributeName + "'");
|
||||
}
|
||||
return;
|
||||
}
|
||||
List<String> svalues = new ArrayList<String>();
|
||||
for (Object o : values) {
|
||||
if (o != null) {
|
||||
if (String.class.isAssignableFrom(o.getClass())) {
|
||||
svalues.add((String) o);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Attribute:" + attributeName + " contains a non string value of type[" + o.getClass() + "]");
|
||||
}
|
||||
svalues.add(o.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
record.put(attributeName, svalues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search, with the requirement that the search shall return a single directory entry, and uses
|
||||
* the supplied mapper to create the object from that entry.
|
||||
|
||||
+52
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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
|
||||
@@ -47,11 +47,12 @@ import java.util.regex.Pattern;
|
||||
* Specialized LDAP authentication provider which uses Active Directory configuration conventions.
|
||||
* <p>
|
||||
* It will authenticate using the Active Directory
|
||||
* <a href="http://msdn.microsoft.com/en-us/library/ms680857%28VS.85%29.aspx">{@code userPrincipalName}</a>
|
||||
* (in the form {@code username@domain}). If the username does not already end with the domain name, the
|
||||
* {@code userPrincipalName} will be built by appending the configured domain name to the username supplied in the
|
||||
* authentication request. If no domain name is configured, it is assumed that the username will always contain the
|
||||
* domain name.
|
||||
* <a href="http://msdn.microsoft.com/en-us/library/ms680857%28VS.85%29.aspx">{@code userPrincipalName}</a> or
|
||||
* <a href="http://msdn.microsoft.com/en-us/library/ms679635%28v=vs.85%29.aspx">{@code sAMAccountName}</a> (or a custom
|
||||
* {@link #setSearchFilter(String) searchFilter}) in the form {@code username@domain}. If the username does not
|
||||
* already end with the domain name, the {@code userPrincipalName} will be built by appending the configured domain
|
||||
* name to the username supplied in the authentication request. If no domain name is configured, it is assumed that
|
||||
* the username will always contain the domain name.
|
||||
* <p>
|
||||
* The user authorities are obtained from the data contained in the {@code memberOf} attribute.
|
||||
*
|
||||
@@ -96,17 +97,11 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
private final String rootDn;
|
||||
private final String url;
|
||||
private boolean convertSubErrorCodesToExceptions;
|
||||
private String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))";
|
||||
|
||||
// Only used to allow tests to substitute a mock LdapContext
|
||||
ContextFactory contextFactory = new ContextFactory();
|
||||
|
||||
/**
|
||||
* @param domain the domain for which authentication should take place
|
||||
*/
|
||||
// public ActiveDirectoryLdapAuthenticationProvider(String domain) {
|
||||
// this (domain, null);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param domain the domain name (may be null or empty)
|
||||
* @param url an LDAP url (or multiple URLs)
|
||||
@@ -114,7 +109,6 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
public ActiveDirectoryLdapAuthenticationProvider(String domain, String url) {
|
||||
Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty");
|
||||
this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null;
|
||||
//this.url = StringUtils.hasText(url) ? url : null;
|
||||
this.url = url;
|
||||
rootDn = this.domain == null ? null : rootDnFromDomain(this.domain);
|
||||
}
|
||||
@@ -122,13 +116,12 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
@Override
|
||||
protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken auth) {
|
||||
String username = auth.getName();
|
||||
String password = (String)auth.getCredentials();
|
||||
String password = (String) auth.getCredentials();
|
||||
|
||||
DirContext ctx = bindAsUser(username, password);
|
||||
|
||||
try {
|
||||
return searchForUser(ctx, username);
|
||||
|
||||
} catch (NamingException e) {
|
||||
logger.error("Failed to locate directory entry for authenticated user: " + username, e);
|
||||
throw badCredentials(e);
|
||||
@@ -168,7 +161,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
// TODO. add DNS lookup based on domain
|
||||
final String bindUrl = url;
|
||||
|
||||
Hashtable<String,String> env = new Hashtable<String,String>();
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
String bindPrincipal = createBindPrincipal(username);
|
||||
env.put(Context.SECURITY_PRINCIPAL, bindPrincipal);
|
||||
@@ -189,25 +182,26 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
}
|
||||
}
|
||||
|
||||
void handleBindException(String bindPrincipal, NamingException exception) {
|
||||
private void handleBindException(String bindPrincipal, NamingException exception) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authentication for " + bindPrincipal + " failed:" + exception);
|
||||
}
|
||||
|
||||
int subErrorCode = parseSubErrorCode(exception.getMessage());
|
||||
|
||||
if (subErrorCode > 0) {
|
||||
logger.info("Active Directory authentication failed: " + subCodeToLogMessage(subErrorCode));
|
||||
|
||||
if (convertSubErrorCodesToExceptions) {
|
||||
raiseExceptionForErrorCode(subErrorCode, exception);
|
||||
}
|
||||
} else {
|
||||
if (subErrorCode <= 0) {
|
||||
logger.debug("Failed to locate AD-specific sub-error code in message");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Active Directory authentication failed: " + subCodeToLogMessage(subErrorCode));
|
||||
|
||||
if (convertSubErrorCodesToExceptions) {
|
||||
raiseExceptionForErrorCode(subErrorCode, exception);
|
||||
}
|
||||
}
|
||||
|
||||
int parseSubErrorCode(String message) {
|
||||
private int parseSubErrorCode(String message) {
|
||||
Matcher m = SUB_ERROR_CODE.matcher(message);
|
||||
|
||||
if (m.matches()) {
|
||||
@@ -217,7 +211,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
return -1;
|
||||
}
|
||||
|
||||
void raiseExceptionForErrorCode(int code, NamingException exception) {
|
||||
private void raiseExceptionForErrorCode(int code, NamingException exception) {
|
||||
String hexString = Integer.toHexString(code);
|
||||
Throwable cause = new ActiveDirectoryAuthenticationException(hexString, exception.getMessage(), exception);
|
||||
switch (code) {
|
||||
@@ -238,7 +232,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
}
|
||||
}
|
||||
|
||||
String subCodeToLogMessage(int code) {
|
||||
private String subCodeToLogMessage(int code) {
|
||||
switch (code) {
|
||||
case USERNAME_NOT_FOUND:
|
||||
return "User was not found in directory";
|
||||
@@ -270,28 +264,25 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
return (BadCredentialsException) badCredentials().initCause(cause);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private DirContextOperations searchForUser(DirContext ctx, String username) throws NamingException {
|
||||
SearchControls searchCtls = new SearchControls();
|
||||
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))";
|
||||
|
||||
final String bindPrincipal = createBindPrincipal(username);
|
||||
private DirContextOperations searchForUser(DirContext context, String username) throws NamingException {
|
||||
SearchControls searchControls = new SearchControls();
|
||||
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
String bindPrincipal = createBindPrincipal(username);
|
||||
String searchRoot = rootDn != null ? rootDn : searchRootFromPrincipal(bindPrincipal);
|
||||
|
||||
try {
|
||||
return SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, searchCtls, searchRoot, searchFilter,
|
||||
new Object[]{bindPrincipal});
|
||||
return SpringSecurityLdapTemplate.searchForSingleEntryInternal(context, searchControls,
|
||||
searchRoot, searchFilter, new Object[]{bindPrincipal});
|
||||
} catch (IncorrectResultSizeDataAccessException incorrectResults) {
|
||||
if (incorrectResults.getActualSize() == 0) {
|
||||
UsernameNotFoundException userNameNotFoundException = new UsernameNotFoundException("User " + username + " not found in directory.", username);
|
||||
userNameNotFoundException.initCause(incorrectResults);
|
||||
throw badCredentials(userNameNotFoundException);
|
||||
// Search should never return multiple results if properly configured - just rethrow
|
||||
if (incorrectResults.getActualSize() != 0) {
|
||||
throw incorrectResults;
|
||||
}
|
||||
// Search should never return multiple results if properly configured, so just rethrow
|
||||
throw incorrectResults;
|
||||
// If we found no results, then the username/password did not match
|
||||
UsernameNotFoundException userNameNotFoundException = new UsernameNotFoundException("User " + username
|
||||
+ " not found in directory.", incorrectResults);
|
||||
throw badCredentials(userNameNotFoundException);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +294,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
throw badCredentials();
|
||||
}
|
||||
|
||||
return rootDnFromDomain(bindPrincipal.substring(atChar+ 1, bindPrincipal.length()));
|
||||
return rootDnFromDomain(bindPrincipal.substring(atChar + 1, bindPrincipal.length()));
|
||||
}
|
||||
|
||||
private String rootDnFromDomain(String domain) {
|
||||
@@ -342,6 +333,22 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda
|
||||
this.convertSubErrorCodesToExceptions = convertSubErrorCodesToExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* The LDAP filter string to search for the user being authenticated.
|
||||
* Occurrences of {0} are replaced with the {@code username@domain}.
|
||||
* <p>
|
||||
* Defaults to: {@code (&(objectClass=user)(userPrincipalName={0}))}
|
||||
* </p>
|
||||
*
|
||||
* @param searchFilter the filter string
|
||||
*
|
||||
* @since 3.2.6
|
||||
*/
|
||||
public void setSearchFilter(String searchFilter) {
|
||||
Assert.hasText(searchFilter,"searchFilter must have text");
|
||||
this.searchFilter = searchFilter;
|
||||
}
|
||||
|
||||
static class ContextFactory {
|
||||
DirContext createContext(Hashtable<?,?> env) throws NamingException {
|
||||
return new InitialLdapContext(env, null);
|
||||
|
||||
@@ -127,7 +127,6 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life
|
||||
|
||||
server = new LdapServer();
|
||||
server.setDirectoryService(service);
|
||||
// AbstractLdapIntegrationTests assume IPv4, so we specify the same here
|
||||
server.setTransports(new TcpTransport(port));
|
||||
start();
|
||||
}
|
||||
|
||||
+7
-86
@@ -72,12 +72,12 @@ import java.util.Set;
|
||||
* The configuration below shows how the group search might be performed with the above schema.
|
||||
* <pre>
|
||||
* <bean id="ldapAuthoritiesPopulator"
|
||||
* class="org.springframework.security.authentication.ldap.populator.DefaultLdapAuthoritiesPopulator">
|
||||
* class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
|
||||
* <constructor-arg ref="contextSource"/>
|
||||
* <constructor-arg value="ou=groups"/>
|
||||
* <property name="groupRoleAttribute" value="ou"/>
|
||||
* <!-- the following properties are shown with their default values -->
|
||||
* <property name="searchSubTree" value="false"/>
|
||||
* <property name="searchSubtree" value="false"/>
|
||||
* <property name="rolePrefix" value="ROLE_"/>
|
||||
* <property name="convertToUpperCase" value="true"/>
|
||||
* </bean>
|
||||
@@ -92,7 +92,6 @@ import java.util.Set;
|
||||
* a search of the entire subtree under <tt>groupSearchBase</tt>.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Filip Hanik
|
||||
*/
|
||||
public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
@@ -106,9 +105,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
*/
|
||||
private GrantedAuthority defaultRole;
|
||||
|
||||
/**
|
||||
* Template that will be used for searching
|
||||
*/
|
||||
private final SpringSecurityLdapTemplate ldapTemplate;
|
||||
|
||||
/**
|
||||
@@ -131,13 +127,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
* The pattern to be used for the user search. {0} is the user's DN
|
||||
*/
|
||||
private String groupSearchFilter = "(member={0})";
|
||||
/**
|
||||
* The role prefix that will be prepended to each role name
|
||||
*/
|
||||
private String rolePrefix = "ROLE_";
|
||||
/**
|
||||
* Should we convert the role name to uppercase
|
||||
*/
|
||||
private boolean convertToUpperCase = true;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
@@ -153,7 +143,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
|
||||
Assert.notNull(contextSource, "contextSource must not be null");
|
||||
ldapTemplate = new SpringSecurityLdapTemplate(contextSource);
|
||||
getLdapTemplate().setSearchControls(getSearchControls());
|
||||
ldapTemplate.setSearchControls(searchControls);
|
||||
this.groupSearchBase = groupSearchBase;
|
||||
|
||||
if (groupSearchBase == null) {
|
||||
@@ -222,8 +212,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
+ groupSearchFilter + " in search base '" + getGroupSearchBase() + "'");
|
||||
}
|
||||
|
||||
Set<String> userRoles = getLdapTemplate().searchForSingleAttributeValues(getGroupSearchBase(), groupSearchFilter,
|
||||
new String[]{userDn, username}, groupRoleAttribute);
|
||||
Set<String> userRoles = ldapTemplate.searchForSingleAttributeValues(getGroupSearchBase(), groupSearchFilter,
|
||||
new String[]{userDn, username}, groupRoleAttribute);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Roles from search: " + userRoles);
|
||||
@@ -242,7 +232,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
}
|
||||
|
||||
protected ContextSource getContextSource() {
|
||||
return getLdapTemplate().getContextSource();
|
||||
return ldapTemplate.getContextSource();
|
||||
}
|
||||
|
||||
protected String getGroupSearchBase() {
|
||||
@@ -307,75 +297,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
|
||||
* @see LdapTemplate#setIgnoreNameNotFoundException(boolean)
|
||||
*/
|
||||
public void setIgnorePartialResultException(boolean ignore) {
|
||||
getLdapTemplate().setIgnorePartialResultException(ignore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current LDAP template.
|
||||
* Method available so that classes extending this can override the template used
|
||||
* @return the LDAP template
|
||||
* @see {@link org.springframework.security.ldap.SpringSecurityLdapTemplate}
|
||||
*/
|
||||
protected SpringSecurityLdapTemplate getLdapTemplate() {
|
||||
return ldapTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute name of the LDAP attribute that will be mapped to the role name
|
||||
* Method available so that classes extending this can override
|
||||
* @return the attribute name used for role mapping
|
||||
* @see {@link #setGroupRoleAttribute(String)}
|
||||
*/
|
||||
protected final String getGroupRoleAttribute() {
|
||||
return groupRoleAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search filter configured for this populator
|
||||
* Method available so that classes extending this can override
|
||||
* @return the search filter
|
||||
* @see {@link #setGroupSearchFilter(String)}
|
||||
*/
|
||||
protected final String getGroupSearchFilter() {
|
||||
return groupSearchFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the role prefix used by this populator
|
||||
* Method available so that classes extending this can override
|
||||
* @return the role prefix
|
||||
* @see {@link #setRolePrefix(String)}
|
||||
*/
|
||||
protected final String getRolePrefix() {
|
||||
return rolePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if role names are converted to uppercase
|
||||
* Method available so that classes extending this can override
|
||||
* @return true if role names are converted to uppercase.
|
||||
* @see {@link #setConvertToUpperCase(boolean)}
|
||||
*/
|
||||
protected final boolean isConvertToUpperCase() {
|
||||
return convertToUpperCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default role
|
||||
* Method available so that classes extending this can override
|
||||
* @return the default role used
|
||||
* @see {@link #setDefaultRole(String)}
|
||||
*/
|
||||
private GrantedAuthority getDefaultRole() {
|
||||
return defaultRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search controls
|
||||
* Method available so that classes extending this can override the search controls used
|
||||
* @return the search controls
|
||||
*/
|
||||
private SearchControls getSearchControls() {
|
||||
return searchControls;
|
||||
ldapTemplate.setIgnorePartialResultException(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.ldap.userdetails;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An authority that contains at least a DN and a role name for an LDAP entry but can also contain other desired
|
||||
* attributes to be fetched during an LDAP authority search.
|
||||
*
|
||||
* @author Filip Hanik
|
||||
*/
|
||||
public class LdapAuthority implements GrantedAuthority {
|
||||
|
||||
|
||||
private String dn;
|
||||
private String role;
|
||||
private Map<String, List<String>> attributes;
|
||||
|
||||
/**
|
||||
* Constructs an LdapAuthority that has a role and a DN but no other attributes
|
||||
*
|
||||
* @param role
|
||||
* @param dn
|
||||
*/
|
||||
public LdapAuthority(String role, String dn) {
|
||||
this(role, dn, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an LdapAuthority with the given role, DN and other LDAP attributes
|
||||
*
|
||||
* @param role
|
||||
* @param dn
|
||||
* @param attributes
|
||||
*/
|
||||
public LdapAuthority(String role, String dn, Map<String, List<String>> attributes) {
|
||||
Assert.notNull(role, "role can not be null");
|
||||
Assert.notNull(dn, "dn can not be null");
|
||||
|
||||
this.role = role;
|
||||
this.dn = dn;
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LDAP attributes
|
||||
*
|
||||
* @return the LDAP attributes, map can be null
|
||||
*/
|
||||
public Map<String, List<String>> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DN for this LDAP authority
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDn() {
|
||||
return dn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values for a specific attribute
|
||||
*
|
||||
* @param name the attribute name
|
||||
* @return a String array, never null but may be zero length
|
||||
*/
|
||||
public List<String> getAttributeValues(String name) {
|
||||
List<String> result = null;
|
||||
if (attributes != null) {
|
||||
result = attributes.get(name);
|
||||
}
|
||||
if (result == null) {
|
||||
result = Collections.emptyList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first attribute value for a specified attribute
|
||||
*
|
||||
* @param name
|
||||
* @return the first attribute value for a specified attribute, may be null
|
||||
*/
|
||||
public String getFirstAttributeValue(String name) {
|
||||
List<String> result = getAttributeValues(name);
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return result.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getAuthority() {
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the LdapAuthority based on {@link #getAuthority()} and {@link #getDn()} values {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof LdapAuthority)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LdapAuthority that = (LdapAuthority) o;
|
||||
|
||||
if (!dn.equals(that.dn)) {
|
||||
return false;
|
||||
}
|
||||
return role.equals(that.role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = dn.hashCode();
|
||||
result = 31 * result + (role != null ? role.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LdapAuthority{" +
|
||||
"dn='" + dn + '\'' +
|
||||
", role='" + role + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
-258
@@ -1,258 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.ldap.userdetails;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.ldap.core.ContextSource;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A LDAP authority populator that can recursively search static nested groups. <p>An example of nested groups can be
|
||||
* <pre>
|
||||
* #Nested groups data
|
||||
*
|
||||
* dn: uid=javadude,ou=people,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: person
|
||||
* objectclass: organizationalPerson
|
||||
* objectclass: inetOrgPerson
|
||||
* cn: Java Dude
|
||||
* sn: Dude
|
||||
* uid: javadude
|
||||
* userPassword: javadudespassword
|
||||
*
|
||||
* dn: uid=groovydude,ou=people,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: person
|
||||
* objectclass: organizationalPerson
|
||||
* objectclass: inetOrgPerson
|
||||
* cn: Groovy Dude
|
||||
* sn: Dude
|
||||
* uid: groovydude
|
||||
* userPassword: groovydudespassword
|
||||
*
|
||||
* dn: uid=closuredude,ou=people,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: person
|
||||
* objectclass: organizationalPerson
|
||||
* objectclass: inetOrgPerson
|
||||
* cn: Closure Dude
|
||||
* sn: Dude
|
||||
* uid: closuredude
|
||||
* userPassword: closuredudespassword
|
||||
*
|
||||
* dn: uid=scaladude,ou=people,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: person
|
||||
* objectclass: organizationalPerson
|
||||
* objectclass: inetOrgPerson
|
||||
* cn: Scala Dude
|
||||
* sn: Dude
|
||||
* uid: scaladude
|
||||
* userPassword: scaladudespassword
|
||||
*
|
||||
* dn: cn=j-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: groupOfNames
|
||||
* cn: j-developers
|
||||
* ou: jdeveloper
|
||||
* member: cn=java-developers,ou=groups,dc=springframework,dc=org
|
||||
*
|
||||
* dn: cn=java-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: groupOfNames
|
||||
* cn: java-developers
|
||||
* ou: jdeveloper
|
||||
* member: cn=groovy-developers,ou=groups,dc=springframework,dc=org
|
||||
* member: cn=scala-developers,ou=groups,dc=springframework,dc=org
|
||||
* member: uid=javadude,ou=people,dc=springframework,dc=org
|
||||
*
|
||||
* dn: cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: groupOfNames
|
||||
* cn: java-developers
|
||||
* ou: jdeveloper
|
||||
* member: cn=closure-developers,ou=groups,dc=springframework,dc=org
|
||||
* member: uid=groovydude,ou=people,dc=springframework,dc=org
|
||||
*
|
||||
* dn: cn=closure-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: groupOfNames
|
||||
* cn: java-developers
|
||||
* ou: jdeveloper
|
||||
* member: uid=closuredude,ou=people,dc=springframework,dc=org
|
||||
*
|
||||
* dn: cn=scala-developers,ou=jdeveloper,dc=springframework,dc=org
|
||||
* objectclass: top
|
||||
* objectclass: groupOfNames
|
||||
* cn: java-developers
|
||||
* ou: jdeveloper
|
||||
* member: uid=scaladude,ou=people,dc=springframework,dc=org * </pre>
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @author Filip Hanik
|
||||
*/
|
||||
|
||||
public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator {
|
||||
private static final Log logger = LogFactory.getLog(NestedLdapAuthoritiesPopulator.class);
|
||||
|
||||
/**
|
||||
* The attribute names to retrieve for each LDAP group
|
||||
*/
|
||||
private Set<String> attributeNames;
|
||||
|
||||
/**
|
||||
* Maximum search depth - represents the number of recursive searches performed
|
||||
*/
|
||||
private int maxSearchDepth = 10;
|
||||
|
||||
/**
|
||||
* Constructor for group search scenarios. <tt>userRoleAttributes</tt> may still be set as a property.
|
||||
*
|
||||
* @param contextSource supplies the contexts used to search for user roles.
|
||||
* @param groupSearchBase if this is an empty string the search will be performed from the root DN of the
|
||||
*/
|
||||
public NestedLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
|
||||
super(contextSource, groupSearchBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String username) {
|
||||
if (getGroupSearchBase() == null) {
|
||||
return new HashSet<GrantedAuthority>();
|
||||
}
|
||||
|
||||
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
|
||||
|
||||
performNestedSearch(userDn, username, authorities, getMaxSearchDepth());
|
||||
|
||||
return authorities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the nested group search
|
||||
*
|
||||
* @param userDn - the userDN to search for, will become the group DN for subsequent searches
|
||||
* @param username - the username of the user
|
||||
* @param authorities - the authorities set that will be populated, must not be null
|
||||
* @param depth - the depth remaining, when 0 recursion will end
|
||||
*/
|
||||
private void performNestedSearch(String userDn, String username, Set<GrantedAuthority> authorities, int depth) {
|
||||
if (depth == 0) {
|
||||
//back out of recursion
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Search aborted, max depth reached," +
|
||||
" for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter "
|
||||
+ getGroupSearchFilter() + " in search base '" + getGroupSearchBase() + "'");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter "
|
||||
+ getGroupSearchFilter() + " in search base '" + getGroupSearchBase() + "'");
|
||||
}
|
||||
|
||||
if (getAttributeNames() == null) {
|
||||
setAttributeNames(new HashSet<String>());
|
||||
}
|
||||
if (StringUtils.hasText(getGroupRoleAttribute()) && !getAttributeNames().contains(getGroupRoleAttribute())) {
|
||||
getAttributeNames().add(getGroupRoleAttribute());
|
||||
}
|
||||
|
||||
Set<Map<String, List<String>>> userRoles = getLdapTemplate().searchForMultipleAttributeValues(
|
||||
getGroupSearchBase(),
|
||||
getGroupSearchFilter(),
|
||||
new String[]{userDn, username},
|
||||
getAttributeNames().toArray(new String[getAttributeNames().size()]));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Roles from search: " + userRoles);
|
||||
}
|
||||
|
||||
for (Map<String, List<String>> record : userRoles) {
|
||||
boolean circular = false;
|
||||
String dn = record.get(SpringSecurityLdapTemplate.DN_KEY).get(0);
|
||||
List<String> roleValues = record.get(getGroupRoleAttribute());
|
||||
Set<String> roles = new HashSet<String>();
|
||||
if(roleValues != null) {
|
||||
roles.addAll(roleValues);
|
||||
}
|
||||
for (String role : roles) {
|
||||
if (isConvertToUpperCase()) {
|
||||
role = role.toUpperCase();
|
||||
}
|
||||
role = getRolePrefix() + role;
|
||||
//if the group already exist, we will not search for it's parents again.
|
||||
//this prevents a forever loop for a misconfigured ldap directory
|
||||
circular = circular | (!authorities.add(new LdapAuthority(role, dn, record)));
|
||||
}
|
||||
String roleName = roles.size() > 0 ? roles.iterator().next() : dn;
|
||||
if (!circular) {
|
||||
performNestedSearch(dn, roleName, authorities, (depth - 1));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute names that this populator has been configured to retrieve Value can be null, represents
|
||||
* fetch all attributes
|
||||
*
|
||||
* @return the attribute names or null for all
|
||||
*/
|
||||
private Set<String> getAttributeNames() {
|
||||
return attributeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute names to retrieve for each ldap groups. Null means retrieve all
|
||||
*
|
||||
* @param attributeNames - the names of the LDAP attributes to retrieve
|
||||
*/
|
||||
public void setAttributeNames(Set<String> attributeNames) {
|
||||
this.attributeNames = attributeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* How far should a nested search go. Depth is calculated in the number of levels we search up for parent groups.
|
||||
*
|
||||
* @return the max search depth, default is 10
|
||||
*/
|
||||
private int getMaxSearchDepth() {
|
||||
return maxSearchDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* How far should a nested search go. Depth is calculated in the number of levels we search up for parent groups.
|
||||
*
|
||||
* @param maxSearchDepth the max search depth
|
||||
*/
|
||||
public void setMaxSearchDepth(int maxSearchDepth) {
|
||||
this.maxSearchDepth = maxSearchDepth;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user