Compare commits
128 Commits
5.6.3
...
3.2.7.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 644392045a | |||
| 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 |
+1
-2
@@ -18,5 +18,4 @@ build/
|
||||
*.ipr
|
||||
*.iws
|
||||
.gradle/
|
||||
atlassian-ide-plugin.xml
|
||||
/samples
|
||||
atlassian-ide-plugin.xml
|
||||
+1
-1
@@ -16,7 +16,7 @@ Is there already an issue that addresses your concern? Do a bit of searching in
|
||||
If you're considering anything more than correcting a typo or fixing a minor bug , please discuss it on the [Spring Security forums](http://forum.springsource.org/forumdisplay.php?33-Security) before submitting a pull request. We're happy to provide guidance but please spend an hour or two researching the subject on your own including searching the forums for prior discussions.
|
||||
|
||||
# Sign the Contributor License Agreement
|
||||
If you have not previously done so, please fill out and submit the SpringSource CLA form. You'll receive a token when this process is complete. Keep track of this, you may be asked for it later!
|
||||
If you have not previously done so, please fill out and submit the [SpringSource CLA form](https://support.springsource.com/spring_committer_signup). You'll receive a token when this process is complete. Keep track of this, you may be asked for it later!
|
||||
|
||||
* For **Project** select _Spring Security_
|
||||
* For **Project Lead** enter _Rob Winch_
|
||||
|
||||
+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
-1
@@ -2,13 +2,14 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
'aopalliance:aopalliance:1.0',
|
||||
"org.springframework:spring-aop:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion"
|
||||
|
||||
optional "net.sf.ehcache:ehcache:$ehcacheVersion"
|
||||
optional "net.sf.ehcache:ehcache-core:$ehcacheVersion"
|
||||
|
||||
testCompile "org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context-support:$springVersion",
|
||||
|
||||
+13
-19
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.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-snasphot</id>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.8.RELEASE</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>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -106,8 +100,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -120,7 +114,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,19 +144,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
-- drop table acl_class;
|
||||
-- drop table acl_sid;
|
||||
|
||||
|
||||
create table acl_sid(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
principal boolean not null,
|
||||
sid varchar_ignorecase(100) not null,
|
||||
constraint unique_uk_1 unique(sid,principal));
|
||||
constraint unique_uk_1 unique(sid,principal)
|
||||
);
|
||||
|
||||
create table acl_class(
|
||||
id bigint generated by default as identity(start with 100) not null primary key,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
-- ACL Schema SQL for MySQL 5.5+ / MariaDB equivalent
|
||||
|
||||
-- drop table acl_entry;
|
||||
-- drop table acl_object_identity;
|
||||
-- drop table acl_class;
|
||||
-- drop table acl_sid;
|
||||
|
||||
CREATE TABLE acl_sid (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
principal BOOLEAN NOT NULL,
|
||||
sid VARCHAR(100) NOT NULL,
|
||||
UNIQUE KEY unique_acl_sid (sid, principal)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE acl_class (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
class VARCHAR(100) NOT NULL,
|
||||
UNIQUE KEY uk_acl_class (class)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE acl_object_identity (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
object_id_class BIGINT UNSIGNED NOT NULL,
|
||||
object_id_identity BIGINT NOT NULL,
|
||||
parent_object BIGINT UNSIGNED,
|
||||
owner_sid BIGINT UNSIGNED,
|
||||
entries_inheriting BOOLEAN NOT NULL,
|
||||
UNIQUE KEY uk_acl_object_identity (object_id_class, object_id_identity),
|
||||
CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id),
|
||||
CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
|
||||
CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE acl_entry (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
acl_object_identity BIGINT UNSIGNED NOT NULL,
|
||||
ace_order INTEGER NOT NULL,
|
||||
sid BIGINT UNSIGNED NOT NULL,
|
||||
mask INTEGER UNSIGNED NOT NULL,
|
||||
granting BOOLEAN NOT NULL,
|
||||
audit_success BOOLEAN NOT NULL,
|
||||
audit_failure BOOLEAN NOT NULL,
|
||||
UNIQUE KEY unique_acl_entry (acl_object_identity, ace_order),
|
||||
CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
|
||||
CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
|
||||
) ENGINE=InnoDB;
|
||||
@@ -0,0 +1,82 @@
|
||||
-- ACL Schema SQL for Oracle Database 10g+
|
||||
|
||||
-- drop trigger acl_sid_id_trigger;
|
||||
-- drop trigger acl_class_id_trigger;
|
||||
-- drop trigger acl_object_identity_id_trigger;
|
||||
-- drop trigger acl_entry_id_trigger;
|
||||
-- drop sequence acl_sid_sequence;
|
||||
-- drop sequence acl_class_sequence;
|
||||
-- drop sequence acl_object_identity_sequence;
|
||||
-- drop sequence acl_entry_sequence;
|
||||
-- drop table acl_entry;
|
||||
-- drop table acl_object_identity;
|
||||
-- drop table acl_class;
|
||||
-- drop table acl_sid;
|
||||
|
||||
CREATE TABLE acl_sid (
|
||||
id NUMBER(38) NOT NULL PRIMARY KEY,
|
||||
principal NUMBER(1) NOT NULL CHECK (principal in (0, 1)),
|
||||
sid NVARCHAR2(100) NOT NULL,
|
||||
CONSTRAINT unique_acl_sid UNIQUE (sid, principal)
|
||||
);
|
||||
CREATE SEQUENCE acl_sid_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
|
||||
CREATE OR REPLACE TRIGGER acl_sid_id_trigger
|
||||
BEFORE INSERT ON acl_sid
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT acl_sid_sequence.nextval INTO :new.id FROM dual;
|
||||
END;
|
||||
|
||||
CREATE TABLE acl_class (
|
||||
id NUMBER(38) NOT NULL PRIMARY KEY,
|
||||
class NVARCHAR2(100) NOT NULL,
|
||||
CONSTRAINT uk_acl_class UNIQUE (class)
|
||||
);
|
||||
CREATE SEQUENCE acl_class_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
|
||||
CREATE OR REPLACE TRIGGER acl_class_id_trigger
|
||||
BEFORE INSERT ON acl_class
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT acl_class_sequence.nextval INTO :new.id FROM dual;
|
||||
END;
|
||||
|
||||
CREATE TABLE acl_object_identity (
|
||||
id NUMBER(38) NOT NULL PRIMARY KEY,
|
||||
object_id_class NUMBER(38) NOT NULL,
|
||||
object_id_identity NUMBER(38) NOT NULL,
|
||||
parent_object NUMBER(38),
|
||||
owner_sid NUMBER(38),
|
||||
entries_inheriting NUMBER(1) NOT NULL CHECK (entries_inheriting in (0, 1)),
|
||||
CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity),
|
||||
CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id),
|
||||
CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
|
||||
CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
|
||||
);
|
||||
CREATE SEQUENCE acl_object_identity_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
|
||||
CREATE OR REPLACE TRIGGER acl_object_identity_id_trigger
|
||||
BEFORE INSERT ON acl_object_identity
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT acl_object_identity_sequence.nextval INTO :new.id FROM dual;
|
||||
END;
|
||||
|
||||
CREATE TABLE acl_entry (
|
||||
id NUMBER(38) NOT NULL PRIMARY KEY,
|
||||
acl_object_identity NUMBER(38) NOT NULL,
|
||||
ace_order INTEGER NOT NULL,
|
||||
sid NUMBER(38) NOT NULL,
|
||||
mask INTEGER NOT NULL,
|
||||
granting NUMBER(1) NOT NULL CHECK (granting in (0, 1)),
|
||||
audit_success NUMBER(1) NOT NULL CHECK (audit_success in (0, 1)),
|
||||
audit_failure NUMBER(1) NOT NULL CHECK (audit_failure in (0, 1)),
|
||||
CONSTRAINT unique_acl_entry UNIQUE (acl_object_identity, ace_order),
|
||||
CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
|
||||
CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
|
||||
);
|
||||
CREATE SEQUENCE acl_entry_sequence START WITH 1 INCREMENT BY 1 NOMAXVALUE;
|
||||
CREATE OR REPLACE TRIGGER acl_entry_id_trigger
|
||||
BEFORE INSERT ON acl_entry
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
SELECT acl_entry_sequence.nextval INTO :new.id FROM dual;
|
||||
END;
|
||||
@@ -0,0 +1,46 @@
|
||||
-- ACL Schema SQL for Microsoft SQL Server 2008+
|
||||
|
||||
-- drop table acl_entry;
|
||||
-- drop table acl_object_identity;
|
||||
-- drop table acl_class;
|
||||
-- drop table acl_sid;
|
||||
|
||||
CREATE TABLE acl_sid (
|
||||
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
|
||||
principal BIT NOT NULL,
|
||||
sid VARCHAR(100) NOT NULL,
|
||||
CONSTRAINT unique_acl_sid UNIQUE (sid, principal)
|
||||
);
|
||||
|
||||
CREATE TABLE acl_class (
|
||||
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
|
||||
class VARCHAR(100) NOT NULL,
|
||||
CONSTRAINT uk_acl_class UNIQUE (class)
|
||||
);
|
||||
|
||||
CREATE TABLE acl_object_identity (
|
||||
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
|
||||
object_id_class BIGINT NOT NULL,
|
||||
object_id_identity BIGINT NOT NULL,
|
||||
parent_object BIGINT,
|
||||
owner_sid BIGINT,
|
||||
entries_inheriting BIT NOT NULL,
|
||||
CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity),
|
||||
CONSTRAINT fk_acl_object_identity_parent FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id),
|
||||
CONSTRAINT fk_acl_object_identity_class FOREIGN KEY (object_id_class) REFERENCES acl_class (id),
|
||||
CONSTRAINT fk_acl_object_identity_owner FOREIGN KEY (owner_sid) REFERENCES acl_sid (id)
|
||||
);
|
||||
|
||||
CREATE TABLE acl_entry (
|
||||
id BIGINT NOT NULL IDENTITY PRIMARY KEY,
|
||||
acl_object_identity BIGINT NOT NULL,
|
||||
ace_order INTEGER NOT NULL,
|
||||
sid BIGINT NOT NULL,
|
||||
mask INTEGER NOT NULL,
|
||||
granting BIT NOT NULL,
|
||||
audit_success BIT NOT NULL,
|
||||
audit_failure BIT NOT NULL,
|
||||
CONSTRAINT unique_acl_entry UNIQUE (acl_object_identity, ace_order),
|
||||
CONSTRAINT fk_acl_entry_object FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity (id),
|
||||
CONSTRAINT fk_acl_entry_acl FOREIGN KEY (sid) REFERENCES acl_sid (id)
|
||||
);
|
||||
+130
-123
@@ -1,11 +1,28 @@
|
||||
package org.springframework.security.acls.jdbc;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.fest.assertions.Assertions.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.junit.*;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||
import org.springframework.security.acls.domain.AclImpl;
|
||||
@@ -19,50 +36,43 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
* Tests {@link EhCacheBasedAclCache}
|
||||
*
|
||||
* @author Andrei Stefan
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class EhCacheBasedAclCacheTests {
|
||||
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
|
||||
|
||||
private static CacheManager cacheManager;
|
||||
@Mock
|
||||
private Ehcache cache;
|
||||
@Captor
|
||||
private ArgumentCaptor<Element> element;
|
||||
|
||||
@BeforeClass
|
||||
public static void initCacheManaer() {
|
||||
cacheManager = CacheManager.create();
|
||||
// Use disk caching immediately (to test for serialization issue reported in SEC-527)
|
||||
cacheManager.addCache(new Cache("ehcachebasedacltests", 0, true, false, 600, 300));
|
||||
}
|
||||
private EhCacheBasedAclCache myCache;
|
||||
|
||||
@AfterClass
|
||||
public static void shutdownCacheManager() {
|
||||
cacheManager.removalAll();
|
||||
cacheManager.shutdown();
|
||||
private MutableAcl acl;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
myCache = new EhCacheBasedAclCache(cache);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
|
||||
acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearContext() {
|
||||
public void cleanup() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
private Ehcache getCache() {
|
||||
Ehcache cache = cacheManager.getCache("ehcachebasedacltests");
|
||||
cache.removeAll();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void constructorRejectsNullParameters() throws Exception {
|
||||
new EhCacheBasedAclCache(null);
|
||||
@@ -70,9 +80,6 @@ public class EhCacheBasedAclCacheTests {
|
||||
|
||||
@Test
|
||||
public void methodsRejectNullParameters() throws Exception {
|
||||
Ehcache cache = new MockEhcache();
|
||||
EhCacheBasedAclCache myCache = new EhCacheBasedAclCache(cache);
|
||||
|
||||
try {
|
||||
Serializable id = null;
|
||||
myCache.evictFromCache(id);
|
||||
@@ -122,12 +129,6 @@ public class EhCacheBasedAclCacheTests {
|
||||
// SEC-527
|
||||
@Test
|
||||
public void testDiskSerializationOfMutableAclObjectInstance() throws Exception {
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
// Serialization test
|
||||
File file = File.createTempFile("SEC_TEST", ".object");
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
@@ -150,111 +151,117 @@ public class EhCacheBasedAclCacheTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheOperationsAclWithoutParent() throws Exception {
|
||||
Ehcache cache = getCache();
|
||||
EhCacheBasedAclCache myCache = new EhCacheBasedAclCache(cache);
|
||||
public void clearCache() throws Exception {
|
||||
myCache.clearCache();
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(100));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
assertEquals(0, cache.getDiskStoreSize());
|
||||
myCache.putInCache(acl);
|
||||
assertEquals(cache.getSize(), 2);
|
||||
assertEquals(2, cache.getDiskStoreSize());
|
||||
assertTrue(cache.isElementOnDisk(acl.getObjectIdentity()));
|
||||
assertFalse(cache.isElementInMemory(acl.getObjectIdentity()));
|
||||
|
||||
// Check we can get from cache the same objects we put in
|
||||
assertEquals(myCache.getFromCache(Long.valueOf(1)), acl);
|
||||
assertEquals(myCache.getFromCache(identity), acl);
|
||||
|
||||
// Put another object in cache
|
||||
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(101));
|
||||
MutableAcl acl2 = new AclImpl(identity2, Long.valueOf(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
myCache.putInCache(acl2);
|
||||
assertEquals(cache.getSize(), 4);
|
||||
assertEquals(4, cache.getDiskStoreSize());
|
||||
|
||||
// Try to evict an entry that doesn't exist
|
||||
myCache.evictFromCache(Long.valueOf(3));
|
||||
myCache.evictFromCache(new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(102)));
|
||||
assertEquals(cache.getSize(), 4);
|
||||
assertEquals(4, cache.getDiskStoreSize());
|
||||
|
||||
myCache.evictFromCache(Long.valueOf(1));
|
||||
assertEquals(cache.getSize(), 2);
|
||||
assertEquals(2, cache.getDiskStoreSize());
|
||||
|
||||
// Check the second object inserted
|
||||
assertEquals(myCache.getFromCache(Long.valueOf(2)), acl2);
|
||||
assertEquals(myCache.getFromCache(identity2), acl2);
|
||||
|
||||
myCache.evictFromCache(identity2);
|
||||
assertEquals(cache.getSize(), 0);
|
||||
verify(cache).removeAll();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void cacheOperationsAclWithParent() throws Exception {
|
||||
Ehcache cache = getCache();
|
||||
EhCacheBasedAclCache myCache = new EhCacheBasedAclCache(cache);
|
||||
public void putInCache() throws Exception {
|
||||
myCache.putInCache(acl);
|
||||
|
||||
verify(cache, times(2)).put(element.capture());
|
||||
assertThat(element.getValue().getKey()).isEqualTo(acl.getId());
|
||||
assertThat(element.getValue().getObjectValue()).isEqualTo(acl);
|
||||
assertThat(element.getAllValues().get(0).getKey()).isEqualTo(acl.getObjectIdentity());
|
||||
assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putInCacheAclWithParent() throws Exception {
|
||||
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(1));
|
||||
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, Long.valueOf(2));
|
||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||
new SimpleGrantedAuthority("ROLE_GENERAL"));
|
||||
MutableAcl acl = new AclImpl(identity, Long.valueOf(1), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
MutableAcl parentAcl = new AclImpl(identityParent, Long.valueOf(2), aclAuthorizationStrategy, new ConsoleAuditLogger());
|
||||
|
||||
acl.setParent(parentAcl);
|
||||
|
||||
assertEquals(0, cache.getDiskStoreSize());
|
||||
myCache.putInCache(acl);
|
||||
assertEquals(cache.getSize(), 4);
|
||||
assertEquals(4, cache.getDiskStoreSize());
|
||||
assertTrue(cache.isElementOnDisk(acl.getObjectIdentity()));
|
||||
assertTrue(cache.isElementOnDisk(Long.valueOf(1)));
|
||||
assertFalse(cache.isElementInMemory(acl.getObjectIdentity()));
|
||||
assertFalse(cache.isElementInMemory(Long.valueOf(1)));
|
||||
cache.flush();
|
||||
// Wait for the spool to be written to disk (it's asynchronous)
|
||||
Map spool = (Map) FieldUtils.getFieldValue(cache, "diskStore.spool");
|
||||
|
||||
while(spool.size() > 0) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
verify(cache, times(4)).put(element.capture());
|
||||
|
||||
// Check we can get from cache the same objects we put in
|
||||
AclImpl aclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(1));
|
||||
// For the checks on transient fields, we need to be sure that the object is being loaded from the cache,
|
||||
// not from the ehcache spool or elsewhere...
|
||||
assertFalse(acl == aclFromCache);
|
||||
assertEquals(acl, aclFromCache);
|
||||
// SEC-951 check transient fields are set on parent
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "aclAuthorizationStrategy"));
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "permissionGrantingStrategy"));
|
||||
assertEquals(acl, myCache.getFromCache(identity));
|
||||
assertNotNull(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy"));
|
||||
AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(Long.valueOf(2));
|
||||
assertEquals(parentAcl, parentAclFromCache);
|
||||
assertNotNull(FieldUtils.getFieldValue(parentAclFromCache, "aclAuthorizationStrategy"));
|
||||
assertEquals(parentAcl, myCache.getFromCache(identityParent));
|
||||
List<Element> allValues = element.getAllValues();
|
||||
|
||||
assertThat(allValues.get(0).getKey()).isEqualTo(parentAcl.getObjectIdentity());
|
||||
assertThat(allValues.get(0).getObjectValue()).isEqualTo(parentAcl);
|
||||
|
||||
assertThat(allValues.get(1).getKey()).isEqualTo(parentAcl.getId());
|
||||
assertThat(allValues.get(1).getObjectValue()).isEqualTo(parentAcl);
|
||||
|
||||
|
||||
assertThat(allValues.get(2).getKey()).isEqualTo(acl.getObjectIdentity());
|
||||
assertThat(allValues.get(2).getObjectValue()).isEqualTo(acl);
|
||||
|
||||
assertThat(allValues.get(3).getKey()).isEqualTo(acl.getId());
|
||||
assertThat(allValues.get(3).getObjectValue()).isEqualTo(acl);
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
@Test
|
||||
public void getFromCacheSerializable() throws Exception {
|
||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl));
|
||||
|
||||
private class MockEhcache extends Cache {
|
||||
public MockEhcache() {
|
||||
super("cache", 0, true, true, 0, 0);
|
||||
}
|
||||
assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFromCacheSerializablePopulatesTransient() throws Exception {
|
||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl));
|
||||
|
||||
myCache.putInCache(acl);
|
||||
|
||||
ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null);
|
||||
ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null);
|
||||
|
||||
MutableAcl fromCache = myCache.getFromCache(acl.getId());
|
||||
|
||||
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFromCacheObjectIdentity() throws Exception {
|
||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl));
|
||||
|
||||
assertThat(myCache.getFromCache(acl.getId())).isEqualTo(acl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFromCacheObjectIdentityPopulatesTransient() throws Exception {
|
||||
when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(),acl));
|
||||
|
||||
myCache.putInCache(acl);
|
||||
|
||||
ReflectionTestUtils.setField(acl, "permissionGrantingStrategy", null);
|
||||
ReflectionTestUtils.setField(acl, "aclAuthorizationStrategy", null);
|
||||
|
||||
MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity());
|
||||
|
||||
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull();
|
||||
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictCacheSerializable() throws Exception {
|
||||
when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(),acl));
|
||||
|
||||
myCache.evictFromCache(acl.getObjectIdentity());
|
||||
|
||||
verify(cache).remove(acl.getId());
|
||||
verify(cache).remove(acl.getObjectIdentity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictCacheObjectIdentity() throws Exception {
|
||||
when(cache.get(acl.getId())).thenReturn(new Element(acl.getId(),acl));
|
||||
|
||||
myCache.evictFromCache(acl.getId());
|
||||
|
||||
verify(cache).remove(acl.getId());
|
||||
verify(cache).remove(acl.getObjectIdentity());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-security-core'),
|
||||
springCoreDependency,
|
||||
"org.springframework:spring-beans:$springVersion",
|
||||
"org.springframework:spring-context:$springVersion"
|
||||
|
||||
|
||||
+8
-14
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.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-snasphot</id>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -108,7 +102,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -132,13 +126,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+12
-33
@@ -2,12 +2,13 @@ import groovy.text.SimpleTemplateEngine
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.5")
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.6")
|
||||
classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2")
|
||||
classpath("org.gradle.api.plugins:gradle-tomcat-plugin:0.9.8")
|
||||
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')
|
||||
classpath('org.asciidoctor:asciidoctor-gradle-plugin:0.7.0')
|
||||
classpath('org.asciidoctor:asciidoctor-java-integration:0.1.4.preview.1')
|
||||
@@ -25,8 +26,8 @@ allprojects {
|
||||
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.springVersion = '3.2.8.RELEASE'
|
||||
ext.spring4Version = '4.0.2.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'
|
||||
|
||||
@@ -61,7 +62,7 @@ ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && pr
|
||||
ext.sampleProjects = subprojects.findAll { project -> project.name.startsWith('spring-security-samples') }
|
||||
ext.itestProjects = subprojects.findAll { project -> project.name.startsWith('itest') }
|
||||
ext.coreModuleProjects = javaProjects - sampleProjects - itestProjects
|
||||
ext.aspectjProjects = [project(':spring-security-aspects'), project(':spring-security-samples-aspectj-xml')]
|
||||
ext.aspectjProjects = [project(':spring-security-aspects'), project(':spring-security-samples-aspectj-xml'), project(':spring-security-samples-aspectj-jc')]
|
||||
|
||||
configure(allprojects - javaProjects) {
|
||||
task afterEclipseImport {
|
||||
@@ -100,6 +101,9 @@ configure(javaProjects) {
|
||||
configure(coreModuleProjects) {
|
||||
apply plugin: 'bundlor'
|
||||
apply plugin: 'emma'
|
||||
apply plugin: 'spring-io'
|
||||
|
||||
ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : 'latest.integration'
|
||||
|
||||
bundlor.doFirst {
|
||||
def templateText = file("template.mf").text
|
||||
@@ -107,27 +111,10 @@ configure(coreModuleProjects) {
|
||||
}
|
||||
configurations {
|
||||
jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo
|
||||
spring4TestRuntime.extendsFrom testRuntime
|
||||
}
|
||||
configurations.spring4TestRuntime {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.springframework') {
|
||||
details.useVersion spring4Version
|
||||
}
|
||||
if (details.requested.name == 'ehcache') {
|
||||
details.useVersion '2.6.5'
|
||||
}
|
||||
if (details.requested.name == 'ehcache-terracotta') {
|
||||
details.useVersion '2.1.1'
|
||||
}
|
||||
if (details.requested.group == 'org.springframework.ldap') {
|
||||
details.useVersion springLdap2Version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
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}.*"
|
||||
@@ -135,14 +122,6 @@ configure(coreModuleProjects) {
|
||||
integrationTest {
|
||||
jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=${project.group}.*"
|
||||
}
|
||||
task spring4Test(type: Test) {
|
||||
jvmArgs = ['-ea', '-Xmx500m', '-XX:MaxPermSize=128M']
|
||||
exclude "**/EhCacheBasedAclCacheTests.class", "**/Issue55Tests.class"
|
||||
classpath = sourceSets.test.output + sourceSets.main.output + configurations.spring4TestRuntime
|
||||
testResultsDir = file("$buildDir/spring4-test-results/")
|
||||
testReportDir = file("$buildDir/reports/spring4-tests/")
|
||||
}
|
||||
check.dependsOn spring4Test
|
||||
}
|
||||
|
||||
configure (aspectjProjects) {
|
||||
@@ -194,5 +173,5 @@ artifacts {
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.10-rc-2'
|
||||
gradleVersion = '1.12'
|
||||
}
|
||||
|
||||
+4
-3
@@ -2,12 +2,13 @@
|
||||
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",
|
||||
"org.jasig.cas.client:cas-client-core:3.2.1"
|
||||
"org.jasig.cas.client:cas-client-core:3.3.3"
|
||||
|
||||
optional "net.sf.ehcache:ehcache:$ehcacheVersion"
|
||||
optional "net.sf.ehcache:ehcache-core:$ehcacheVersion"
|
||||
|
||||
provided "org.apache.tomcat:tomcat-servlet-api:$servletApiVersion"
|
||||
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||
}
|
||||
|
||||
+15
-21
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<name>spring-security-cas</name>
|
||||
<description>spring-security-cas</description>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
@@ -42,47 +42,41 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<artifactId>cas-client-core</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.8.RELEASE</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>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -106,15 +100,15 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-servlet-api</artifactId>
|
||||
<version>7.0.33</version>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -126,7 +120,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -49,9 +49,7 @@ public class ServiceProperties implements InitializingBean {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if(!authenticateAllArtifacts) {
|
||||
Assert.hasLength(this.service, "service must be specified unless authenticateAllArtifacts is true.");
|
||||
}
|
||||
Assert.hasLength(this.service, "service cannot be empty.");
|
||||
Assert.hasLength(this.artifactParameter, "artifactParameter cannot be empty.");
|
||||
Assert.hasLength(this.serviceParameter, "serviceParameter cannot be empty.");
|
||||
}
|
||||
|
||||
+20
-3
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.security.cas.web.authentication;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -50,11 +52,13 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
||||
* string from containing the artifact name and value. This can
|
||||
* be created using {@link #createArtifactPattern(String)}.
|
||||
*/
|
||||
DefaultServiceAuthenticationDetails(HttpServletRequest request, Pattern artifactPattern) {
|
||||
DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, Pattern artifactPattern) throws MalformedURLException {
|
||||
super(request);
|
||||
URL casServiceUrl = new URL(casService);
|
||||
int port = getServicePort(casServiceUrl);
|
||||
final String query = getQueryString(request,artifactPattern);
|
||||
this.serviceUrl = UrlUtils.buildFullRequestUrl(request.getScheme(),
|
||||
request.getServerName(), request.getServerPort(),
|
||||
this.serviceUrl = UrlUtils.buildFullRequestUrl(casServiceUrl.getProtocol(),
|
||||
casServiceUrl.getHost(), port,
|
||||
request.getRequestURI(), query);
|
||||
}
|
||||
|
||||
@@ -128,4 +132,17 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
||||
Assert.hasLength(artifactParameterName);
|
||||
return Pattern.compile("&?"+Pattern.quote(artifactParameterName)+"=[^&]*");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the port from the casServiceURL ensuring to return the proper value if the default port is being used.
|
||||
* @param casServiceUrl the casServerUrl to be used (i.e. "https://example.com/context/j_spring_security_cas_check")
|
||||
* @return the port that is configured for the casServerUrl
|
||||
*/
|
||||
private static int getServicePort(URL casServiceUrl) {
|
||||
int port = casServiceUrl.getPort();
|
||||
if(port == -1) {
|
||||
port = casServiceUrl.getDefaultPort();
|
||||
}
|
||||
return port;
|
||||
}
|
||||
}
|
||||
+48
-2
@@ -15,12 +15,18 @@
|
||||
*/
|
||||
package org.springframework.security.cas.web.authentication;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The {@code AuthenticationDetailsSource} that is set on the
|
||||
@@ -33,20 +39,33 @@ import org.springframework.security.cas.ServiceProperties;
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class ServiceAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest,
|
||||
ServiceAuthenticationDetails> {
|
||||
ServiceAuthenticationDetails>, ApplicationContextAware {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final Pattern artifactPattern;
|
||||
|
||||
private ServiceProperties serviceProperties;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Creates an implementation that uses the default CAS artifactParameterName.
|
||||
* @deprecated Use ServiceAuthenticationDetailsSource(ServiceProperties)
|
||||
*/
|
||||
@Deprecated
|
||||
public ServiceAuthenticationDetailsSource() {
|
||||
this(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an implementation that uses the specified ServiceProperites and the default CAS artifactParameterName.
|
||||
*
|
||||
* @param serviceProperties The ServiceProperties to use to construct the serviceUrl.
|
||||
*/
|
||||
public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties) {
|
||||
this(serviceProperties,ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an implementation that uses the specified artifactParameterName
|
||||
*
|
||||
@@ -54,11 +73,27 @@ public class ServiceAuthenticationDetailsSource implements AuthenticationDetails
|
||||
* the artifactParameterName that is removed from the current
|
||||
* URL. The result becomes the service url. Cannot be null and
|
||||
* cannot be an empty String.
|
||||
* @deprecated Use ServiceAuthenticationDetailsSource(ServiceProperties,String)
|
||||
*/
|
||||
public ServiceAuthenticationDetailsSource(final String artifactParameterName) {
|
||||
this.artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(artifactParameterName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an implementation that uses the specified artifactParameterName
|
||||
*
|
||||
* @param serviceProperties The ServiceProperties to use to construct the serviceUrl.
|
||||
* @param artifactParameterName
|
||||
* the artifactParameterName that is removed from the current
|
||||
* URL. The result becomes the service url. Cannot be null and
|
||||
* cannot be an empty String.
|
||||
*/
|
||||
public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties, String artifactParameterName) {
|
||||
Assert.notNull(serviceProperties, "serviceProperties cannot be null");
|
||||
this.serviceProperties = serviceProperties;
|
||||
this.artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(artifactParameterName);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
@@ -66,6 +101,17 @@ public class ServiceAuthenticationDetailsSource implements AuthenticationDetails
|
||||
* @return the {@code ServiceAuthenticationDetails} containing information about the current request
|
||||
*/
|
||||
public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||
return new DefaultServiceAuthenticationDetails(context,artifactPattern);
|
||||
try {
|
||||
return new DefaultServiceAuthenticationDetails(serviceProperties.getService(),context,artifactPattern);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
if(serviceProperties == null) {
|
||||
serviceProperties = applicationContext.getBean(ServiceProperties.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,10 +36,13 @@ public class ServicePropertiesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowNullServiceWhenAuthenticateAllTokens() throws Exception {
|
||||
public void nullServiceWhenAuthenticateAllTokens() throws Exception {
|
||||
ServiceProperties sp = new ServiceProperties();
|
||||
sp.setAuthenticateAllArtifacts(true);
|
||||
sp.afterPropertiesSet();
|
||||
try {
|
||||
sp.afterPropertiesSet();
|
||||
fail("Expected Exception");
|
||||
}catch(IllegalArgumentException success) {}
|
||||
sp.setAuthenticateAllArtifacts(false);
|
||||
try {
|
||||
sp.afterPropertiesSet();
|
||||
|
||||
+63
-12
@@ -18,11 +18,21 @@ import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -32,9 +42,13 @@ public class DefaultServiceAuthenticationDetailsTests {
|
||||
private DefaultServiceAuthenticationDetails details;
|
||||
private MockHttpServletRequest request;
|
||||
private Pattern artifactPattern;
|
||||
private String casServiceUrl;
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
casServiceUrl = "https://localhost:8443/j_spring_security_cas";
|
||||
request = new MockHttpServletRequest();
|
||||
request.setScheme("https");
|
||||
request.setServerName("localhost");
|
||||
@@ -44,45 +58,82 @@ public class DefaultServiceAuthenticationDetailsTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlNullQuery() throws Exception {
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),details.getServiceUrl());
|
||||
@After
|
||||
public void cleanup() {
|
||||
if(context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketOnlyParam() {
|
||||
public void getServiceUrlNullQuery() throws Exception {
|
||||
details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request), details.getServiceUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketOnlyParam() throws Exception {
|
||||
request.setQueryString("ticket=123");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString(null);
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketFirstMultiParam() {
|
||||
public void getServiceUrlTicketFirstMultiParam() throws Exception {
|
||||
request.setQueryString("ticket=123&other=value");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString("other=value");
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketLastMultiParam() {
|
||||
public void getServiceUrlTicketLastMultiParam() throws Exception {
|
||||
request.setQueryString("other=value&ticket=123");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString("other=value");
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlTicketMiddleMultiParam() {
|
||||
public void getServiceUrlTicketMiddleMultiParam() throws Exception {
|
||||
request.setQueryString("other=value&ticket=123&last=this");
|
||||
details = new DefaultServiceAuthenticationDetails(request,artifactPattern);
|
||||
details = new DefaultServiceAuthenticationDetails(casServiceUrl,request,artifactPattern);
|
||||
String serviceUrl = details.getServiceUrl();
|
||||
request.setQueryString("other=value&last=this");
|
||||
assertEquals(UrlUtils.buildFullRequestUrl(request),serviceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlDoesNotUseHostHeader() throws Exception {
|
||||
casServiceUrl = "https://example.com/j_spring_security_cas";
|
||||
request.setServerName("evil.com");
|
||||
details = new DefaultServiceAuthenticationDetails(casServiceUrl, request,artifactPattern);
|
||||
assertEquals("https://example.com/cas-sample/secure/",details.getServiceUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlDoesNotUseHostHeaderPassivity() {
|
||||
casServiceUrl = "https://example.com/j_spring_security_cas";
|
||||
request.setServerName("evil.com");
|
||||
ServiceAuthenticationDetails details = loadServiceAuthenticationDetails("defaultserviceauthenticationdetails-passivity.xml");
|
||||
assertEquals("https://example.com/cas-sample/secure/", details.getServiceUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServiceUrlDoesNotUseHostHeaderExplicit() {
|
||||
casServiceUrl = "https://example.com/j_spring_security_cas";
|
||||
request.setServerName("evil.com");
|
||||
ServiceAuthenticationDetails details = loadServiceAuthenticationDetails("defaultserviceauthenticationdetails-explicit.xml");
|
||||
assertEquals("https://example.com/cas-sample/secure/", details.getServiceUrl());
|
||||
}
|
||||
|
||||
private ServiceAuthenticationDetails loadServiceAuthenticationDetails(String resourceName) {
|
||||
context = new GenericXmlApplicationContext(getClass(), resourceName);
|
||||
ServiceAuthenticationDetailsSource source = context.getBean(ServiceAuthenticationDetailsSource.class);
|
||||
return source.buildDetails(request);
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
|
||||
|
||||
<bean id="serviceProperties"
|
||||
class="org.springframework.security.cas.ServiceProperties">
|
||||
<property name="service"
|
||||
value="https://example.com/j_spring_security_cas"/>
|
||||
<property name="sendRenew" value="false"/>
|
||||
</bean>
|
||||
<bean id="serviceProperties2"
|
||||
class="org.springframework.security.cas.ServiceProperties">
|
||||
<property name="service"
|
||||
value="https://example2.com/j_spring_security_cas"/>
|
||||
<property name="sendRenew" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
|
||||
<constructor-arg ref="serviceProperties"/>
|
||||
</bean>
|
||||
</beans>
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
|
||||
|
||||
<bean id="serviceProperties"
|
||||
class="org.springframework.security.cas.ServiceProperties">
|
||||
<property name="service"
|
||||
value="https://example.com/j_spring_security_cas"/>
|
||||
<property name="sendRenew" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
|
||||
</beans>
|
||||
+1
-1
@@ -14,7 +14,7 @@ Import-Template:
|
||||
org.springframework.security.core.*;version="${secRange}",
|
||||
org.springframework.security.authentication.*;version="${secRange}",
|
||||
org.springframework.security.web.*;version="${secRange}",
|
||||
org.springframework.beans.factory;version="${springRange}",
|
||||
org.springframework.beans.*;version="${springRange}",
|
||||
org.springframework.cache.*;version="${springRange}";resolution:=optional,
|
||||
org.springframework.context.*;version="${springRange}",
|
||||
org.springframework.dao;version="${springRange}",
|
||||
|
||||
+11
-8
@@ -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,13 +19,14 @@ dependencies {
|
||||
optional project(':spring-security-web'),
|
||||
project(':spring-security-ldap'),
|
||||
project(':spring-security-openid'),
|
||||
project(':spring-security-aspects'),
|
||||
"org.springframework:spring-web:$springVersion",
|
||||
"org.springframework:spring-webmvc:$springVersion",
|
||||
"org.aspectj:aspectjweaver:$aspectjVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion"
|
||||
|
||||
provided "org.apache.tomcat:tomcat-servlet-api:$servletApiVersion"
|
||||
provided "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||
|
||||
testCompile project(':spring-security-cas'),
|
||||
project(':spring-security-core').sourceSets.test.output,
|
||||
@@ -34,10 +36,8 @@ dependencies {
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
"org.springframework:spring-orm:$springVersion",
|
||||
"org.springframework:spring-tx:$springVersion",
|
||||
"org.spockframework:spock-core:$spockVersion",
|
||||
"org.spockframework:spock-spring:$spockVersion",
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
"org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final",
|
||||
"org.eclipse.persistence:javax.persistence:2.0.5",
|
||||
"org.hibernate:hibernate-entitymanager:4.1.0.Final",
|
||||
"org.codehaus.groovy:groovy-all:$groovyVersion",
|
||||
"org.apache.directory.server:apacheds-core:$apacheDsVersion",
|
||||
@@ -48,12 +48,15 @@ dependencies {
|
||||
'org.apache.directory.shared:shared-ldap:0.9.15',
|
||||
'ldapsdk:ldapsdk:4.1',
|
||||
powerMockDependencies,
|
||||
"org.springframework.data:spring-data-jpa:1.2.0.RELEASE",
|
||||
"org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final",
|
||||
"org.hibernate:hibernate-entitymanager:3.6.10.Final",
|
||||
"org.hsqldb:hsqldb:2.2.8"
|
||||
"org.hsqldb:hsqldb:2.2.8",
|
||||
spockDependencies
|
||||
|
||||
testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
}
|
||||
testCompile('org.springframework.data:spring-data-jpa:1.4.1.RELEASE') {
|
||||
exclude group: 'org.aspectj', module: 'aspectjrt'
|
||||
}
|
||||
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
|
||||
+62
-43
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.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-snasphot</id>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -105,59 +99,66 @@
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-servlet-api</artifactId>
|
||||
<version>7.0.33</version>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -181,7 +182,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -239,15 +240,9 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||
<version>1.0.0.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||
<version>1.0.1.Final</version>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>javax.persistence</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -295,37 +290,43 @@
|
||||
<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>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<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>
|
||||
@@ -339,18 +340,36 @@
|
||||
<artifactId>spock-core</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.2.0.RELEASE</version>
|
||||
<version>1.4.1.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<groupId>org.aspectj</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
@@ -361,25 +380,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+62
-6
@@ -15,10 +15,12 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.authentication.ldap
|
||||
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory
|
||||
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.ldap.core.ContextSource;
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
@@ -27,7 +29,13 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication
|
||||
import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor
|
||||
import org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
@@ -57,6 +65,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +83,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupRoleAttribute("group")
|
||||
}
|
||||
}
|
||||
@@ -92,6 +102,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.groupSearchFilter("ou=groupName");
|
||||
}
|
||||
}
|
||||
@@ -110,6 +121,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.rolePrefix("role_")
|
||||
}
|
||||
}
|
||||
@@ -120,7 +132,7 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
AuthenticationManager auth = context.getBean(AuthenticationManager)
|
||||
then:
|
||||
auth
|
||||
auth.authenticate(new UsernamePasswordAuthenticationToken("admin","password")).authorities.collect { it.authority }.sort() == ["ROLE_ADMIN","ROLE_USER"]
|
||||
auth.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"]
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -130,6 +142,29 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2472: Can use crypto PasswordEncoder"() {
|
||||
setup:
|
||||
loadConfig(PasswordEncoderConfig)
|
||||
when:
|
||||
AuthenticationManager auth = context.getBean(AuthenticationManager)
|
||||
then:
|
||||
auth.authenticate(new UsernamePasswordAuthenticationToken("bcrypt","password")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"]
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class PasswordEncoderConfig extends BaseLdapServerConfig {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.contextSource(contextSource())
|
||||
.passwordEncoder(new BCryptPasswordEncoder())
|
||||
.groupSearchBase("ou=groups")
|
||||
.groupSearchFilter("(member={0})")
|
||||
.userDnPatterns("uid={0},ou=people");
|
||||
}
|
||||
}
|
||||
@@ -142,23 +177,44 @@ class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSp
|
||||
static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig {
|
||||
@Bean
|
||||
public ApacheDSContainer ldapServer() throws Exception {
|
||||
ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/users.ldif");
|
||||
apacheDSContainer.setPort(33389);
|
||||
ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
||||
apacheDSContainer.setPort(getPort());
|
||||
return apacheDSContainer;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalAuthentication
|
||||
@Import(ObjectPostProcessorConfiguration)
|
||||
static abstract class BaseLdapProviderConfig {
|
||||
|
||||
@Bean
|
||||
public BaseLdapPathContextSource contextSource() throws Exception {
|
||||
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
|
||||
"ldap://127.0.0.1:33389/dc=springframework,dc=org")
|
||||
"ldap://127.0.0.1:"+ getPort() + "/dc=springframework,dc=org")
|
||||
contextSource.userDn = "uid=admin,ou=system"
|
||||
contextSource.password = "secret"
|
||||
contextSource.afterPropertiesSet();
|
||||
contextSource.afterPropertiesSet()
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) {
|
||||
configure(auth)
|
||||
auth.build()
|
||||
}
|
||||
|
||||
abstract protected void configure(AuthenticationManagerBuilder auth)
|
||||
}
|
||||
|
||||
static Integer port;
|
||||
|
||||
static int getPort() {
|
||||
if(port == null) {
|
||||
ServerSocket socket = new ServerSocket(0)
|
||||
port = socket.localPort
|
||||
socket.close()
|
||||
}
|
||||
port
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.authentication.ldap
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.LdapAuthenticationProviderConfig
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider
|
||||
import org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator
|
||||
import org.springframework.security.ldap.userdetails.PersonContextMapper
|
||||
import org.springframework.test.util.ReflectionTestUtils
|
||||
|
||||
import static org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.*
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
class LdapAuthenticationProviderConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
def "authentication-manager support multiple default ldap contexts (ports dynamically allocated)"() {
|
||||
when:
|
||||
loadConfig(MultiLdapAuthenticationProvidersConfig)
|
||||
then:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.and()
|
||||
.ldapAuthentication()
|
||||
.groupSearchBase("ou=groups")
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -40,7 +40,7 @@ class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec {
|
||||
when:
|
||||
loadConfig(LdapAuthenticationProviderConfig)
|
||||
then:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password")).authorities*.authority.sort() == ['ROLE_USER']
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
|
||||
}
|
||||
|
||||
def "ldap-authentication-provider custom"() {
|
||||
@@ -75,6 +75,6 @@ class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec {
|
||||
LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
|
||||
then:
|
||||
provider.authenticator instanceof PasswordComparisonAuthenticator
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password")).authorities*.authority.sort() == ['ROLE_USER']
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
|
||||
}
|
||||
}
|
||||
+32
-4
@@ -1,7 +1,13 @@
|
||||
package org.springframework.security.config.ldap
|
||||
|
||||
|
||||
import static org.mockito.Mockito.*
|
||||
|
||||
import java.text.MessageFormat
|
||||
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.security.config.AbstractXmlConfigTests
|
||||
import org.springframework.security.config.BeanIds
|
||||
import org.springframework.security.util.FieldUtils
|
||||
@@ -36,7 +42,7 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
|
||||
|
||||
def simpleProviderAuthenticatesCorrectly() {
|
||||
xml.'ldap-server'()
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('group-search-filter':'member={0}')
|
||||
}
|
||||
@@ -66,7 +72,7 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthentication() {
|
||||
xml.'ldap-server'()
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people')
|
||||
'password-compare'
|
||||
@@ -83,7 +89,7 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthenticationWithHashAttribute() {
|
||||
xml.'ldap-server'()
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'('password-attribute': 'uid', hash: 'plaintext')
|
||||
@@ -102,7 +108,7 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
}
|
||||
|
||||
def supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
|
||||
xml.'ldap-server'()
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'('password-attribute': 'uid') {
|
||||
@@ -122,6 +128,28 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
|
||||
notThrown(AuthenticationException)
|
||||
}
|
||||
|
||||
def 'SEC-2472: Supports Crypto PasswordEncoder'() {
|
||||
setup:
|
||||
xml.'ldap-server'(ldif:'test-server.ldif')
|
||||
xml.'authentication-manager'{
|
||||
'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
|
||||
'password-compare'() {
|
||||
'password-encoder'(ref: 'pe')
|
||||
}
|
||||
}
|
||||
}
|
||||
xml.'b:bean'(id:'pe','class':BCryptPasswordEncoder.class.name)
|
||||
|
||||
createAppContext('')
|
||||
def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
|
||||
|
||||
when:
|
||||
def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password'))
|
||||
|
||||
then:
|
||||
auth != null
|
||||
}
|
||||
|
||||
def inetOrgContextMapperIsSupported() {
|
||||
xml.'ldap-server'(url: 'ldap://127.0.0.1:343/dc=springframework,dc=org')
|
||||
xml.'authentication-manager'{
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
.userSearchFilter("(uid={0})") // ldap-authentication-provider@user-search-filter
|
||||
// .contextSource(contextSource) // ldap-authentication-provider@server-ref
|
||||
.contextSource()
|
||||
.ldif("classpath:user.ldif") // ldap-server@ldif
|
||||
.ldif("classpath:users.xldif") // ldap-server@ldif
|
||||
.managerDn("uid=admin,ou=system") // ldap-server@manager-dn
|
||||
.managerPassword("secret") // ldap-server@manager-password
|
||||
.port(33399) // ldap-server@port
|
||||
|
||||
@@ -28,6 +28,16 @@ sn: Alex
|
||||
uid: ben
|
||||
userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=
|
||||
|
||||
dn: uid=bcrypt,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: BCrypt user
|
||||
sn: BCrypt
|
||||
uid: bcrypt
|
||||
userPassword: $2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u
|
||||
|
||||
dn: uid=bob,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
@@ -58,11 +68,22 @@ sn: Mouse
|
||||
uid: jerry
|
||||
userPassword: jerryspassword
|
||||
|
||||
dn: uid=bcrypt,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: BCrypt user
|
||||
sn: BCrypt
|
||||
uid: bcrypt
|
||||
userPassword: $2a$10$lDa0YFNHAt63MjIzK/wUqeM0qjIhzPhp3RNI/MLUQEAUbzhB/SnnS
|
||||
|
||||
dn: cn=developers,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: developers
|
||||
ou: developer
|
||||
member: uid=bcrypt,ou=people,dc=springframework,dc=org
|
||||
member: uid=ben,ou=people,dc=springframework,dc=org
|
||||
member: uid=bob,ou=people,dc=springframework,dc=org
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
dn: ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: groups
|
||||
|
||||
dn: ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: people
|
||||
|
||||
dn: uid=admin,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Rod Johnson
|
||||
sn: Johnson
|
||||
uid: admin
|
||||
userPassword: password
|
||||
|
||||
dn: uid=user,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Dianne Emu
|
||||
sn: Emu
|
||||
uid: user
|
||||
userPassword: password
|
||||
|
||||
dn: cn=user,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: user
|
||||
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
|
||||
uniqueMember: uid=user,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=admin,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: admin
|
||||
uniqueMember: uid=admin,ou=people,dc=springframework,dc=org
|
||||
@@ -0,0 +1,92 @@
|
||||
dn: ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: groups
|
||||
|
||||
dn: ou=subgroups,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: subgroups
|
||||
|
||||
dn: ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: people
|
||||
|
||||
dn: ou=otherpeople,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: organizationalUnit
|
||||
ou: otherpeople
|
||||
|
||||
dn: uid=ben,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Ben Alex
|
||||
sn: Alex
|
||||
uid: ben
|
||||
userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=
|
||||
|
||||
dn: uid=bcrypt,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: BCrypt user
|
||||
sn: BCrypt
|
||||
uid: bcrypt
|
||||
userPassword: $2a$10$lDa0YFNHAt63MjIzK/wUqeM0qjIhzPhp3RNI/MLUQEAUbzhB/SnnS
|
||||
|
||||
dn: uid=bob,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Bob Hamilton
|
||||
sn: Hamilton
|
||||
uid: bob
|
||||
userPassword: bobspassword
|
||||
|
||||
dn: uid=joe,ou=otherpeople,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Joe Smeth
|
||||
sn: Smeth
|
||||
uid: joe
|
||||
userPassword: joespassword
|
||||
|
||||
dn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: person
|
||||
objectclass: organizationalPerson
|
||||
objectclass: inetOrgPerson
|
||||
cn: Mouse, Jerry
|
||||
sn: Mouse
|
||||
uid: jerry
|
||||
userPassword: jerryspassword
|
||||
|
||||
dn: cn=developers,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: developers
|
||||
ou: developer
|
||||
member: uid=ben,ou=people,dc=springframework,dc=org
|
||||
member: uid=bob,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=managers,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: managers
|
||||
ou: manager
|
||||
member: uid=ben,ou=people,dc=springframework,dc=org
|
||||
member: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
|
||||
|
||||
dn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org
|
||||
objectclass: top
|
||||
objectclass: groupOfNames
|
||||
cn: submanagers
|
||||
ou: submanager
|
||||
member: uid=ben,ou=people,dc=springframework,dc=org
|
||||
-2
@@ -29,8 +29,6 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
|
||||
import com.google.inject.internal.ImmutableList.Builder;
|
||||
|
||||
/**
|
||||
* <p>A base {@link SecurityBuilder} that allows {@link SecurityConfigurer} to be
|
||||
* applied to it. This makes modifying the {@link SecurityBuilder} a strategy
|
||||
|
||||
+21
-6
@@ -78,6 +78,9 @@ public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuil
|
||||
*/
|
||||
public AuthenticationManagerBuilder parentAuthenticationManager(
|
||||
AuthenticationManager authenticationManager) {
|
||||
if(authenticationManager instanceof ProviderManager) {
|
||||
eraseCredentials(((ProviderManager) authenticationManager).isEraseCredentialsAfterAuthentication());
|
||||
}
|
||||
this.parentAuthenticationManager = authenticationManager;
|
||||
return this;
|
||||
}
|
||||
@@ -135,19 +138,31 @@ public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuil
|
||||
|
||||
/**
|
||||
* Add JDBC authentication to the {@link AuthenticationManagerBuilder} and
|
||||
* return a {@link JdbcUserDetailsManagerConfigurer} to allow customization of the
|
||||
* JDBC authentication.
|
||||
* return a {@link JdbcUserDetailsManagerConfigurer} to allow customization
|
||||
* of the JDBC authentication.
|
||||
*
|
||||
* <p>
|
||||
* When using with a persistent data store, it is best to add users external
|
||||
* of configuration using something like <a
|
||||
* href="http://flywaydb.org/">Flyway</a> or <a
|
||||
* href="http://www.liquibase.org/">Liquibase</a> to create the schema and
|
||||
* adding users to ensure these steps are only done once and that the
|
||||
* optimal SQL is used.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This method also ensure that a {@link UserDetailsService} is available
|
||||
* for the {@link #getDefaultUserDetailsService()} method. Note that
|
||||
* additional {@link UserDetailsService}'s may override this
|
||||
* {@link UserDetailsService} as the default.
|
||||
* {@link UserDetailsService} as the default. See the <a href=
|
||||
* "http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#user-schema"
|
||||
* >User Schema</a> section of the reference for the default schema.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link JdbcUserDetailsManagerConfigurer} to allow customization of the
|
||||
* JDBC authentication
|
||||
* @throws Exception if an error occurs when adding the JDBC authentication
|
||||
* @return a {@link JdbcUserDetailsManagerConfigurer} to allow customization
|
||||
* of the JDBC authentication
|
||||
* @throws Exception
|
||||
* if an error occurs when adding the JDBC authentication
|
||||
*/
|
||||
public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication()
|
||||
throws Exception {
|
||||
|
||||
+2
-3
@@ -61,7 +61,7 @@ public class AuthenticationConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
|
||||
public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
|
||||
return new EnableGlobalAuthenticationAutowiredConfigurer(context);
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ public class AuthenticationConfiguration {
|
||||
lazyTargetSource.setTargetBeanName(beanNamesForType[0]);
|
||||
lazyTargetSource.setBeanFactory(applicationContext);
|
||||
ProxyFactoryBean proxyFactory = new ProxyFactoryBean();
|
||||
proxyFactory = objectPostProcessor.postProcess(proxyFactory);
|
||||
proxyFactory.setTargetSource(lazyTargetSource);
|
||||
proxyFactory.setInterfaces(new Class[] { interfaceName });
|
||||
return (T) proxyFactory.getObject();
|
||||
}
|
||||
|
||||
@@ -122,7 +122,6 @@ public class AuthenticationConfiguration {
|
||||
return lazyBean(AuthenticationManager.class);
|
||||
}
|
||||
|
||||
|
||||
private static class EnableGlobalAuthenticationAutowiredConfigurer extends GlobalAuthenticationConfigurerAdapter {
|
||||
private final ApplicationContext context;
|
||||
private static final Log logger = LogFactory.getLog(EnableGlobalAuthenticationAutowiredConfigurer.class);
|
||||
|
||||
+56
-6
@@ -40,6 +40,10 @@ import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
|
||||
import org.springframework.security.ldap.userdetails.PersonContextMapper;
|
||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
/**
|
||||
* Configures LDAP {@link AuthenticationProvider} in the {@link ProviderManagerBuilder}.
|
||||
@@ -60,7 +64,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
private BaseLdapPathContextSource contextSource;
|
||||
private ContextSourceBuilder contextSourceBuilder = new ContextSourceBuilder();
|
||||
private UserDetailsContextMapper userDetailsContextMapper;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private Object passwordEncoder;
|
||||
private String passwordAttribute;
|
||||
private LdapAuthoritiesPopulator ldapAuthoritiesPopulator;
|
||||
|
||||
@@ -149,7 +153,9 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
*/
|
||||
private PasswordComparisonAuthenticator createPasswordCompareAuthenticator(BaseLdapPathContextSource contextSource) {
|
||||
PasswordComparisonAuthenticator ldapAuthenticator = new PasswordComparisonAuthenticator(contextSource);
|
||||
ldapAuthenticator.setPasswordAttributeName(passwordAttribute);
|
||||
if(passwordAttribute != null) {
|
||||
ldapAuthenticator.setPasswordAttributeName(passwordAttribute);
|
||||
}
|
||||
ldapAuthenticator.setPasswordEncoder(passwordEncoder);
|
||||
return ldapAuthenticator;
|
||||
}
|
||||
@@ -204,12 +210,26 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
*
|
||||
* @param passwordEncoder the {@link PasswordEncoder} to use
|
||||
* @return the {@link LdapAuthenticationProviderConfigurer} for further customization
|
||||
* @deprecated Use {@link #passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder)} instead
|
||||
*/
|
||||
public LdapAuthenticationProviderConfigurer<B> passwordEncoder(PasswordEncoder passwordEncoder) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link org.springframework.security.crypto.password.PasswordEncoder} to be used when authenticating with
|
||||
* password comparison.
|
||||
*
|
||||
* @param passwordEncoder the {@link org.springframework.security.crypto.password.PasswordEncoder} to use
|
||||
* @return the {@link LdapAuthenticationProviderConfigurer} for further customization
|
||||
*/
|
||||
public LdapAuthenticationProviderConfigurer<B> passwordEncoder(final org.springframework.security.crypto.password.PasswordEncoder passwordEncoder) {
|
||||
Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If your users are at a fixed location in the directory (i.e. you can work
|
||||
* out the DN directly from the username without doing a directory search),
|
||||
@@ -373,7 +393,8 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
private String ldif = "classpath*:*.ldif";
|
||||
private String managerPassword;
|
||||
private String managerDn;
|
||||
private int port = 33389;
|
||||
private Integer port;
|
||||
private static final int DEFAULT_PORT = 33389;
|
||||
private String root = "dc=springframework,dc=org";
|
||||
private String url;
|
||||
|
||||
@@ -418,7 +439,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
}
|
||||
|
||||
/**
|
||||
* The port to connect to LDAP to (the default is 33389).
|
||||
* The port to connect to LDAP to (the default is 33389 or random available port if unavailable).
|
||||
* @param port the port to connect to
|
||||
* @return the {@link ContextSourceBuilder} for further customization
|
||||
*/
|
||||
@@ -478,14 +499,43 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
return contextSource;
|
||||
}
|
||||
ApacheDSContainer apacheDsContainer = new ApacheDSContainer(root, ldif);
|
||||
apacheDsContainer.setPort(port);
|
||||
apacheDsContainer.setPort(getPort());
|
||||
postProcess(apacheDsContainer);
|
||||
return contextSource;
|
||||
}
|
||||
|
||||
private int getPort() {
|
||||
if(port == null) {
|
||||
port = getDefaultPort();
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
private int getDefaultPort() {
|
||||
ServerSocket serverSocket = null;
|
||||
try {
|
||||
try {
|
||||
serverSocket = new ServerSocket(DEFAULT_PORT);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
serverSocket = new ServerSocket(0);
|
||||
} catch(IOException e2) {
|
||||
return DEFAULT_PORT;
|
||||
}
|
||||
}
|
||||
return serverSocket.getLocalPort();
|
||||
} finally {
|
||||
if(serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getProviderUrl() {
|
||||
if(url == null) {
|
||||
return "ldap://127.0.0.1:" + port + "/" + root;
|
||||
return "ldap://127.0.0.1:" + getPort() + "/" + root;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
-67
@@ -1,67 +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.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) {
|
||||
|
||||
AopConfigUtils
|
||||
.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
|
||||
|
||||
Map<String, Object> annotationAttributes = importingClassMetadata
|
||||
.getAnnotationAttributes(EnableGlobalMethodSecurity.class
|
||||
.getName());
|
||||
AnnotationAttributes enableAJAutoProxy = AnnotationAttributes
|
||||
.fromMap(annotationAttributes);
|
||||
|
||||
if (enableAJAutoProxy.getBoolean("proxyTargetClass")) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+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;
|
||||
}
|
||||
}
|
||||
+13
-11
@@ -24,10 +24,8 @@ 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.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
@@ -48,6 +46,7 @@ import org.springframework.security.access.intercept.AfterInvocationProviderMana
|
||||
import org.springframework.security.access.intercept.RunAsManager;
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
|
||||
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
|
||||
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.method.MethodSecurityMetadataSource;
|
||||
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
|
||||
@@ -87,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
|
||||
@@ -111,7 +110,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
*/
|
||||
@Bean
|
||||
public MethodInterceptor methodSecurityInterceptor() throws Exception {
|
||||
MethodSecurityInterceptor methodSecurityInterceptor = new MethodSecurityInterceptor();
|
||||
MethodSecurityInterceptor methodSecurityInterceptor = isAspectJ() ? new AspectJMethodSecurityInterceptor() : new MethodSecurityInterceptor();
|
||||
methodSecurityInterceptor
|
||||
.setAccessDecisionManager(accessDecisionManager());
|
||||
methodSecurityInterceptor
|
||||
@@ -353,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() {
|
||||
@@ -379,6 +377,10 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
return (Integer) enableMethodSecurity().get("order");
|
||||
}
|
||||
|
||||
private boolean isAspectJ() {
|
||||
return enableMethodSecurity().getEnum("mode") == AdviceMode.ASPECTJ;
|
||||
}
|
||||
|
||||
private AnnotationAttributes enableMethodSecurity() {
|
||||
if (enableMethodSecurity == null) {
|
||||
// if it is null look at this instance (i.e. a subclass was used)
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1000,7 +1000,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
* .and()
|
||||
* .formLogin()
|
||||
* .and()
|
||||
* .channelSecurity()
|
||||
* .requiresChannel()
|
||||
* .anyRequest().requiresSecure();
|
||||
* }
|
||||
*
|
||||
|
||||
+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() {
|
||||
|
||||
+49
-13
@@ -16,11 +16,20 @@
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -44,6 +53,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
|
||||
@@ -71,8 +81,8 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
|
||||
private AuthenticationConfiguration authenticationConfiguration;
|
||||
private AuthenticationManagerBuilder authenticationBuilder;
|
||||
private AuthenticationManagerBuilder parentAuthenticationBuilder;
|
||||
private boolean disableAuthenticationRegistration;
|
||||
private AuthenticationManagerBuilder localConfigureAuthenticationBldr;
|
||||
private boolean disableLocalConfigureAuthenticationBldr;
|
||||
private boolean authenticationManagerInitialized;
|
||||
private AuthenticationManager authenticationManager;
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
@@ -148,7 +158,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
this.disableAuthenticationRegistration = true;
|
||||
this.disableLocalConfigureAuthenticationBldr = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,11 +173,11 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
}
|
||||
|
||||
DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
|
||||
parentAuthenticationBuilder.authenticationEventPublisher(eventPublisher);
|
||||
localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
|
||||
|
||||
AuthenticationManager authenticationManager = authenticationManager();
|
||||
authenticationBuilder.parentAuthenticationManager(authenticationManager);
|
||||
http = new HttpSecurity(objectPostProcessor,authenticationBuilder, parentAuthenticationBuilder.getSharedObjects());
|
||||
http = new HttpSecurity(objectPostProcessor,authenticationBuilder, localConfigureAuthenticationBldr.getSharedObjects());
|
||||
http.setSharedObject(UserDetailsService.class, userDetailsService());
|
||||
http.setSharedObject(ApplicationContext.class, context);
|
||||
http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy);
|
||||
@@ -207,7 +217,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
* @throws Exception
|
||||
*/
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return new AuthenticationManagerDelegator(authenticationBuilder);
|
||||
return new AuthenticationManagerDelegator(authenticationBuilder, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,11 +231,11 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
*/
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
if(!authenticationManagerInitialized) {
|
||||
configure(parentAuthenticationBuilder);
|
||||
if(disableAuthenticationRegistration) {
|
||||
configure(localConfigureAuthenticationBldr);
|
||||
if(disableLocalConfigureAuthenticationBldr) {
|
||||
authenticationManager = authenticationConfiguration.getAuthenticationManager();
|
||||
} else {
|
||||
authenticationManager = parentAuthenticationBuilder.build();
|
||||
authenticationManager = localConfigureAuthenticationBldr.build();
|
||||
}
|
||||
authenticationManagerInitialized = true;
|
||||
}
|
||||
@@ -253,7 +263,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
*/
|
||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class);
|
||||
return new UserDetailsServiceDelegator(Arrays.asList(parentAuthenticationBuilder, globalAuthBuilder));
|
||||
return new UserDetailsServiceDelegator(Arrays.asList(localConfigureAuthenticationBldr, globalAuthBuilder));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,7 +276,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
*/
|
||||
protected UserDetailsService userDetailsService() {
|
||||
AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class);
|
||||
return new UserDetailsServiceDelegator(Arrays.asList(parentAuthenticationBuilder, globalAuthBuilder));
|
||||
return new UserDetailsServiceDelegator(Arrays.asList(localConfigureAuthenticationBldr, globalAuthBuilder));
|
||||
}
|
||||
|
||||
public void init(final WebSecurity web) throws Exception {
|
||||
@@ -337,7 +347,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
|
||||
authenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
parentAuthenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor) {
|
||||
localConfigureAuthenticationBldr = new AuthenticationManagerBuilder(objectPostProcessor) {
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
@@ -410,9 +420,14 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
private AuthenticationManagerBuilder delegateBuilder;
|
||||
private AuthenticationManager delegate;
|
||||
private final Object delegateMonitor = new Object();
|
||||
private Set<String> beanNames;
|
||||
|
||||
AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder) {
|
||||
AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder, ApplicationContext context) {
|
||||
Assert.notNull(delegateBuilder,"delegateBuilder cannot be null");
|
||||
Field parentAuthMgrField = ReflectionUtils.findField(AuthenticationManagerBuilder.class, "parentAuthenticationManager");
|
||||
ReflectionUtils.makeAccessible(parentAuthMgrField);
|
||||
beanNames = getAuthenticationManagerBeanNames(context);
|
||||
validateBeanCycle(ReflectionUtils.getField(parentAuthMgrField, delegateBuilder), beanNames);
|
||||
this.delegateBuilder = delegateBuilder;
|
||||
}
|
||||
|
||||
@@ -430,5 +445,26 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
|
||||
return delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
private static Set<String> getAuthenticationManagerBeanNames(ApplicationContext applicationContext) {
|
||||
String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, AuthenticationManager.class);
|
||||
return new HashSet<String>(Arrays.asList(beanNamesForType));
|
||||
}
|
||||
|
||||
private static void validateBeanCycle(Object auth, Set<String> beanNames) {
|
||||
if(auth != null && !beanNames.isEmpty()) {
|
||||
if(auth instanceof Advised){
|
||||
Advised advised = (Advised) auth;
|
||||
TargetSource targetSource = advised.getTargetSource();
|
||||
if(targetSource instanceof LazyInitTargetSource) {
|
||||
LazyInitTargetSource lits = (LazyInitTargetSource) targetSource;
|
||||
if(beanNames.contains(lits.getTargetBeanName())) {
|
||||
throw new FatalBeanException("A dependency cycle was detected when trying to resolve the AuthenticationManager. Please ensure you have configured authentication.");
|
||||
}
|
||||
}
|
||||
}
|
||||
beanNames = Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+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;
|
||||
}
|
||||
|
||||
+3
-1
@@ -294,7 +294,9 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
|
||||
}
|
||||
if(http.getConfigurer(CsrfConfigurer.class) != null) {
|
||||
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
|
||||
} else {
|
||||
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl);
|
||||
}
|
||||
return new AntPathRequestMatcher(this.logoutUrl);
|
||||
return this.logoutRequestMatcher;
|
||||
}
|
||||
}
|
||||
+17
-2
@@ -15,7 +15,9 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
@@ -114,12 +116,13 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>> exte
|
||||
return defaultCache;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RequestMatcher createDefaultSavedRequestMatcher(H http) {
|
||||
ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
|
||||
if(contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
|
||||
|
||||
RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.ico"));
|
||||
|
||||
MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.APPLICATION_JSON);
|
||||
@@ -127,6 +130,18 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>> exte
|
||||
RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest);
|
||||
|
||||
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(new RequestHeaderRequestMatcher("X-Requested-With","XMLHttpRequest"));
|
||||
return new AndRequestMatcher(getRequests, notFavIcon, notJson, notXRequestedWith);
|
||||
|
||||
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
|
||||
|
||||
List<RequestMatcher> matchers = new ArrayList<RequestMatcher>();
|
||||
if(isCsrfEnabled) {
|
||||
RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
|
||||
matchers.add(0, getRequests);
|
||||
}
|
||||
matchers.add(notFavIcon);
|
||||
matchers.add(notJson);
|
||||
matchers.add(notXRequestedWith);
|
||||
|
||||
return new AndRequestMatcher(matchers);
|
||||
}
|
||||
}
|
||||
|
||||
+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
|
||||
|
||||
+1
-1
@@ -208,7 +208,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
String fromParameter = getAttribute(frameElt, ATT_FROM_PARAMETER, "from");
|
||||
allowFromStrategy.addPropertyValue("allowFromParameterName", fromParameter);
|
||||
builder.addConstructorArgValue(allowFromStrategy);
|
||||
builder.addConstructorArgValue(allowFromStrategy.getBeanDefinition());
|
||||
}
|
||||
} else {
|
||||
parserContext.getReaderContext().error("One of 'strategy' and 'strategy-ref' must be set.",
|
||||
|
||||
+18
-4
@@ -46,10 +46,12 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
final String rememberMeServices;
|
||||
private ManagedList<BeanMetadataElement> logoutHandlers = new ManagedList<BeanMetadataElement>();
|
||||
private boolean csrfEnabled;
|
||||
|
||||
public LogoutBeanDefinitionParser(String rememberMeServices, BeanMetadataElement csrfLogoutHandler) {
|
||||
this.rememberMeServices = rememberMeServices;
|
||||
if(csrfLogoutHandler != null) {
|
||||
this.csrfEnabled = csrfLogoutHandler != null;
|
||||
if(this.csrfEnabled) {
|
||||
logoutHandlers.add(csrfLogoutHandler);
|
||||
}
|
||||
}
|
||||
@@ -78,10 +80,9 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
if (!StringUtils.hasText(logoutUrl)) {
|
||||
logoutUrl = DEF_LOGOUT_URL;
|
||||
}
|
||||
BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter$FilterProcessUrlRequestMatcher");
|
||||
matcherBuilder.addConstructorArgValue(logoutUrl);
|
||||
|
||||
builder.addPropertyValue("logoutRequestMatcher", matcherBuilder.getBeanDefinition());
|
||||
|
||||
builder.addPropertyValue("logoutRequestMatcher", getLogoutRequestMatcher(logoutUrl));
|
||||
|
||||
if (StringUtils.hasText(successHandlerRef)) {
|
||||
if (StringUtils.hasText(logoutSuccessUrl)) {
|
||||
@@ -117,6 +118,19 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanDefinition getLogoutRequestMatcher(String logoutUrl) {
|
||||
if(this.csrfEnabled) {
|
||||
BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.web.util.matcher.AntPathRequestMatcher");
|
||||
matcherBuilder.addConstructorArgValue(logoutUrl);
|
||||
matcherBuilder.addConstructorArgValue("POST");
|
||||
return matcherBuilder.getBeanDefinition();
|
||||
} else {
|
||||
BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter$FilterProcessUrlRequestMatcher");
|
||||
matcherBuilder.addConstructorArgValue(logoutUrl);
|
||||
return matcherBuilder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
ManagedList<BeanMetadataElement> getLogoutHandlers() {
|
||||
return logoutHandlers;
|
||||
}
|
||||
|
||||
+3
@@ -452,6 +452,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
|
||||
}
|
||||
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
||||
if(!registry.containsBeanDefinition(beanName)) {
|
||||
return;
|
||||
}
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
|
||||
beanDefinition.setLazyInit(true);
|
||||
}
|
||||
|
||||
+2
-1
@@ -123,7 +123,8 @@ abstract class BaseSpringSpec extends Specification {
|
||||
AuthenticationManager getAuthenticationManager() {
|
||||
try {
|
||||
authenticationManager().delegateBuilder.getObject()
|
||||
} catch(NoSuchBeanDefinitionException e) {}
|
||||
} catch(NoSuchBeanDefinitionException e) {
|
||||
} catch(MissingPropertyException e) {}
|
||||
findFilter(FilterSecurityInterceptor).authenticationManager
|
||||
}
|
||||
|
||||
|
||||
+22
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.authentication
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
@@ -89,4 +90,25 @@ class NamespaceAuthenticationManagerTests extends BaseSpringSpec {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2533: global authentication-manager@erase-credentials=false"() {
|
||||
when:
|
||||
loadConfig(GlobalEraseCredentialsFalseConfig)
|
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
|
||||
then:
|
||||
auth.credentials == "password"
|
||||
auth.principal.password == "password"
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.eraseCredentials(false)
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+79
-1
@@ -15,7 +15,14 @@
|
||||
*/
|
||||
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
|
||||
import org.springframework.context.annotation.Import
|
||||
@@ -25,8 +32,9 @@ import org.springframework.security.access.annotation.Secured
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
|
||||
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.authentication.configurers.GlobalAuthenticationConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration
|
||||
@@ -292,4 +300,74 @@ class AuthenticationConfigurationTests extends BaseSpringSpec {
|
||||
auth.authenticationProvider(provider)
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2531: AuthenticationConfiguration#lazyBean should use BeanClassLoader on ProxyFactoryBean"() {
|
||||
setup:
|
||||
ObjectPostProcessor opp = Mock()
|
||||
Sec2531Config. opp = opp
|
||||
loadConfig(Sec2531Config)
|
||||
when:
|
||||
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
|
||||
config.getAuthenticationManager()
|
||||
then:
|
||||
1 * opp.postProcess(_ as ProxyFactoryBean) >> { args ->
|
||||
args[0]
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(AuthenticationConfiguration)
|
||||
static class Sec2531Config {
|
||||
static ObjectPostProcessor opp
|
||||
|
||||
@Bean
|
||||
public ObjectPostProcessor objectPostProcessor() {
|
||||
opp
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager manager() {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -15,11 +15,14 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.method.configuration
|
||||
|
||||
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
import java.lang.reflect.Method
|
||||
|
||||
import org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect
|
||||
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.context.ConfigurableApplicationContext
|
||||
@@ -188,8 +191,8 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(AspectJModeConfig)
|
||||
then:
|
||||
AnnotationAwareAspectJAutoProxyCreator autoProxyCreator = context.getBean(AnnotationAwareAspectJAutoProxyCreator)
|
||||
autoProxyCreator.proxyTargetClass == true
|
||||
context.getBean(AnnotationSecurityAspect)
|
||||
context.getBean(AspectJMethodSecurityInterceptor)
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -201,8 +204,8 @@ public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
|
||||
when:
|
||||
context = new AnnotationConfigApplicationContext(BaseMethodConfig,AspectJModeExtendsGMSCConfig)
|
||||
then:
|
||||
AnnotationAwareAspectJAutoProxyCreator autoProxyCreator = context.getBean(AnnotationAwareAspectJAutoProxyCreator)
|
||||
autoProxyCreator.proxyTargetClass == false
|
||||
context.getBean(AnnotationSecurityAspect)
|
||||
context.getBean(AspectJMethodSecurityInterceptor)
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
|
||||
public class Sec2515Tests extends BaseSpringSpec {
|
||||
|
||||
def "SEC-2515: Prevent StackOverflow with bean graph cycle"() {
|
||||
when:
|
||||
loadConfig(StackOverflowSecurityConfig)
|
||||
then:
|
||||
thrown(FatalBeanException)
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class StackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManagerBean()
|
||||
throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
}
|
||||
|
||||
def "Custom Name Prevent StackOverflow with bean graph cycle"() {
|
||||
when:
|
||||
loadConfig(StackOverflowSecurityConfig)
|
||||
then:
|
||||
thrown(FatalBeanException)
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@Bean(name="custom")
|
||||
public AuthenticationManager authenticationManagerBean()
|
||||
throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2549: Can load with child classloader"() {
|
||||
setup:
|
||||
CanLoadWithChildConfig.AM = Mock(AuthenticationManager)
|
||||
context = new AnnotationConfigApplicationContext()
|
||||
context.classLoader = new URLClassLoader(new URL[0], context.classLoader)
|
||||
context.register(CanLoadWithChildConfig)
|
||||
context.refresh()
|
||||
when:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
|
||||
then:
|
||||
noExceptionThrown()
|
||||
1 * CanLoadWithChildConfig.AM.authenticate(_) >> new TestingAuthenticationToken("user","password","ROLE_USER")
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class CanLoadWithChildConfig extends WebSecurityConfigurerAdapter {
|
||||
static AuthenticationManager AM
|
||||
@Bean
|
||||
public AuthenticationManager am() {
|
||||
AM
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2515: @Bean still works when configure(AuthenticationManagerBuilder) used"() {
|
||||
when:
|
||||
loadConfig(SecurityConfig)
|
||||
then:
|
||||
noExceptionThrown();
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManagerBean()
|
||||
throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth)
|
||||
throws Exception {
|
||||
auth.inMemoryAuthentication()
|
||||
}
|
||||
}
|
||||
}
|
||||
+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)
|
||||
}
|
||||
}
|
||||
|
||||
+93
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers
|
||||
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
||||
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
@@ -102,6 +104,49 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2498: Disable CSRF enables RequestCache for any method"() {
|
||||
setup:
|
||||
loadConfig(DisableCsrfEnablesRequestCacheConfig)
|
||||
request.requestURI = '/tosave'
|
||||
request.method = "POST"
|
||||
clearCsrfToken()
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.redirectedUrl
|
||||
when:
|
||||
super.setupWeb(request.session)
|
||||
request.method = "POST"
|
||||
request.servletPath = '/login'
|
||||
request.parameters['username'] = ['user'] as String[]
|
||||
request.parameters['password'] = ['password'] as String[]
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.redirectedUrl == 'http://localhost/tosave'
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin().and()
|
||||
.csrf().disable()
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
|
||||
setup:
|
||||
loadConfig(InvalidSessionUrlConfig)
|
||||
@@ -192,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()
|
||||
@@ -293,6 +339,18 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
currentAuthentication != null
|
||||
}
|
||||
|
||||
def "SEC-2543: CSRF means logout requires POST"() {
|
||||
setup:
|
||||
loadConfig(LogoutConfig)
|
||||
login()
|
||||
request.servletPath = "/logout"
|
||||
request.method = "GET"
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "logout with GET is not performed"
|
||||
currentAuthentication != null
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class LogoutConfig extends WebSecurityConfigurerAdapter {
|
||||
@@ -305,9 +363,36 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "CSRF can explicitly enable GET for logout"() {
|
||||
setup:
|
||||
loadConfig(LogoutAllowsGetConfig)
|
||||
login()
|
||||
request.servletPath = "/logout"
|
||||
request.method = "GET"
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "logout with GET is not performed"
|
||||
currentAuthentication == null
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class LogoutAllowsGetConfig extends WebSecurityConfigurerAdapter {
|
||||
static AccessDeniedHandler deniedHandler
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.formLogin().and()
|
||||
.logout()
|
||||
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
@@ -334,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"
|
||||
@@ -381,6 +467,13 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def 'SEC-2749: requireCsrfProtectionMatcher null'() {
|
||||
when:
|
||||
new CsrfConfigurer<>().requireCsrfProtectionMatcher(null)
|
||||
then:
|
||||
thrown(IllegalArgumentException)
|
||||
}
|
||||
|
||||
def clearCsrfToken() {
|
||||
request.removeAllParameters()
|
||||
}
|
||||
|
||||
+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"() {
|
||||
|
||||
+52
-13
@@ -12,27 +12,29 @@
|
||||
*/
|
||||
package org.springframework.security.config.http
|
||||
|
||||
import static org.mockito.Mockito.*
|
||||
import static org.mockito.Matchers.*
|
||||
import static org.mockito.Mockito.*
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.spockframework.compiler.model.WhenBlock;
|
||||
import org.springframework.mock.web.MockFilterChain
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurerTests.CsrfTokenRepositoryConfig;
|
||||
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurerTests.RequireCsrfProtectionMatcherConfig
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.authority.AuthorityUtils
|
||||
import org.springframework.security.core.context.SecurityContextImpl
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.context.HttpRequestResponseHolder
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository
|
||||
import org.springframework.security.web.csrf.CsrfFilter
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor
|
||||
import org.springframework.security.web.csrf.CsrfToken
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor
|
||||
|
||||
import spock.lang.Unroll
|
||||
|
||||
@@ -117,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"
|
||||
@@ -151,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"
|
||||
@@ -203,6 +207,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
}
|
||||
mockBean(RequestMatcher,'matcher')
|
||||
createAppContext()
|
||||
request.method = 'POST'
|
||||
RequestMatcher matcher = appContext.getBean("matcher",RequestMatcher)
|
||||
when:
|
||||
when(matcher.matches(any(HttpServletRequest))).thenReturn(false)
|
||||
@@ -249,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")
|
||||
@@ -272,10 +278,43 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
|
||||
request.setParameter(token.parameterName,token.token)
|
||||
request.method = "POST"
|
||||
request.requestURI = "/j_spring_security_logout"
|
||||
request.servletPath = "/j_spring_security_logout"
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
verify(repo).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
|
||||
}
|
||||
|
||||
def "SEC-2495: csrf disables logout on GET"() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'csrf'()
|
||||
}
|
||||
createAppContext()
|
||||
login()
|
||||
request.method = "GET"
|
||||
request.requestURI = "/j_spring_security_logout"
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
getAuthentication(request) != null
|
||||
}
|
||||
|
||||
|
||||
def login(String username="user", String role="ROLE_USER") {
|
||||
login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role)))
|
||||
}
|
||||
|
||||
def login(Authentication auth) {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
|
||||
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
|
||||
repo.loadContext(requestResponseHolder)
|
||||
repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
|
||||
}
|
||||
|
||||
def getAuthentication(HttpServletRequest request) {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
|
||||
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
|
||||
repo.loadContext(requestResponseHolder)?.authentication
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -172,6 +172,26 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
|
||||
}
|
||||
|
||||
def 'http headers frame-options ALLOW-FROM with whitelist strategy'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'frame-options'(policy : 'ALLOW-FROM', strategy: 'whitelist', value : 'https://example.com')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
|
||||
def request = new MockHttpServletRequest()
|
||||
request.setParameter("from", "https://example.com");
|
||||
hf.doFilter(request, response, new MockFilterChain())
|
||||
|
||||
then:
|
||||
assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
|
||||
}
|
||||
|
||||
def 'http headers header a=b'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.method.sec2499;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
public class Sec2499Tests {
|
||||
private GenericXmlApplicationContext parent;
|
||||
|
||||
private GenericXmlApplicationContext child;
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
if(parent != null) {
|
||||
parent.close();
|
||||
}
|
||||
if(child != null) {
|
||||
child.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodExpressionHandlerInParentContextLoads() {
|
||||
parent = new GenericXmlApplicationContext("org/springframework/security/config/method/sec2499/parent.xml");
|
||||
child = new GenericXmlApplicationContext();
|
||||
child.load("org/springframework/security/config/method/sec2499/child.xml");
|
||||
child.setParent(parent);
|
||||
child.refresh();
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<global-method-security pre-post-annotations="enabled">
|
||||
<expression-handler ref="expressionHandler"/>
|
||||
</global-method-security>
|
||||
|
||||
</b:beans>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?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 id="expressionHandler"
|
||||
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"/>
|
||||
|
||||
</beans>
|
||||
@@ -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>
|
||||
@@ -16,6 +16,7 @@ Import-Template:
|
||||
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}",
|
||||
|
||||
+7
-5
@@ -8,16 +8,19 @@ configurations {
|
||||
included
|
||||
|
||||
compile.extendsFrom included
|
||||
|
||||
testCompile.exclude group: 'org.mockito', module: 'mockito-all'
|
||||
}
|
||||
|
||||
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",
|
||||
"org.springframework:spring-expression:$springVersion"
|
||||
|
||||
optional "net.sf.ehcache:ehcache:$ehcacheVersion",
|
||||
optional "net.sf.ehcache:ehcache-core:$ehcacheVersion",
|
||||
'javax.annotation:jsr250-api:1.0',
|
||||
"org.aspectj:aspectjrt:$aspectjVersion",
|
||||
"org.springframework:spring-jdbc:$springVersion",
|
||||
@@ -30,8 +33,7 @@ dependencies {
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
powerMockDependencies
|
||||
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:$cglibVersion"
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion"
|
||||
}
|
||||
|
||||
classes.doLast {
|
||||
@@ -43,7 +45,7 @@ classes.doLast {
|
||||
|
||||
sourceJar.from cryptoProject.sourceSets.main.java
|
||||
|
||||
configure([test,spring4Test]) {
|
||||
configure(project.tasks.withType(Test)) {
|
||||
systemProperties['springSecurityVersion'] = version
|
||||
systemProperties['springVersion'] = springVersion
|
||||
}
|
||||
+90
-30
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.1.CI-SNAPSHOT</version>
|
||||
<version>3.2.7.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-snasphot</id>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.8.RELEASE</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>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -107,8 +101,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<artifactId>ehcache-core</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -122,23 +116,17 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>2.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
@@ -150,18 +138,36 @@
|
||||
<artifactId>commons-collections</artifactId>
|
||||
<version>3.2</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
@@ -174,54 +180,108 @@
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<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>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<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>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-core</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<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>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</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>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-reflect</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.6.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.5</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<version>3.2.13.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<groupId>org.mockito</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
+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);
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@ package org.springframework.security.authentication.dao;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.encoding.PasswordEncoder;
|
||||
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
|
||||
@@ -106,11 +107,11 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
|
||||
}
|
||||
throw notFound;
|
||||
} catch (Exception repositoryProblem) {
|
||||
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
|
||||
throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
|
||||
}
|
||||
|
||||
if (loadedUser == null) {
|
||||
throw new AuthenticationServiceException(
|
||||
throw new InternalAuthenticationServiceException(
|
||||
"UserDetailsService returned null, which is an interface contract violation");
|
||||
}
|
||||
return loadedUser;
|
||||
|
||||
+4
@@ -64,6 +64,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}
|
||||
|
||||
+4
@@ -61,6 +61,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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
package org.springframework.security.core;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Generic implementation of version comparison.
|
||||
*
|
||||
* NOTE: This is a copy from https://svn.apache.org/repos/asf/maven/maven-3/tags/maven-3.1.0/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java
|
||||
*
|
||||
* <p>Features:
|
||||
* <ul>
|
||||
* <li>mixing of '<code>-</code>' (dash) and '<code>.</code>' (dot) separators,</li>
|
||||
* <li>transition between characters and digits also constitutes a separator:
|
||||
* <code>1.0alpha1 => [1, 0, alpha, 1]</code></li>
|
||||
* <li>unlimited number of version components,</li>
|
||||
* <li>version components in the text can be digits or strings,</li>
|
||||
* <li>strings are checked for well-known qualifiers and the qualifier ordering is used for version ordering.
|
||||
* Well-known qualifiers (case insensitive) are:<ul>
|
||||
* <li><code>alpha</code> or <code>a</code></li>
|
||||
* <li><code>beta</code> or <code>b</code></li>
|
||||
* <li><code>milestone</code> or <code>m</code></li>
|
||||
* <li><code>rc</code> or <code>cr</code></li>
|
||||
* <li><code>snapshot</code></li>
|
||||
* <li><code>(the empty string)</code> or <code>ga</code> or <code>final</code></li>
|
||||
* <li><code>sp</code></li>
|
||||
* </ul>
|
||||
* Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive),
|
||||
* </li>
|
||||
* <li>a dash usually precedes a qualifier, and is always less important than something preceded with a dot.</li>
|
||||
* </ul></p>
|
||||
*
|
||||
* @see <a href="https://cwiki.apache.org/confluence/display/MAVENOLD/Versioning">"Versioning" on Maven Wiki</a>
|
||||
* @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a>
|
||||
* @author <a href="mailto:hboutemy@apache.org">Hervé Boutemy</a>
|
||||
*/
|
||||
class ComparableVersion
|
||||
implements Comparable<ComparableVersion>
|
||||
{
|
||||
private String value;
|
||||
|
||||
private String canonical;
|
||||
|
||||
private ListItem items;
|
||||
|
||||
private interface Item
|
||||
{
|
||||
final int INTEGER_ITEM = 0;
|
||||
final int STRING_ITEM = 1;
|
||||
final int LIST_ITEM = 2;
|
||||
|
||||
int compareTo( Item item );
|
||||
|
||||
int getType();
|
||||
|
||||
boolean isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a numeric item in the version item list.
|
||||
*/
|
||||
private static class IntegerItem
|
||||
implements Item
|
||||
{
|
||||
private static final BigInteger BigInteger_ZERO = new BigInteger( "0" );
|
||||
|
||||
private final BigInteger value;
|
||||
|
||||
public static final IntegerItem ZERO = new IntegerItem();
|
||||
|
||||
private IntegerItem()
|
||||
{
|
||||
this.value = BigInteger_ZERO;
|
||||
}
|
||||
|
||||
public IntegerItem( String str )
|
||||
{
|
||||
this.value = new BigInteger( str );
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return INTEGER_ITEM;
|
||||
}
|
||||
|
||||
public boolean isNull()
|
||||
{
|
||||
return BigInteger_ZERO.equals( value );
|
||||
}
|
||||
|
||||
public int compareTo( Item item )
|
||||
{
|
||||
if ( item == null )
|
||||
{
|
||||
return BigInteger_ZERO.equals( value ) ? 0 : 1; // 1.0 == 1, 1.1 > 1
|
||||
}
|
||||
|
||||
switch ( item.getType() )
|
||||
{
|
||||
case INTEGER_ITEM:
|
||||
return value.compareTo( ( (IntegerItem) item ).value );
|
||||
|
||||
case STRING_ITEM:
|
||||
return 1; // 1.1 > 1-sp
|
||||
|
||||
case LIST_ITEM:
|
||||
return 1; // 1.1 > 1-1
|
||||
|
||||
default:
|
||||
throw new RuntimeException( "invalid item: " + item.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a string in the version item list, usually a qualifier.
|
||||
*/
|
||||
private static class StringItem
|
||||
implements Item
|
||||
{
|
||||
private static final String[] QUALIFIERS = { "alpha", "beta", "milestone", "rc", "snapshot", "", "sp" };
|
||||
|
||||
private static final List<String> _QUALIFIERS = Arrays.asList( QUALIFIERS );
|
||||
|
||||
private static final Properties ALIASES = new Properties();
|
||||
static
|
||||
{
|
||||
ALIASES.put( "ga", "" );
|
||||
ALIASES.put( "final", "" );
|
||||
ALIASES.put( "cr", "rc" );
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparable value for the empty-string qualifier. This one is used to determine if a given qualifier makes
|
||||
* the version older than one without a qualifier, or more recent.
|
||||
*/
|
||||
private static final String RELEASE_VERSION_INDEX = String.valueOf( _QUALIFIERS.indexOf( "" ) );
|
||||
|
||||
private String value;
|
||||
|
||||
public StringItem( String value, boolean followedByDigit )
|
||||
{
|
||||
if ( followedByDigit && value.length() == 1 )
|
||||
{
|
||||
// a1 = alpha-1, b1 = beta-1, m1 = milestone-1
|
||||
switch ( value.charAt( 0 ) )
|
||||
{
|
||||
case 'a':
|
||||
value = "alpha";
|
||||
break;
|
||||
case 'b':
|
||||
value = "beta";
|
||||
break;
|
||||
case 'm':
|
||||
value = "milestone";
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.value = ALIASES.getProperty( value , value );
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return STRING_ITEM;
|
||||
}
|
||||
|
||||
public boolean isNull()
|
||||
{
|
||||
return ( comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX ) == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a comparable value for a qualifier.
|
||||
*
|
||||
* This method takes into account the ordering of known qualifiers then unknown qualifiers with lexical ordering.
|
||||
*
|
||||
* just returning an Integer with the index here is faster, but requires a lot of if/then/else to check for -1
|
||||
* or QUALIFIERS.size and then resort to lexical ordering. Most comparisons are decided by the first character,
|
||||
* so this is still fast. If more characters are needed then it requires a lexical sort anyway.
|
||||
*
|
||||
* @param qualifier
|
||||
* @return an equivalent value that can be used with lexical comparison
|
||||
*/
|
||||
public static String comparableQualifier( String qualifier )
|
||||
{
|
||||
int i = _QUALIFIERS.indexOf( qualifier );
|
||||
|
||||
return i == -1 ? ( _QUALIFIERS.size() + "-" + qualifier ) : String.valueOf( i );
|
||||
}
|
||||
|
||||
public int compareTo( Item item )
|
||||
{
|
||||
if ( item == null )
|
||||
{
|
||||
// 1-rc < 1, 1-ga > 1
|
||||
return comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX );
|
||||
}
|
||||
switch ( item.getType() )
|
||||
{
|
||||
case INTEGER_ITEM:
|
||||
return -1; // 1.any < 1.1 ?
|
||||
|
||||
case STRING_ITEM:
|
||||
return comparableQualifier( value ).compareTo( comparableQualifier( ( (StringItem) item ).value ) );
|
||||
|
||||
case LIST_ITEM:
|
||||
return -1; // 1.any < 1-1
|
||||
|
||||
default:
|
||||
throw new RuntimeException( "invalid item: " + item.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a version list item. This class is used both for the global item list and for sub-lists (which start
|
||||
* with '-(number)' in the version specification).
|
||||
*/
|
||||
private static class ListItem
|
||||
extends ArrayList<Item>
|
||||
implements Item
|
||||
{
|
||||
public int getType()
|
||||
{
|
||||
return LIST_ITEM;
|
||||
}
|
||||
|
||||
public boolean isNull()
|
||||
{
|
||||
return ( size() == 0 );
|
||||
}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
for( ListIterator<Item> iterator = listIterator( size() ); iterator.hasPrevious(); )
|
||||
{
|
||||
Item item = iterator.previous();
|
||||
if ( item.isNull() )
|
||||
{
|
||||
iterator.remove(); // remove null trailing items: 0, "", empty list
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo( Item item )
|
||||
{
|
||||
if ( item == null )
|
||||
{
|
||||
if ( size() == 0 )
|
||||
{
|
||||
return 0; // 1-0 = 1- (normalize) = 1
|
||||
}
|
||||
Item first = get( 0 );
|
||||
return first.compareTo( null );
|
||||
}
|
||||
switch ( item.getType() )
|
||||
{
|
||||
case INTEGER_ITEM:
|
||||
return -1; // 1-1 < 1.0.x
|
||||
|
||||
case STRING_ITEM:
|
||||
return 1; // 1-1 > 1-sp
|
||||
|
||||
case LIST_ITEM:
|
||||
Iterator<Item> left = iterator();
|
||||
Iterator<Item> right = ( (ListItem) item ).iterator();
|
||||
|
||||
while ( left.hasNext() || right.hasNext() )
|
||||
{
|
||||
Item l = left.hasNext() ? left.next() : null;
|
||||
Item r = right.hasNext() ? right.next() : null;
|
||||
|
||||
// if this is shorter, then invert the compare and mul with -1
|
||||
int result = l == null ? -1 * r.compareTo( l ) : l.compareTo( r );
|
||||
|
||||
if ( result != 0 )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
throw new RuntimeException( "invalid item: " + item.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder( "(" );
|
||||
for( Iterator<Item> iter = iterator(); iter.hasNext(); )
|
||||
{
|
||||
buffer.append( iter.next() );
|
||||
if ( iter.hasNext() )
|
||||
{
|
||||
buffer.append( ',' );
|
||||
}
|
||||
}
|
||||
buffer.append( ')' );
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public ComparableVersion( String version )
|
||||
{
|
||||
parseVersion( version );
|
||||
}
|
||||
|
||||
public final void parseVersion( String version )
|
||||
{
|
||||
this.value = version;
|
||||
|
||||
items = new ListItem();
|
||||
|
||||
version = version.toLowerCase( Locale.ENGLISH );
|
||||
|
||||
ListItem list = items;
|
||||
|
||||
Stack<Item> stack = new Stack<Item>();
|
||||
stack.push( list );
|
||||
|
||||
boolean isDigit = false;
|
||||
|
||||
int startIndex = 0;
|
||||
|
||||
for ( int i = 0; i < version.length(); i++ )
|
||||
{
|
||||
char c = version.charAt( i );
|
||||
|
||||
if ( c == '.' )
|
||||
{
|
||||
if ( i == startIndex )
|
||||
{
|
||||
list.add( IntegerItem.ZERO );
|
||||
}
|
||||
else
|
||||
{
|
||||
list.add( parseItem( isDigit, version.substring( startIndex, i ) ) );
|
||||
}
|
||||
startIndex = i + 1;
|
||||
}
|
||||
else if ( c == '-' )
|
||||
{
|
||||
if ( i == startIndex )
|
||||
{
|
||||
list.add( IntegerItem.ZERO );
|
||||
}
|
||||
else
|
||||
{
|
||||
list.add( parseItem( isDigit, version.substring( startIndex, i ) ) );
|
||||
}
|
||||
startIndex = i + 1;
|
||||
|
||||
if ( isDigit )
|
||||
{
|
||||
list.normalize(); // 1.0-* = 1-*
|
||||
|
||||
if ( ( i + 1 < version.length() ) && Character.isDigit( version.charAt( i + 1 ) ) )
|
||||
{
|
||||
// new ListItem only if previous were digits and new char is a digit,
|
||||
// ie need to differentiate only 1.1 from 1-1
|
||||
list.add( list = new ListItem() );
|
||||
|
||||
stack.push( list );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( Character.isDigit( c ) )
|
||||
{
|
||||
if ( !isDigit && i > startIndex )
|
||||
{
|
||||
list.add( new StringItem( version.substring( startIndex, i ), true ) );
|
||||
startIndex = i;
|
||||
}
|
||||
|
||||
isDigit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isDigit && i > startIndex )
|
||||
{
|
||||
list.add( parseItem( true, version.substring( startIndex, i ) ) );
|
||||
startIndex = i;
|
||||
}
|
||||
|
||||
isDigit = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( version.length() > startIndex )
|
||||
{
|
||||
list.add( parseItem( isDigit, version.substring( startIndex ) ) );
|
||||
}
|
||||
|
||||
while ( !stack.isEmpty() )
|
||||
{
|
||||
list = (ListItem) stack.pop();
|
||||
list.normalize();
|
||||
}
|
||||
|
||||
canonical = items.toString();
|
||||
}
|
||||
|
||||
private static Item parseItem( boolean isDigit, String buf )
|
||||
{
|
||||
return isDigit ? new IntegerItem( buf ) : new StringItem( buf, false );
|
||||
}
|
||||
|
||||
public int compareTo( ComparableVersion o )
|
||||
{
|
||||
return items.compareTo( o.items );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
return ( o instanceof ComparableVersion ) && canonical.equals( ( (ComparableVersion) o ).canonical );
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return canonical.hashCode();
|
||||
}
|
||||
}
|
||||
+12
-3
@@ -23,7 +23,7 @@ public class SpringSecurityCoreVersion {
|
||||
*/
|
||||
public static final long SERIAL_VERSION_UID = 320L;
|
||||
|
||||
static final String MIN_SPRING_VERSION = "3.2.8.RELEASE";
|
||||
static final String MIN_SPRING_VERSION = "3.2.13.RELEASE";
|
||||
|
||||
static {
|
||||
performVersionChecks();
|
||||
@@ -38,6 +38,15 @@ public class SpringSecurityCoreVersion {
|
||||
* Performs version checks
|
||||
*/
|
||||
private static void performVersionChecks() {
|
||||
performVersionChecks(MIN_SPRING_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform version checks with specific min Spring Version
|
||||
*
|
||||
* @param minSpringVersion
|
||||
*/
|
||||
private static void performVersionChecks(String minSpringVersion) {
|
||||
// Check Spring Compatibility
|
||||
String springVersion = SpringVersion.getVersion();
|
||||
String version = getVersion();
|
||||
@@ -47,8 +56,8 @@ public class SpringSecurityCoreVersion {
|
||||
}
|
||||
|
||||
logger.info("You are running with Spring Security Core " + version);
|
||||
if (springVersion.compareTo(MIN_SPRING_VERSION) < 0) {
|
||||
logger.warn("**** You are advised to use Spring " + MIN_SPRING_VERSION +
|
||||
if (new ComparableVersion(springVersion).compareTo(new ComparableVersion(minSpringVersion)) < 0) {
|
||||
logger.warn("**** You are advised to use Spring " + minSpringVersion +
|
||||
" or later with this version. You are running: " + springVersion);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public interface UserDetailsService {
|
||||
|
||||
/**
|
||||
* Locates the user based on the username. In the actual implementation, the search may possibly be case
|
||||
* insensitive, or case insensitive depending on how the implementation instance is configured. In this case, the
|
||||
* sensitive, or case insensitive depending on how the implementation instance is configured. In this case, the
|
||||
* <code>UserDetails</code> object that comes back may have a username that is of a different case than what was
|
||||
* actually requested..
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=P\u0159\u00EDstup odep\u0159en
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=\u0160patn\u00E9 p\u0159ihla\u0161ovac\u00ED \u00FAdaje
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Nebyl nalezen \u017E\u00E1dn\u00FD Authentication objekt v SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=\u0160patn\u00E9 p\u0159ihla\u0161ovac\u00ED \u00FAdaje
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Platnost u\u017Eivatelsk\u00E9ho hesla vypr\u0161ela
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Zugriff verweigert
|
||||
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
|
||||
@@ -29,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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Acceso denegado
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Credenciales err\u00F3neas
|
||||
AbstractSecurityInterceptor.authenticationNotFound=El objeto Authentication no ha sido encontrado en el SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciales err\u00F3neas
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Las credenciales del usuario han expirado
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Translation by Laurent Pireyn (laurent.pireyn@pisolutions.eu)
|
||||
# Translation by Valentin Crettaz (valentin.crettaz@consulthys.com)
|
||||
AbstractAccessDecisionManager.accessDenied=Acc\u00E8s refus\u00E9
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Le mot de passe est obligatoire
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Aucun objet Authentication n'a \u00E9t\u00E9 trouv\u00E9 dans le SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Les identifications sont erron\u00E9es
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Les identifications de l'utilisateur ont expir\u00E9
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Accesso negato
|
||||
AbstractLdapAuthenticationProvider.badCredentials=Credenziali non valide
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Nessuna autenticazione trovata dentro il Security Context
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenziali non valide
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenziali dell'utente scadute
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
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.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Pri\u0117jimas neleid\u017eiamas
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Tu\u0161\u010dias slapta\u017eodis
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Authentication objektas nerastas SecurityContext kontekste
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Blogi kredencialai
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Pasibaig\u0117 vartotojo kredencial\u0173 galiojimas
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=Dost\u0119p zabroniony
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Niepoprawne dane uwierzytelniaj\u0105ce
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Obiekt Authentication nie zosta\u0142 odnaleziony w SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Niepoprawne dane uwierzytelniaj\u0105ce
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Wa\u017Cno\u015B\u0107 danych uwierzytelniaj\u0105cych wygas\u0142a
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Messages in Brazilian Portuguese
|
||||
# Translation by Leonardo Pinto (leoviveiros@gmail.com)
|
||||
AbstractAccessDecisionManager.accessDenied=Acesso negado
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Usu\u00E1rio inexistente ou senha inv\u00E1lida
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Um objeto de autentica\u00E7\u00E3o n\u00E3o foi encontrado no SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Usu\u00E1rio inexistente ou senha inv\u00E1lida
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Credenciais expiradas
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Spring Security Portuguese Resource Bundle
|
||||
# Author: José Santos
|
||||
AbstractAccessDecisionManager.accessDenied=Acesso negado
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=Credenciais inv\u00E1lidas
|
||||
AbstractSecurityInterceptor.authenticationNotFound=Objecto Authentication n\u00E3o encontrado em SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciais inv\u00E1lidas
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=As credenciais do utilizador expiraram
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=\u0414\u043E\u0441\u0442\u0443\u043F \u0437\u0430\u0431\u043E\u0440\u043E\u043D\u0435\u043D\u0438\u0439
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
|
||||
AbstractSecurityInterceptor.authenticationNotFound=\u041E\u0431'\u0454\u043A\u0442 Authentication \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u0438\u0439 \u0432 SecurityContext
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=\u0414\u0430\u043D\u0456 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435\u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0456
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u041F\u043E\u0432\u043D\u043E\u0432\u0430\u0436\u0435\u043D\u043D\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u043B\u0438 \u0442\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
AbstractAccessDecisionManager.accessDenied=\u4E0D\u5141\u8BB8\u8BBF\u95EE
|
||||
AbstractLdapAuthenticationProvider.emptyPassword=\u574F\u7684\u51ED\u8BC1
|
||||
AbstractSecurityInterceptor.authenticationNotFound=\u672A\u5728SecurityContext\u4E2D\u67E5\u627E\u5230\u8BA4\u8BC1\u5BF9\u8C61
|
||||
AbstractUserDetailsAuthenticationProvider.badCredentials=\u574F\u7684\u51ED\u8BC1
|
||||
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ED\u8BC1\u5DF2\u8FC7\u671F
|
||||
|
||||
+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) {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.access.annotation.sec2150;
|
||||
|
||||
public interface CrudRepository {
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.access.annotation.sec2150;
|
||||
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
@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 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user