Compare commits
112 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| afcad4f0d4 | |||
| 32c767a30d | |||
| a11746a8d1 | |||
| a18265a163 | |||
| d7a2c0a98c | |||
| 9057fbe0ed | |||
| 537d8f974f | |||
| 783af4012b | |||
| 5f5b8052d8 | |||
| 7dbb8e777e | |||
| bb563967cc | |||
| 974105ed19 | |||
| 2cad2f401b | |||
| 3048e2c6e7 | |||
| 561f284718 | |||
| afc6a6ee0d | |||
| fa05e9c590 | |||
| 818be86d46 | |||
| 60704eb50e | |||
| f02b77794f | |||
| 1172d44397 | |||
| 49738e4588 | |||
| 3b13c1fdf4 | |||
| 8f6450ede1 | |||
| f2cde4ffa3 | |||
| 9810768186 | |||
| 7f99a2dfbb | |||
| 85305050c0 | |||
| 8a3a7961cb | |||
| fc8e4868ce | |||
| 65367e6547 | |||
| bf2df220ca | |||
| 152f41f61e | |||
| 7a3da28987 | |||
| e17adad878 | |||
| 058b9debef | |||
| 6c35c33abe | |||
| c42e13c966 | |||
| 6b42a2eae1 | |||
| ec8b48150d | |||
| 4eff50b48b | |||
| 087b56da96 | |||
| 8d8475deb1 | |||
| b5f5665ea6 | |||
| 3b05fd6fed | |||
| 4c84805ac9 | |||
| a99c6db327 | |||
| 1f833b0d6b | |||
| add3aae6ef | |||
| f09ce267b3 | |||
| 374aceed2b | |||
| df703e0189 | |||
| 8c580dc170 | |||
| 5205bf57c6 | |||
| 994117ad75 | |||
| b7041ed00e | |||
| 053c890a69 | |||
| 7838e3eeca | |||
| 2df5541905 | |||
| 04fac30d75 | |||
| 54ffa28bde | |||
| ca1080fb96 | |||
| 4708287ad3 | |||
| 0d12397662 | |||
| a34178bc40 | |||
| aaa7cec32e | |||
| 6f9085dd5d | |||
| 7f714ebb23 | |||
| 00d668dc5c | |||
| 035067caf4 | |||
| 0da9b6c64b | |||
| 418bb57323 | |||
| 4672c2a1f7 | |||
| 4460e84b29 | |||
| 548ed4e14a | |||
| 6be4de854a | |||
| feeb380b51 | |||
| ec524da6cb | |||
| fc6fc19eed | |||
| fa39ecd719 | |||
| 7e274ea5b6 | |||
| 8e8bdad8e6 | |||
| f2fdc9d1f5 | |||
| 74a6303b6f | |||
| be15213819 | |||
| 595b16d836 | |||
| 2a632a061e | |||
| 4308e72573 | |||
| b8cc42e3a3 | |||
| ab08d99a52 | |||
| 135df149a3 | |||
| c6a534cad8 | |||
| 0b996c669f | |||
| 13c5af5b91 | |||
| e97758dd3a | |||
| 209cf317d6 | |||
| 5641ab98c1 | |||
| c7b93e6cee | |||
| 59e13e7bbb | |||
| 5a59c74d02 | |||
| 5bc6f64b03 | |||
| bc6fc518d3 | |||
| 9dbe30c81d | |||
| 2d2f91484d | |||
| afddb5eb39 | |||
| 1745715865 | |||
| 6382b6341a | |||
| 85cd5627b6 | |||
| 4944e602cb | |||
| f1f3acdf75 | |||
| 2c8946c406 | |||
| 9c703a3051 |
@@ -19,3 +19,4 @@ build/
|
||||
*.iws
|
||||
.gradle/
|
||||
atlassian-ide-plugin.xml
|
||||
/samples
|
||||
|
||||
+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_
|
||||
|
||||
+18
-24
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-acl</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<name>spring-security-acl</name>
|
||||
<description>spring-security-acl</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -88,13 +82,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -132,7 +126,7 @@
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<version>2.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,19 +144,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -98,7 +98,7 @@ public abstract class AclFormattingUtils {
|
||||
}
|
||||
|
||||
private static String printBinary(int i, char on, char off) {
|
||||
String s = Integer.toString(i, 2);
|
||||
String s = Integer.toBinaryString(i);
|
||||
String pattern = Permission.THIRTY_TWO_RESERVED_OFF;
|
||||
String temp2 = pattern.substring(0, pattern.length() - s.length()) + s;
|
||||
|
||||
|
||||
@@ -119,6 +119,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
* @param acl containing the ACEs to insert
|
||||
*/
|
||||
protected void createEntries(final MutableAcl acl) {
|
||||
if(acl.getEntries().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
jdbcTemplate.batchUpdate(insertEntry,
|
||||
new BatchPreparedStatementSetter() {
|
||||
public int getBatchSize() {
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
@@ -124,4 +124,12 @@ public class AclFormattingUtilsTests extends TestCase {
|
||||
|
||||
Assert.assertEquals("............................xxxx", AclFormattingUtils.printBinary(15, 'x'));
|
||||
}
|
||||
|
||||
public void testPrintBinaryNegative() {
|
||||
Assert.assertEquals("*...............................", AclFormattingUtils.printBinary(0x80000000));
|
||||
}
|
||||
|
||||
public void testPrintBinaryMinusOne() {
|
||||
Assert.assertEquals("********************************", AclFormattingUtils.printBinary(0xffffffff));
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -105,6 +105,7 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
||||
jdbcTemplate.execute("drop table acl_object_identity");
|
||||
jdbcTemplate.execute("drop table acl_class");
|
||||
jdbcTemplate.execute("drop table acl_sid");
|
||||
aclCache.clearCache();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+14
-20
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-aspects</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<name>spring-security-aspects</name>
|
||||
<description>spring-security-aspects</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,35 +42,29 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -132,13 +126,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
apply plugin: 'maven-bom'
|
||||
apply from: "$rootDir/gradle/maven-deployment.gradle"
|
||||
|
||||
generatePom.enabled = false
|
||||
sonarRunner.skipProject = true
|
||||
|
||||
mavenBom {
|
||||
projects = coreModuleProjects
|
||||
}
|
||||
+16
-7
@@ -5,11 +5,12 @@ buildscript {
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.5")
|
||||
classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2")
|
||||
classpath("org.gradle.api.plugins:gradle-tomcat-plugin:0.9.8")
|
||||
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
|
||||
classpath('org.asciidoctor:asciidoctor-gradle-plugin:0.7.0')
|
||||
classpath('org.asciidoctor:asciidoctor-java-integration:0.1.4.preview.1')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +25,17 @@ allprojects {
|
||||
|
||||
ext.releaseBuild = version.endsWith('RELEASE')
|
||||
ext.snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
ext.springVersion = '3.2.8.RELEASE'
|
||||
ext.spring4Version = '4.0.2.RELEASE'
|
||||
ext.springLdapVersion = '1.3.2.RELEASE'
|
||||
ext.springLdap2Version = '2.0.1.RELEASE'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
|
||||
repositories {
|
||||
maven { url "http://repo.springsource.org/libs-snapshot" }
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/libs-snapshot" }
|
||||
maven { url "https://repo.spring.io/plugins-release" }
|
||||
maven { url "http://repo.terracotta.org/maven2/" }
|
||||
}
|
||||
|
||||
@@ -51,7 +57,7 @@ sonarRunner {
|
||||
}
|
||||
|
||||
// Set up different subproject lists for individual configuration
|
||||
ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && project.name != 'manual' && project.name != 'guides' }
|
||||
ext.javaProjects = subprojects.findAll { project -> project.name != 'docs' && project.name != 'manual' && project.name != 'guides' && project.name != 'spring-security-bom' }
|
||||
ext.sampleProjects = subprojects.findAll { project -> project.name.startsWith('spring-security-samples') }
|
||||
ext.itestProjects = subprojects.findAll { project -> project.name.startsWith('itest') }
|
||||
ext.coreModuleProjects = javaProjects - sampleProjects - itestProjects
|
||||
@@ -76,7 +82,7 @@ configure(allprojects - javaProjects) {
|
||||
}
|
||||
}
|
||||
|
||||
configure(subprojects - coreModuleProjects) {
|
||||
configure(subprojects - coreModuleProjects - project(':spring-security-samples-messages-jc') - project(':spring-security-bom')) {
|
||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
sonarRunner {
|
||||
skipProject = true
|
||||
@@ -106,7 +112,7 @@ configure(coreModuleProjects) {
|
||||
configurations.spring4TestRuntime {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.springframework') {
|
||||
details.useVersion '4.0.0.RC1'
|
||||
details.useVersion spring4Version
|
||||
}
|
||||
if (details.requested.name == 'ehcache') {
|
||||
details.useVersion '2.6.5'
|
||||
@@ -114,6 +120,9 @@ configure(coreModuleProjects) {
|
||||
if (details.requested.name == 'ehcache-terracotta') {
|
||||
details.useVersion '2.1.1'
|
||||
}
|
||||
if (details.requested.group == 'org.springframework.ldap') {
|
||||
details.useVersion springLdap2Version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,5 +194,5 @@ artifacts {
|
||||
}
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '1.8'
|
||||
gradleVersion = '1.10-rc-2'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.plugins.*
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
public class MavenBomPlugin implements Plugin<Project> {
|
||||
static String MAVEN_BOM_TASK_NAME = "mavenBom"
|
||||
|
||||
public void apply(Project project) {
|
||||
project.plugins.apply(JavaPlugin)
|
||||
project.plugins.apply(MavenPlugin)
|
||||
project.task(MAVEN_BOM_TASK_NAME, type: MavenBomTask, group: 'Generate', description: 'Configures the pom as a Maven Build of Materials (BOM)')
|
||||
project.install.dependsOn project.mavenBom
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import groovy.xml.MarkupBuilder
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
public class MavenBomTask extends DefaultTask {
|
||||
|
||||
Set<Project> projects
|
||||
|
||||
File bomFile
|
||||
|
||||
|
||||
public MavenBomTask() {
|
||||
this.group = "Generate"
|
||||
this.description = "Generates a Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies"
|
||||
this.projects = project.subprojects
|
||||
this.bomFile = project.file("${->project.buildDir}/maven-bom/${->project.name}-${->project.version}.txt")
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void configureBom() {
|
||||
project.configurations.archives.artifacts.clear()
|
||||
|
||||
bomFile.parentFile.mkdirs()
|
||||
bomFile.write("Maven Build of Materials (BOM). See http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies")
|
||||
project.artifacts {
|
||||
// work around GRADLE-2406 by attaching text artifact
|
||||
archives(bomFile)
|
||||
}
|
||||
project.install {
|
||||
repositories.mavenInstaller {
|
||||
pom.whenConfigured {
|
||||
packaging = "pom"
|
||||
withXml {
|
||||
asNode().children().last() + {
|
||||
delegate.dependencyManagement {
|
||||
delegate.dependencies {
|
||||
projects.sort { dep -> "$dep.group:$dep.name" }.each { p ->
|
||||
|
||||
delegate.dependency {
|
||||
delegate.groupId(p.group)
|
||||
delegate.artifactId(p.name)
|
||||
delegate.version(p.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=MavenBomPlugin
|
||||
+15
-21
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<name>spring-security-cas</name>
|
||||
<description>spring-security-cas</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -94,7 +88,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -150,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -35,6 +35,7 @@ dependencies {
|
||||
"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.hibernate:hibernate-entitymanager:4.1.0.Final",
|
||||
@@ -46,13 +47,16 @@ dependencies {
|
||||
"org.apache.directory.server:apacheds-server-jndi:$apacheDsVersion",
|
||||
'org.apache.directory.shared:shared-ldap:0.9.15',
|
||||
'ldapsdk:ldapsdk:4.1',
|
||||
powerMockDependencies
|
||||
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"
|
||||
testCompile('org.openid4java:openid4java-nodeps:0.9.6') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
}
|
||||
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion",
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:2.2"
|
||||
}
|
||||
|
||||
@@ -60,10 +64,6 @@ test {
|
||||
inputs.file file("$rootDir/docs/manual/src/docbook/appendix-namespace.xml")
|
||||
}
|
||||
|
||||
integrationTest {
|
||||
systemProperties['apacheDSWorkDir'] = "${buildDir}/apacheDSWork"
|
||||
}
|
||||
|
||||
rncToXsd {
|
||||
rncDir = file('src/main/resources/org/springframework/security/config/')
|
||||
xsdDir = rncDir
|
||||
|
||||
+60
-36
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<name>spring-security-config</name>
|
||||
<description>spring-security-config</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,31 +52,31 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -108,49 +102,49 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-ldap</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-openid</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -172,12 +166,6 @@
|
||||
<version>0.9.29</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
@@ -244,6 +232,12 @@
|
||||
<version>1.4</version>
|
||||
<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>
|
||||
@@ -256,6 +250,24 @@
|
||||
<version>4.1.0.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>3.6.10.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.2.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
@@ -322,6 +334,18 @@
|
||||
<version>0.7-groovy-2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.2.0.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ldap</groupId>
|
||||
<artifactId>spring-ldap-core</artifactId>
|
||||
@@ -331,25 +355,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-cas</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+12
@@ -26,6 +26,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
|
||||
import org.springframework.security.config.annotation.authentication.ldap.NamespaceLdapAuthenticationProviderTestsConfigs.LdapAuthenticationProviderConfig;
|
||||
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;
|
||||
|
||||
@@ -57,6 +58,17 @@ class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec {
|
||||
provider.authenticator.userSearch.searchFilter == "(uid={0})"
|
||||
}
|
||||
|
||||
def "SEC-2490: ldap-authentication-provider custom LdapAuthoritiesPopulator"() {
|
||||
setup:
|
||||
LdapAuthoritiesPopulator LAP = Mock()
|
||||
CustomAuthoritiesPopulatorConfig.LAP = LAP
|
||||
when:
|
||||
loadConfig(CustomAuthoritiesPopulatorConfig)
|
||||
LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
|
||||
then:
|
||||
provider.authoritiesPopulator == LAP
|
||||
}
|
||||
|
||||
def "ldap-authentication-provider password compare"() {
|
||||
when:
|
||||
loadConfig(PasswordCompareLdapConfig)
|
||||
|
||||
+13
@@ -20,6 +20,7 @@ import org.springframework.security.authentication.encoding.PlaintextPasswordEnc
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.PersonContextMapper;
|
||||
|
||||
/**
|
||||
@@ -65,6 +66,18 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class CustomAuthoritiesPopulatorConfig extends WebSecurityConfigurerAdapter {
|
||||
static LdapAuthoritiesPopulator LAP;
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.userSearchFilter("(uid={0})")
|
||||
.ldapAuthoritiesPopulator(LAP);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
+20
-4
@@ -12,7 +12,10 @@
|
||||
*/
|
||||
package org.springframework.security.config.ldap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
@@ -50,10 +53,11 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useOfUrlAttributeCreatesCorrectContextSource() {
|
||||
public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception {
|
||||
int port = getDefaultPort();
|
||||
// Create second "server" with a url pointing at embedded one
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='33388'/>" +
|
||||
"<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:33388/dc=springframework,dc=org' />");
|
||||
appCtx = new InMemoryXmlApplicationContext("<ldap-server ldif='classpath:test-server.ldif' port='" + port + "'/>" +
|
||||
"<ldap-server ldif='classpath:test-server.ldif' id='blah' url='ldap://127.0.0.1:" + port + "/dc=springframework,dc=org' />");
|
||||
|
||||
// Check the default context source is still there.
|
||||
appCtx.getBean(BeanIds.CONTEXT_SOURCE);
|
||||
@@ -83,4 +87,16 @@ public class LdapServerBeanDefinitionParserTests {
|
||||
|
||||
assertEquals("classpath*:*.ldif", ReflectionTestUtils.getField(dsContainer, "ldifResources"));
|
||||
}
|
||||
|
||||
private int getDefaultPort() throws IOException {
|
||||
ServerSocket server = null;
|
||||
try {
|
||||
server = new ServerSocket(0);
|
||||
return server.getLocalPort();
|
||||
} finally {
|
||||
try {
|
||||
server.close();
|
||||
} catch(IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
|
||||
object = doBuild();
|
||||
return object;
|
||||
}
|
||||
throw new IllegalStateException("This object has already been built");
|
||||
throw new AlreadyBuiltException("This object has already been built");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation;
|
||||
|
||||
/**
|
||||
* Thrown when {@link AbstractSecurityBuilder#build()} is two or more times.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public class AlreadyBuiltException extends IllegalStateException {
|
||||
|
||||
public AlreadyBuiltException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -5891004752785553015L;
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ public interface SecurityBuilder<O> {
|
||||
* Builds the object and returns it or null.
|
||||
*
|
||||
* @return the Object to be built or null if the implementation allows it.
|
||||
* @throws Exception if an error occured when building the Object
|
||||
* @throws Exception if an error occurred when building the Object
|
||||
*/
|
||||
O build() throws Exception;
|
||||
}
|
||||
|
||||
+31
@@ -18,6 +18,8 @@ package org.springframework.security.config.annotation.authentication.builders;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
@@ -25,6 +27,7 @@ import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||
@@ -45,6 +48,7 @@ import org.springframework.util.Assert;
|
||||
* @since 3.2
|
||||
*/
|
||||
public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder> implements ProviderManagerBuilder<AuthenticationManagerBuilder> {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private AuthenticationManager parentAuthenticationManager;
|
||||
private List<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>();
|
||||
@@ -74,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;
|
||||
}
|
||||
@@ -218,6 +225,10 @@ public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuil
|
||||
|
||||
@Override
|
||||
protected ProviderManager performBuild() throws Exception {
|
||||
if(!isConfigured()) {
|
||||
logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
|
||||
return null;
|
||||
}
|
||||
ProviderManager providerManager = new ProviderManager(authenticationProviders, parentAuthenticationManager);
|
||||
if(eraseCredentials != null) {
|
||||
providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
|
||||
@@ -229,6 +240,26 @@ public class AuthenticationManagerBuilder extends AbstractConfiguredSecurityBuil
|
||||
return providerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the {@link AuthenticationManagerBuilder} is configured to
|
||||
* build a non null {@link AuthenticationManager}. This means that either a
|
||||
* non-null parent is specified or at least one
|
||||
* {@link AuthenticationProvider} has been specified.
|
||||
*
|
||||
* <p>
|
||||
* When using {@link SecurityConfigurer} instances, the
|
||||
* {@link AuthenticationManagerBuilder} will not be configured until the
|
||||
* {@link SecurityConfigurer#configure(SecurityBuilder)} methods. This means
|
||||
* a {@link SecurityConfigurer} that is last could check this method and
|
||||
* provide a default configuration in the
|
||||
* {@link SecurityConfigurer#configure(SecurityBuilder)} method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isConfigured() {
|
||||
return !authenticationProviders.isEmpty() || parentAuthenticationManager != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default {@link UserDetailsService} for the
|
||||
* {@link AuthenticationManagerBuilder}. The result may be null in some
|
||||
|
||||
+108
-1
@@ -15,10 +15,26 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.authentication.configuration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Exports the authentication {@link Configuration}
|
||||
@@ -29,9 +45,100 @@ import org.springframework.security.config.annotation.authentication.builders.Au
|
||||
*/
|
||||
@Configuration
|
||||
public class AuthenticationConfiguration {
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
private boolean authenticationManagerInitialized;
|
||||
|
||||
private List<GlobalAuthenticationConfigurerAdapter> globalAuthConfigures = Collections.emptyList();
|
||||
|
||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
@Bean
|
||||
public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
return new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
|
||||
return new EnableGlobalAuthenticationAutowiredConfigurer(context);
|
||||
}
|
||||
|
||||
public AuthenticationManager getAuthenticationManager() throws Exception {
|
||||
if(authenticationManagerInitialized) {
|
||||
return authenticationManager;
|
||||
}
|
||||
|
||||
AuthenticationManagerBuilder authBuilder = authenticationManagerBuilder(objectPostProcessor);
|
||||
for(GlobalAuthenticationConfigurerAdapter config : globalAuthConfigures) {
|
||||
authBuilder.apply(config);
|
||||
}
|
||||
|
||||
authenticationManager = authBuilder.build();
|
||||
|
||||
if(authenticationManager == null) {
|
||||
authenticationManager = getAuthenticationMangerBean();
|
||||
}
|
||||
|
||||
this.authenticationManagerInitialized = true;
|
||||
return authenticationManager;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setGlobalAuthenticationConfigurers(List<GlobalAuthenticationConfigurerAdapter> configurers) throws Exception {
|
||||
Collections.sort(configurers, AnnotationAwareOrderComparator.INSTANCE);
|
||||
this.globalAuthConfigures = configurers;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T lazyBean(Class<T> interfaceName) {
|
||||
LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource();
|
||||
String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, interfaceName);
|
||||
if(beanNamesForType.length == 0) {
|
||||
return null;
|
||||
}
|
||||
Assert.isTrue(beanNamesForType.length == 1 , "Expecting to only find a single bean for type " + interfaceName + ", but found " + Arrays.asList(beanNamesForType));
|
||||
lazyTargetSource.setTargetBeanName(beanNamesForType[0]);
|
||||
lazyTargetSource.setBeanFactory(applicationContext);
|
||||
ProxyFactoryBean proxyFactory = new ProxyFactoryBean();
|
||||
proxyFactory = objectPostProcessor.postProcess(proxyFactory);
|
||||
proxyFactory.setTargetSource(lazyTargetSource);
|
||||
proxyFactory.setInterfaces(new Class[] { interfaceName, LazyBean.class });
|
||||
return (T) proxyFactory.getObject();
|
||||
}
|
||||
|
||||
private AuthenticationManager getAuthenticationMangerBean() {
|
||||
return lazyBean(AuthenticationManager.class);
|
||||
}
|
||||
|
||||
private interface LazyBean {}
|
||||
|
||||
private static class EnableGlobalAuthenticationAutowiredConfigurer extends GlobalAuthenticationConfigurerAdapter {
|
||||
private final ApplicationContext context;
|
||||
private static final Log logger = LogFactory.getLog(EnableGlobalAuthenticationAutowiredConfigurer.class);
|
||||
|
||||
public EnableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(AuthenticationManagerBuilder auth) {
|
||||
Map<String, Object> beansWithAnnotation = context.getBeansWithAnnotation(EnableGlobalAuthentication.class);
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Eagerly initializing " + beansWithAnnotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.configuration;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
||||
|
||||
/**
|
||||
* The {@link EnableGlobalAuthentication} annotation signals that the annotated
|
||||
* class can be used to configure a global instance of
|
||||
* {@link AuthenticationManagerBuilder}. For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* @EnableGlobalAuthentication
|
||||
* public class MyGlobalAuthenticationConfiguration {
|
||||
*
|
||||
* @Autowired
|
||||
* public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("user").password("password").roles("USER").and()
|
||||
* .withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Annotations that are annotated with {@link EnableGlobalAuthentication} also
|
||||
* signal that the annotated class can be used to configure a global instance of
|
||||
* {@link AuthenticationManagerBuilder}. For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Autowired
|
||||
* public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("user").password("password").roles("USER").and()
|
||||
* .withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* }
|
||||
*
|
||||
* // Possibly overridden methods ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* The following annotations are annotated with {@link EnableGlobalAuthentication}
|
||||
*
|
||||
* <ul>
|
||||
* <li> {@link EnableWebSecurity} </li>
|
||||
* <li> {@link EnableWebMvcSecurity} </li>
|
||||
* <li> {@link EnableGlobalMethodSecurity} </li>
|
||||
* </ul>
|
||||
*
|
||||
* Configuring {@link AuthenticationManagerBuilder} in a class without the {@link EnableGlobalAuthentication} annotation has
|
||||
* unpredictable results.
|
||||
*
|
||||
* @see EnableWebMvcSecurity
|
||||
* @see EnableWebSecurity
|
||||
* @see EnableGlobalMethodSecurity
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value={java.lang.annotation.ElementType.TYPE})
|
||||
@Documented
|
||||
@Import(AuthenticationConfiguration.class)
|
||||
public @interface EnableGlobalAuthentication {}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.configurers;
|
||||
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
|
||||
/**
|
||||
* A {@link SecurityConfigurer} that can be exposed as a bean to configure the
|
||||
* global {@link AuthenticationManagerBuilder}. Beans of this type are
|
||||
* automatically used by {@link AuthenticationConfiguration} to configure the
|
||||
* global {@link AuthenticationManagerBuilder}.
|
||||
*
|
||||
* @since 3.2.1
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Order(100)
|
||||
public abstract class GlobalAuthenticationConfigurerAdapter implements SecurityConfigurer<AuthenticationManager, AuthenticationManagerBuilder> {
|
||||
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {}
|
||||
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {}
|
||||
}
|
||||
+33
-4
@@ -36,6 +36,7 @@ import org.springframework.security.ldap.search.LdapUserSearch;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper;
|
||||
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;
|
||||
@@ -61,15 +62,13 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
private UserDetailsContextMapper userDetailsContextMapper;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
private String passwordAttribute;
|
||||
private LdapAuthoritiesPopulator ldapAuthoritiesPopulator;
|
||||
|
||||
private LdapAuthenticationProvider build() throws Exception {
|
||||
BaseLdapPathContextSource contextSource = getContextSource();
|
||||
LdapAuthenticator ldapAuthenticator = createLdapAuthenticator(contextSource);
|
||||
|
||||
DefaultLdapAuthoritiesPopulator authoritiesPopulator = new DefaultLdapAuthoritiesPopulator(
|
||||
contextSource, groupSearchBase);
|
||||
authoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute);
|
||||
authoritiesPopulator.setGroupSearchFilter(groupSearchFilter);
|
||||
LdapAuthoritiesPopulator authoritiesPopulator = getLdapAuthoritiesPopulator();
|
||||
|
||||
LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(
|
||||
ldapAuthenticator, authoritiesPopulator);
|
||||
@@ -83,6 +82,17 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
return ldapAuthenticationProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link LdapAuthoritiesPopulator}.
|
||||
*
|
||||
* @param ldapAuthoritiesPopulator the {@link LdapAuthoritiesPopulator} the default is {@link DefaultLdapAuthoritiesPopulator}
|
||||
* @return the {@link LdapAuthenticationProviderConfigurer} for further customizations
|
||||
*/
|
||||
public LdapAuthenticationProviderConfigurer<B> ldapAuthoritiesPopulator(LdapAuthoritiesPopulator ldapAuthoritiesPopulator) {
|
||||
this.ldapAuthoritiesPopulator = ldapAuthoritiesPopulator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ObjectPostProcessor} for this class.
|
||||
*
|
||||
@@ -94,6 +104,25 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link LdapAuthoritiesPopulator} and defaults to {@link DefaultLdapAuthoritiesPopulator}
|
||||
*
|
||||
* @return the {@link LdapAuthoritiesPopulator}
|
||||
*/
|
||||
private LdapAuthoritiesPopulator getLdapAuthoritiesPopulator() {
|
||||
if(ldapAuthoritiesPopulator != null) {
|
||||
return ldapAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
DefaultLdapAuthoritiesPopulator defaultAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator(
|
||||
contextSource, groupSearchBase);
|
||||
defaultAuthoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute);
|
||||
defaultAuthoritiesPopulator.setGroupSearchFilter(groupSearchFilter);
|
||||
|
||||
this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator;
|
||||
return defaultAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link LdapAuthenticator} to use
|
||||
*
|
||||
|
||||
+3
-2
@@ -23,7 +23,7 @@ import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
|
||||
/**
|
||||
@@ -44,7 +44,8 @@ import org.springframework.security.config.annotation.configuration.ObjectPostPr
|
||||
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value={java.lang.annotation.ElementType.TYPE})
|
||||
@Documented
|
||||
@Import({GlobalMethodSecuritySelector.class,ObjectPostProcessorConfiguration.class,AuthenticationConfiguration.class})
|
||||
@Import({GlobalMethodSecuritySelector.class,ObjectPostProcessorConfiguration.class})
|
||||
@EnableGlobalAuthentication
|
||||
public @interface EnableGlobalMethodSecurity {
|
||||
|
||||
/**
|
||||
|
||||
+14
-35
@@ -16,19 +16,14 @@
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.framework.ProxyFactoryBean;
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
@@ -67,6 +62,7 @@ import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -81,7 +77,6 @@ import org.springframework.util.Assert;
|
||||
@Configuration
|
||||
public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
private static final Log logger = LogFactory.getLog(GlobalMethodSecurityConfiguration.class);
|
||||
private ApplicationContext context;
|
||||
private ObjectPostProcessor<Object> objectPostProcessor = new ObjectPostProcessor<Object>() {
|
||||
public <T> T postProcess(T object) {
|
||||
throw new IllegalStateException(ObjectPostProcessor.class.getName()+ " is a required bean. Ensure you have used @"+EnableGlobalMethodSecurity.class.getName());
|
||||
@@ -93,6 +88,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
private boolean disableAuthenticationRegistry;
|
||||
private AnnotationAttributes enableMethodSecurity;
|
||||
private MethodSecurityExpressionHandler expressionHandler;
|
||||
private AuthenticationConfiguration authenticationConfiguration;
|
||||
|
||||
/**
|
||||
* Creates the default MethodInterceptor which is a MethodSecurityInterceptor using the following methods to
|
||||
@@ -248,19 +244,11 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
auth = new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
auth.authenticationEventPublisher(eventPublisher);
|
||||
configure(auth);
|
||||
if(!disableAuthenticationRegistry) {
|
||||
if(disableAuthenticationRegistry) {
|
||||
authenticationManager = getAuthenticationConfiguration().getAuthenticationManager();
|
||||
} else {
|
||||
authenticationManager = auth.build();
|
||||
}
|
||||
if(authenticationManager == null) {
|
||||
try {
|
||||
authenticationManager = context.getBean(AuthenticationManagerBuilder.class).getOrBuild();
|
||||
} catch(NoSuchBeanDefinitionException e) {
|
||||
logger.debug("Could not obtain the AuthenticationManagerBuilder. This is ok for now, we will try using an AuthenticationManager directly",e);
|
||||
}
|
||||
}
|
||||
if(authenticationManager == null) {
|
||||
authenticationManager = lazyBean(AuthenticationManager.class);
|
||||
}
|
||||
}
|
||||
return authenticationManager;
|
||||
}
|
||||
@@ -351,11 +339,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
this.defaultMethodExpressionHandler.setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Autowired(required=false)
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
@@ -370,17 +353,14 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluators.get(0));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T lazyBean(Class<T> interfaceName) {
|
||||
LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource();
|
||||
String[] beanNamesForType = context.getBeanNamesForType(interfaceName);
|
||||
Assert.isTrue(beanNamesForType.length == 1 , "Expecting to only find a single bean for type " + interfaceName + ", but found " + Arrays.asList(beanNamesForType));
|
||||
lazyTargetSource.setTargetBeanName(beanNamesForType[0]);
|
||||
lazyTargetSource.setBeanFactory(context);
|
||||
ProxyFactoryBean proxyFactory = new ProxyFactoryBean();
|
||||
proxyFactory.setTargetSource(lazyTargetSource);
|
||||
proxyFactory.setInterfaces(new Class[] { interfaceName });
|
||||
return (T) proxyFactory.getObject();
|
||||
@Autowired(required = false)
|
||||
public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
|
||||
this.authenticationConfiguration = authenticationConfiguration;
|
||||
}
|
||||
|
||||
private AuthenticationConfiguration getAuthenticationConfiguration() {
|
||||
Assert.notNull(authenticationConfiguration, "authenticationConfiguration cannot be null");
|
||||
return authenticationConfiguration;
|
||||
}
|
||||
|
||||
private boolean prePostEnabled() {
|
||||
@@ -414,5 +394,4 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
|
||||
}
|
||||
return this.enableMethodSecurity;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -280,7 +280,10 @@ public final class WebSecurity extends
|
||||
|
||||
@Override
|
||||
protected Filter performBuild() throws Exception {
|
||||
Assert.state(!securityFilterChainBuilders.isEmpty(), "At least one SecurityFilterBuilder needs to be specified. Invoke FilterChainProxyBuilder.securityFilterChains");
|
||||
Assert.state(!securityFilterChainBuilders.isEmpty(),
|
||||
"At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke "
|
||||
+ WebSecurity.class.getSimpleName()
|
||||
+ ".addSecurityFilterChainBuilder directly");
|
||||
int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
|
||||
List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(chainSize);
|
||||
for(RequestMatcher ignoredRequest : ignoredRequests) {
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
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.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* A class used to get all the {@link WebSecurityConfigurer} instances from the
|
||||
* current {@link ApplicationContext} but ignoring the parent.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
final class AutowiredWebSecurityConfigurersIgnoreParents {
|
||||
|
||||
private final ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
public AutowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) {
|
||||
Assert.notNull(beanFactory,"beanFactory cannot be null");
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
|
||||
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<SecurityConfigurer<Filter, WebSecurity>>();
|
||||
Map<String, WebSecurityConfigurer> beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class);
|
||||
for(Entry<String,WebSecurityConfigurer> entry : beansOfType.entrySet()) {
|
||||
webSecurityConfigurers.add(entry.getValue());
|
||||
}
|
||||
return webSecurityConfigurers;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -20,7 +20,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
|
||||
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
|
||||
@@ -77,7 +77,8 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value={java.lang.annotation.ElementType.TYPE})
|
||||
@Documented
|
||||
@Import({WebSecurityConfiguration.class,ObjectPostProcessorConfiguration.class,AuthenticationConfiguration.class, SpringWebMvcImportSelector.class})
|
||||
@Import({WebSecurityConfiguration.class,ObjectPostProcessorConfiguration.class})
|
||||
@EnableGlobalAuthentication
|
||||
public @interface EnableWebSecurity {
|
||||
|
||||
/**
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Used by {@link EnableWebSecurity} to conditionaly import
|
||||
* {@link WebMvcSecurityConfiguration} when the DispatcherServlet is present on the
|
||||
* classpath.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
class SpringWebMvcImportSelector implements ImportSelector {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.annotation.ImportSelector#selectImports(org.springframework.core.type.AnnotationMetadata)
|
||||
*/
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader());
|
||||
return webmvcPresent ? new String[] {"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration"} : new String[] {};
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -23,6 +23,8 @@ import javax.servlet.Filter;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
@@ -110,7 +112,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
|
||||
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
|
||||
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
|
||||
webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
|
||||
if(debugEnabled != null) {
|
||||
webSecurity.debug(debugEnabled);
|
||||
@@ -132,6 +134,10 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
this.webSecurityConfigurers = webSecurityConfigurers;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) {
|
||||
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom verision of the Spring provided AnnotationAwareOrderComparator
|
||||
|
||||
+44
-27
@@ -16,20 +16,23 @@
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
@@ -42,6 +45,8 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
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;
|
||||
|
||||
@@ -53,6 +58,7 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Order(100)
|
||||
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {
|
||||
private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class);
|
||||
|
||||
@@ -66,9 +72,10 @@ 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();
|
||||
@@ -144,7 +151,7 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
this.disableAuthenticationRegistration = true;
|
||||
this.disableLocalConfigureAuthenticationBldr = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,11 +166,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);
|
||||
@@ -217,22 +224,11 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
*/
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
if(!authenticationManagerInitialized) {
|
||||
configure(parentAuthenticationBuilder);
|
||||
if(disableAuthenticationRegistration) {
|
||||
try {
|
||||
authenticationManager = context.getBean(AuthenticationManagerBuilder.class).getOrBuild();
|
||||
} catch(NoSuchBeanDefinitionException e) {
|
||||
logger.debug("Could not obtain the AuthenticationManagerBuilder. This is ok for now, we will try using an AuthenticationManager directly",e);
|
||||
}
|
||||
if(authenticationManager == null) {
|
||||
try {
|
||||
authenticationManager = context.getBean(AuthenticationManager.class);
|
||||
} catch(NoSuchBeanDefinitionException e) {
|
||||
logger.debug("The AuthenticationManager was not found. This is ok for now as it may not be required.",e);
|
||||
}
|
||||
}
|
||||
configure(localConfigureAuthenticationBldr);
|
||||
if(disableLocalConfigureAuthenticationBldr) {
|
||||
authenticationManager = authenticationConfiguration.getAuthenticationManager();
|
||||
} else {
|
||||
authenticationManager = parentAuthenticationBuilder.build();
|
||||
authenticationManager = localConfigureAuthenticationBldr.build();
|
||||
}
|
||||
authenticationManagerInitialized = true;
|
||||
}
|
||||
@@ -260,7 +256,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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,7 +269,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 {
|
||||
@@ -339,12 +335,12 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
this.contentNegotiationStrategy = contentNegotiationStrategy;
|
||||
}
|
||||
|
||||
@Autowired(required=false)
|
||||
@Autowired
|
||||
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
|
||||
authenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor);
|
||||
parentAuthenticationBuilder = new AuthenticationManagerBuilder(objectPostProcessor) {
|
||||
localConfigureAuthenticationBldr = new AuthenticationManagerBuilder(objectPostProcessor) {
|
||||
@Override
|
||||
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
|
||||
authenticationBuilder.eraseCredentials(eraseCredentials);
|
||||
@@ -354,6 +350,10 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
};
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
|
||||
this.authenticationConfiguration = authenticationConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays the use of the {@link UserDetailsService} from the
|
||||
@@ -414,8 +414,12 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
private AuthenticationManager delegate;
|
||||
private final Object delegateMonitor = new Object();
|
||||
|
||||
AuthenticationManagerDelegator(AuthenticationManagerBuilder authentication) {
|
||||
this.delegateBuilder = authentication;
|
||||
AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder) {
|
||||
Assert.notNull(delegateBuilder,"delegateBuilder cannot be null");
|
||||
Field parentAuthMgrField = ReflectionUtils.findField(AuthenticationManagerBuilder.class, "parentAuthenticationManager");
|
||||
ReflectionUtils.makeAccessible(parentAuthMgrField);
|
||||
validateBeanCycle(ReflectionUtils.getField(parentAuthMgrField, delegateBuilder));
|
||||
this.delegateBuilder = delegateBuilder;
|
||||
}
|
||||
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
@@ -432,5 +436,18 @@ public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigu
|
||||
|
||||
return delegate.authenticate(authentication);
|
||||
}
|
||||
|
||||
private static void validateBeanCycle(Object auth) {
|
||||
if(auth != null) {
|
||||
String lazyBeanClassName = AuthenticationConfiguration.class.getName() + "$LazyBean";
|
||||
Class<?>[] interfaces = auth.getClass().getInterfaces();
|
||||
for(Class<?> i : interfaces) {
|
||||
String className = i.getName();
|
||||
if(className.equals(lazyBeanClassName)) {
|
||||
throw new FatalBeanException("A dependency cycle was detected when trying to resolve the AuthenticationManager. Please ensure you have configured authentication.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
-6
@@ -15,14 +15,22 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
|
||||
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfLogoutHandler;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -50,6 +58,7 @@ import org.springframework.util.Assert;
|
||||
* <li>
|
||||
* {@link ExceptionHandlingConfigurer#accessDeniedHandler(AccessDeniedHandler)}
|
||||
* is used to determine how to handle CSRF attempts</li>
|
||||
* <li>{@link InvalidSessionStrategy}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -100,12 +109,9 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>> extends Abst
|
||||
if(requireCsrfProtectionMatcher != null) {
|
||||
filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher);
|
||||
}
|
||||
ExceptionHandlingConfigurer<H> exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
if(exceptionConfig != null) {
|
||||
AccessDeniedHandler accessDeniedHandler = exceptionConfig.getAccessDeniedHandler();
|
||||
if(accessDeniedHandler != null) {
|
||||
filter.setAccessDeniedHandler(accessDeniedHandler);
|
||||
}
|
||||
AccessDeniedHandler accessDeniedHandler = createAccessDeniedHandler(http);
|
||||
if(accessDeniedHandler != null) {
|
||||
filter.setAccessDeniedHandler(accessDeniedHandler);
|
||||
}
|
||||
LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);
|
||||
if(logoutConfigurer != null) {
|
||||
@@ -118,4 +124,70 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>> extends Abst
|
||||
filter = postProcess(filter);
|
||||
http.addFilter(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default {@link AccessDeniedHandler} from the
|
||||
* {@link ExceptionHandlingConfigurer#getAccessDeniedHandler()} or create a
|
||||
* {@link AccessDeniedHandlerImpl} if not available.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder}
|
||||
* @return the {@link AccessDeniedHandler}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private AccessDeniedHandler getDefaultAccessDeniedHandler(H http) {
|
||||
ExceptionHandlingConfigurer<H> exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
AccessDeniedHandler handler = null;
|
||||
if(exceptionConfig != null) {
|
||||
handler = exceptionConfig.getAccessDeniedHandler();
|
||||
}
|
||||
if(handler == null) {
|
||||
handler = new AccessDeniedHandlerImpl();
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default {@link InvalidSessionStrategy} from the
|
||||
* {@link SessionManagementConfigurer#getInvalidSessionStrategy()} or null
|
||||
* if not available.
|
||||
*
|
||||
* @param http
|
||||
* the {@link HttpSecurityBuilder}
|
||||
* @return the {@link InvalidSessionStrategy}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private InvalidSessionStrategy getInvalidSessionStrategy(H http) {
|
||||
SessionManagementConfigurer<H> sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
|
||||
if(sessionManagement == null) {
|
||||
return null;
|
||||
}
|
||||
return sessionManagement.getInvalidSessionStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link AccessDeniedHandler} from the result of
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} and
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)}. If
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)} is non-null, then
|
||||
* a {@link DelegatingAccessDeniedHandler} is used in combination with
|
||||
* {@link InvalidSessionAccessDeniedHandler} and the
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise,
|
||||
* only {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used.
|
||||
*
|
||||
* @param http the {@link HttpSecurityBuilder}
|
||||
* @return the {@link AccessDeniedHandler}
|
||||
*/
|
||||
private AccessDeniedHandler createAccessDeniedHandler(H http) {
|
||||
InvalidSessionStrategy invalidSessionStrategy = getInvalidSessionStrategy(http);
|
||||
AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(http);
|
||||
if(invalidSessionStrategy == null) {
|
||||
return defaultAccessDeniedHandler;
|
||||
}
|
||||
|
||||
InvalidSessionAccessDeniedHandler invalidSessionDeniedHandler = new InvalidSessionAccessDeniedHandler(invalidSessionStrategy);
|
||||
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers =
|
||||
new LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler>();
|
||||
handlers.put(MissingCsrfTokenException.class, invalidSessionDeniedHandler);
|
||||
return new DelegatingAccessDeniedHandler(handlers, defaultAccessDeniedHandler);
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -132,13 +132,11 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
*
|
||||
* @param requestMatchers the {@link RequestMatcher} instances to register to the {@link ConfigAttribute} instances
|
||||
* @param configAttributes the {@link ConfigAttribute} to be mapped by the {@link RequestMatcher} instances
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further customization.
|
||||
*/
|
||||
private ExpressionUrlAuthorizationConfigurer<H> interceptUrl(Iterable<? extends RequestMatcher> requestMatchers, Collection<ConfigAttribute> configAttributes) {
|
||||
private void interceptUrl(Iterable<? extends RequestMatcher> requestMatchers, Collection<ConfigAttribute> configAttributes) {
|
||||
for(RequestMatcher requestMatcher : requestMatchers) {
|
||||
REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-1
@@ -42,6 +42,7 @@ import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -66,6 +67,7 @@ import org.springframework.util.Assert;
|
||||
* <li>{@link RequestCache}</li>
|
||||
* <li>{@link SecurityContextRepository}</li>
|
||||
* <li>{@link SessionManagementConfigurer}</li>
|
||||
* <li>{@link InvalidSessionStrategy}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Used</h2>
|
||||
@@ -83,6 +85,7 @@ import org.springframework.util.Assert;
|
||||
public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<SessionManagementConfigurer<H>,H> {
|
||||
private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy();
|
||||
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
|
||||
private InvalidSessionStrategy invalidSessionStrategy;
|
||||
private List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<SessionAuthenticationStrategy>();
|
||||
private SessionRegistry sessionRegistry = new SessionRegistryImpl();
|
||||
private Integer maximumSessions;
|
||||
@@ -365,6 +368,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
}
|
||||
http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy());
|
||||
http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -375,7 +379,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
sessionManagementFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(sessionAuthenticationErrorUrl));
|
||||
}
|
||||
if(invalidSessionUrl != null) {
|
||||
sessionManagementFilter.setInvalidSessionStrategy(new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl));
|
||||
sessionManagementFilter.setInvalidSessionStrategy(getInvalidSessionStrategy());
|
||||
}
|
||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
||||
if(trustResolver != null) {
|
||||
@@ -391,6 +395,23 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link InvalidSessionStrategy} to use. If
|
||||
* {@link #invalidSessionUrl} is null, returns null otherwise
|
||||
* {@link SimpleRedirectInvalidSessionStrategy} is used.
|
||||
*
|
||||
* @return the {@link InvalidSessionStrategy} to use
|
||||
*/
|
||||
InvalidSessionStrategy getInvalidSessionStrategy() {
|
||||
if(invalidSessionUrl == null) {
|
||||
return null;
|
||||
}
|
||||
if(invalidSessionStrategy == null) {
|
||||
invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl);
|
||||
}
|
||||
return invalidSessionStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link SessionCreationPolicy}. Can not be null.
|
||||
* @return the {@link SessionCreationPolicy}
|
||||
|
||||
+5
-4
@@ -27,6 +27,7 @@ import org.springframework.security.access.vote.AuthenticatedVoter;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
@@ -48,10 +49,10 @@ import org.springframework.util.Assert;
|
||||
* <pre>
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http
|
||||
* .apply(new UrlAuthorizationConfigurer()).getRegistry()
|
||||
* .antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
* .antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
* .anyRequest().hasRole("USER")
|
||||
* .apply(new UrlAuthorizationConfigurer<HttpSecurity>()).getRegistry()
|
||||
* .antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
* .antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
* .anyRequest().hasRole("USER");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.servlet.configuration;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
|
||||
|
||||
|
||||
/**
|
||||
* Add this annotation to an {@code @Configuration} class to have the Spring Security
|
||||
* configuration integrate with Spring MVC.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@Target(value={java.lang.annotation.ElementType.TYPE})
|
||||
@Documented
|
||||
@Import(WebMvcSecurityConfiguration.class)
|
||||
@EnableGlobalAuthentication
|
||||
public @interface EnableWebMvcSecurity {
|
||||
}
|
||||
+6
-4
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
package org.springframework.security.config.annotation.web.servlet.configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
@@ -38,7 +39,8 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
* @since 3.2
|
||||
*/
|
||||
@Configuration
|
||||
class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
@EnableWebSecurity
|
||||
public class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(
|
||||
@@ -48,6 +50,6 @@ class WebMvcSecurityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public RequestDataValueProcessor requestDataValueProcessor() {
|
||||
return CsrfRequestDataValueProcessor.create();
|
||||
return new CsrfRequestDataValueProcessor();
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -128,6 +128,9 @@ final class AuthenticationConfigBuilder {
|
||||
private final BeanReference portResolver;
|
||||
private final BeanMetadataElement csrfLogoutHandler;
|
||||
|
||||
private String loginProcessingUrl;
|
||||
private String openidLoginProcessingUrl;
|
||||
|
||||
public AuthenticationConfigBuilder(Element element, ParserContext pc, SessionCreationPolicy sessionPolicy,
|
||||
BeanReference requestCache, BeanReference authenticationManager, BeanReference sessionStrategy, BeanReference portMapper, BeanReference portResolver, BeanMetadataElement csrfLogoutHandler) {
|
||||
this.httpElt = element;
|
||||
@@ -197,6 +200,7 @@ final class AuthenticationConfigBuilder {
|
||||
parser.parse(formLoginElt, pc);
|
||||
formFilter = parser.getFilterBean();
|
||||
formEntryPoint = parser.getEntryPointBean();
|
||||
loginProcessingUrl = parser.getLoginProcessingUrl();
|
||||
}
|
||||
|
||||
if (formFilter != null) {
|
||||
@@ -221,6 +225,7 @@ final class AuthenticationConfigBuilder {
|
||||
parser.parse(openIDLoginElt, pc);
|
||||
openIDFilter = parser.getFilterBean();
|
||||
openIDEntryPoint = parser.getEntryPointBean();
|
||||
openidLoginProcessingUrl = parser.getLoginProcessingUrl();
|
||||
|
||||
List<Element> attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE);
|
||||
|
||||
@@ -473,10 +478,12 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
if (formFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(formFilterId);
|
||||
loginPageFilter.addPropertyValue("authenticationUrl", loginProcessingUrl);
|
||||
}
|
||||
|
||||
if (openIDFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(openIDFilterId);
|
||||
loginPageFilter.addPropertyValue("openIDauthenticationUrl", openidLoginProcessingUrl);
|
||||
}
|
||||
|
||||
loginPageGenerationFilter = loginPageFilter.getBeanDefinition();
|
||||
|
||||
+56
-4
@@ -15,17 +15,26 @@
|
||||
*/
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
|
||||
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfLogoutHandler;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
@@ -44,12 +53,12 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private static final String ATT_REPOSITORY = "token-repository-ref";
|
||||
|
||||
private String csrfRepositoryRef;
|
||||
private BeanDefinition csrfFilter;
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
boolean webmvcPresent = ClassUtils.isPresent(DISPATCHER_SERVLET_CLASS_NAME, getClass().getClassLoader());
|
||||
if(webmvcPresent) {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(CsrfRequestDataValueProcessor.class);
|
||||
beanDefinition.setFactoryMethodName("create");
|
||||
BeanComponentDefinition componentDefinition =
|
||||
new BeanComponentDefinition(beanDefinition, REQUEST_DATA_VALUE_PROCESSOR);
|
||||
pc.registerBeanComponent(componentDefinition);
|
||||
@@ -58,21 +67,64 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
|
||||
csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
|
||||
String matcherRef = element.getAttribute(ATT_MATCHER);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class);
|
||||
|
||||
if(!StringUtils.hasText(csrfRepositoryRef)) {
|
||||
RootBeanDefinition csrfTokenRepository = new RootBeanDefinition(HttpSessionCsrfTokenRepository.class);
|
||||
csrfRepositoryRef = pc.getReaderContext().generateBeanName(csrfTokenRepository);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(csrfTokenRepository, csrfRepositoryRef));
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class);
|
||||
builder.addConstructorArgReference(csrfRepositoryRef);
|
||||
|
||||
if(StringUtils.hasText(matcherRef)) {
|
||||
builder.addPropertyReference("requireCsrfProtectionMatcher", matcherRef);
|
||||
}
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
csrfFilter = builder.getBeanDefinition();
|
||||
return csrfFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the AccessDeniedHandler on the {@link CsrfFilter}
|
||||
*
|
||||
* @param invalidSessionStrategy the {@link InvalidSessionStrategy} to use
|
||||
* @param defaultDeniedHandler the {@link AccessDeniedHandler} to use
|
||||
*/
|
||||
void initAccessDeniedHandler(BeanDefinition invalidSessionStrategy, BeanMetadataElement defaultDeniedHandler) {
|
||||
BeanMetadataElement accessDeniedHandler = createAccessDeniedHandler(invalidSessionStrategy, defaultDeniedHandler);
|
||||
csrfFilter.getPropertyValues().addPropertyValue("accessDeniedHandler", accessDeniedHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link AccessDeniedHandler} from the result of
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} and
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)}. If
|
||||
* {@link #getInvalidSessionStrategy(HttpSecurityBuilder)} is non-null, then
|
||||
* a {@link DelegatingAccessDeniedHandler} is used in combination with
|
||||
* {@link InvalidSessionAccessDeniedHandler} and the
|
||||
* {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise,
|
||||
* only {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used.
|
||||
*
|
||||
* @param invalidSessionStrategy the {@link InvalidSessionStrategy} to use
|
||||
* @param defaultDeniedHandler the {@link AccessDeniedHandler} to use
|
||||
*
|
||||
* @return the {@link BeanMetadataElement} that is the {@link AccessDeniedHandler} to populate on the {@link CsrfFilter}
|
||||
*/
|
||||
private BeanMetadataElement createAccessDeniedHandler(BeanDefinition invalidSessionStrategy, BeanMetadataElement defaultDeniedHandler) {
|
||||
if(invalidSessionStrategy == null) {
|
||||
return defaultDeniedHandler;
|
||||
}
|
||||
ManagedMap<Class<? extends AccessDeniedException>,BeanDefinition> handlers =
|
||||
new ManagedMap<Class<? extends AccessDeniedException>, BeanDefinition>();
|
||||
BeanDefinitionBuilder invalidSessionHandlerBldr = BeanDefinitionBuilder.rootBeanDefinition(InvalidSessionAccessDeniedHandler.class);
|
||||
invalidSessionHandlerBldr.addConstructorArgValue(invalidSessionStrategy);
|
||||
handlers.put(MissingCsrfTokenException.class, invalidSessionHandlerBldr.getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder deniedBldr = BeanDefinitionBuilder.rootBeanDefinition(DelegatingAccessDeniedHandler.class);
|
||||
deniedBldr.addConstructorArgValue(handlers);
|
||||
deniedBldr.addConstructorArgValue(defaultDeniedHandler);
|
||||
|
||||
return deniedBldr.getBeanDefinition();
|
||||
}
|
||||
|
||||
BeanDefinition getCsrfAuthenticationStrategy() {
|
||||
|
||||
+11
-1
@@ -66,6 +66,7 @@ public class FormLoginBeanDefinitionParser {
|
||||
private RootBeanDefinition filterBean;
|
||||
private RootBeanDefinition entryPointBean;
|
||||
private String loginPage;
|
||||
private String loginProcessingUrl;
|
||||
|
||||
FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName,
|
||||
BeanReference requestCache, BeanReference sessionStrategy, boolean allowSessionCreation, BeanReference portMapper, BeanReference portResolver) {
|
||||
@@ -148,7 +149,12 @@ public class FormLoginBeanDefinitionParser {
|
||||
loginUrl = defaultLoginProcessingUrl;
|
||||
}
|
||||
|
||||
filterBuilder.addPropertyValue("filterProcessesUrl", loginUrl);
|
||||
this.loginProcessingUrl = loginUrl;
|
||||
|
||||
BeanDefinitionBuilder matcherBuilder = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.web.authentication.logout.LogoutFilter$FilterProcessUrlRequestMatcher");
|
||||
matcherBuilder.addConstructorArgValue(loginUrl);
|
||||
|
||||
filterBuilder.addPropertyValue("requiresAuthenticationRequestMatcher", matcherBuilder.getBeanDefinition());
|
||||
|
||||
if (StringUtils.hasText(successHandlerRef)) {
|
||||
filterBuilder.addPropertyReference("authenticationSuccessHandler", successHandlerRef);
|
||||
@@ -201,4 +207,8 @@ public class FormLoginBeanDefinitionParser {
|
||||
String getLoginPage() {
|
||||
return loginPage;
|
||||
}
|
||||
|
||||
String getLoginProcessingUrl() {
|
||||
return loginProcessingUrl;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-6
@@ -130,6 +130,10 @@ class HttpConfigurationBuilder {
|
||||
private BeanMetadataElement csrfLogoutHandler;
|
||||
private BeanMetadataElement csrfAuthStrategy;
|
||||
|
||||
private CsrfBeanDefinitionParser csrfParser;
|
||||
|
||||
private BeanDefinition invalidSession;
|
||||
|
||||
public HttpConfigurationBuilder(Element element, ParserContext pc,
|
||||
BeanReference portMapper, BeanReference portResolver, BeanReference authenticationManager) {
|
||||
this.httpElt = element;
|
||||
@@ -200,8 +204,8 @@ class HttpConfigurationBuilder {
|
||||
}
|
||||
|
||||
void setAccessDeniedHandler(BeanMetadataElement accessDeniedHandler) {
|
||||
if(csrfFilter != null) {
|
||||
csrfFilter.getPropertyValues().add("accessDeniedHandler", accessDeniedHandler);
|
||||
if(csrfParser != null ) {
|
||||
csrfParser.initAccessDeniedHandler(this.invalidSession, accessDeniedHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +385,10 @@ class HttpConfigurationBuilder {
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(invalidSessionUrl)) {
|
||||
sessionMgmtFilter.addPropertyValue("invalidSessionStrategy", new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl));
|
||||
BeanDefinitionBuilder invalidSessionBldr = BeanDefinitionBuilder.rootBeanDefinition(SimpleRedirectInvalidSessionStrategy.class);
|
||||
invalidSessionBldr.addConstructorArgValue(invalidSessionUrl);
|
||||
invalidSession = invalidSessionBldr.getBeanDefinition();
|
||||
sessionMgmtFilter.addPropertyValue("invalidSessionStrategy", invalidSession);
|
||||
}
|
||||
|
||||
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
|
||||
@@ -637,14 +644,16 @@ class HttpConfigurationBuilder {
|
||||
|
||||
}
|
||||
|
||||
private void createCsrfFilter() {
|
||||
private CsrfBeanDefinitionParser createCsrfFilter() {
|
||||
Element elmt = DomUtils.getChildElementByTagName(httpElt, Elements.CSRF);
|
||||
if (elmt != null) {
|
||||
CsrfBeanDefinitionParser csrfParser = new CsrfBeanDefinitionParser();
|
||||
this.csrfFilter = csrfParser.parse(elmt, pc);
|
||||
csrfParser = new CsrfBeanDefinitionParser();
|
||||
csrfFilter = csrfParser.parse(elmt, pc);
|
||||
this.csrfAuthStrategy = csrfParser.getCsrfAuthenticationStrategy();
|
||||
this.csrfLogoutHandler = csrfParser.getCsrfLogoutHandler();
|
||||
return csrfParser;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
BeanMetadataElement getCsrfLogoutHandler() {
|
||||
|
||||
+19
-2
@@ -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,7 +80,9 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
if (!StringUtils.hasText(logoutUrl)) {
|
||||
logoutUrl = DEF_LOGOUT_URL;
|
||||
}
|
||||
builder.addPropertyValue("filterProcessesUrl", logoutUrl);
|
||||
|
||||
|
||||
builder.addPropertyValue("logoutRequestMatcher", getLogoutRequestMatcher(logoutUrl));
|
||||
|
||||
if (StringUtils.hasText(successHandlerRef)) {
|
||||
if (StringUtils.hasText(logoutSuccessUrl)) {
|
||||
@@ -114,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
-3
@@ -132,12 +132,12 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
if (tokenValiditySet) {
|
||||
int tokenValidity = Integer.parseInt(tokenValiditySeconds);
|
||||
if (tokenValidity < 0 && isPersistent) {
|
||||
boolean isTokenValidityNegative = tokenValiditySeconds.startsWith("-");
|
||||
if (isTokenValidityNegative && isPersistent) {
|
||||
pc.getReaderContext().error(ATT_TOKEN_VALIDITY + " cannot be negative if using" +
|
||||
" a persistent remember-me token repository", source);
|
||||
}
|
||||
services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValidity);
|
||||
services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValiditySeconds);
|
||||
}
|
||||
|
||||
if (remembermeParameterSet) {
|
||||
|
||||
+32
-2
@@ -1,5 +1,8 @@
|
||||
package org.springframework.security.config.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -9,6 +12,7 @@ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -40,7 +44,8 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
/** Defines the port the LDAP_PROVIDER server should run on */
|
||||
public static final String ATT_PORT = "port";
|
||||
public static final String OPT_DEFAULT_PORT = "33389";
|
||||
private static final int DEFAULT_PORT = 33389;
|
||||
public static final String OPT_DEFAULT_PORT = String.valueOf(DEFAULT_PORT);
|
||||
|
||||
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||
@@ -101,7 +106,10 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String port = element.getAttribute(ATT_PORT);
|
||||
|
||||
if (!StringUtils.hasText(port)) {
|
||||
port = OPT_DEFAULT_PORT;
|
||||
port = getDefaultPort();
|
||||
if(logger.isDebugEnabled()) {
|
||||
logger.debug("Using default port of " + port);
|
||||
}
|
||||
}
|
||||
|
||||
String url = "ldap://127.0.0.1:" + port + "/" + suffix;
|
||||
@@ -134,4 +142,26 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
return (RootBeanDefinition) contextSource.getBeanDefinition();
|
||||
}
|
||||
|
||||
private String getDefaultPort() {
|
||||
ServerSocket serverSocket = null;
|
||||
try {
|
||||
try {
|
||||
serverSocket = new ServerSocket(DEFAULT_PORT);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
serverSocket = new ServerSocket(0);
|
||||
} catch(IOException e2) {
|
||||
return String.valueOf(DEFAULT_PORT);
|
||||
}
|
||||
}
|
||||
return String.valueOf(serverSocket.getLocalPort());
|
||||
} finally {
|
||||
if(serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ http-firewall =
|
||||
element http-firewall {ref}
|
||||
|
||||
http =
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "secured" attribute to "false".
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "security" attribute to "none".
|
||||
element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & openid-login? & x509? & jee? & http-basic? & logout? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler?) }
|
||||
http.attlist &=
|
||||
## The request URL pattern which will be mapped to the filter chain created by this <http> element. If omitted, the filter chain will match all requests.
|
||||
|
||||
+1
-1
@@ -868,7 +868,7 @@
|
||||
<xs:documentation>Container element for HTTP security configuration. Multiple elements can now be defined,
|
||||
each with a specific pattern to which the enclosed security configuration applies. A
|
||||
pattern can also be configured to bypass Spring Security's filters completely by setting
|
||||
the "secured" attribute to "false".
|
||||
the "security" attribute to "none".
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
|
||||
+3
-3
@@ -280,7 +280,7 @@ http-firewall =
|
||||
element http-firewall {ref}
|
||||
|
||||
http =
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "secured" attribute to "false".
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "security" attribute to "none".
|
||||
element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & openid-login? & x509? & jee? & http-basic? & logout? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler? & headers? & csrf?) }
|
||||
http.attlist &=
|
||||
## The request URL pattern which will be mapped to the filter chain created by this <http> element. If omitted, the filter chain will match all requests.
|
||||
@@ -357,7 +357,7 @@ intercept-url.attlist &=
|
||||
attribute access {xsd:token}?
|
||||
intercept-url.attlist &=
|
||||
## The HTTP Method for which the access configuration attributes should apply. If not specified, the attributes will apply to any method.
|
||||
attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "TRACE"}?
|
||||
attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "PATCH" | "TRACE"}?
|
||||
|
||||
intercept-url.attlist &=
|
||||
## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.
|
||||
@@ -572,7 +572,7 @@ remember-me.attlist &=
|
||||
|
||||
remember-me.attlist &=
|
||||
## The period (in seconds) for which the remember-me cookie should be valid.
|
||||
attribute token-validity-seconds {xsd:integer}?
|
||||
attribute token-validity-seconds {xsd:string}?
|
||||
|
||||
remember-me.attlist &=
|
||||
## Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful remember-me authentication.
|
||||
|
||||
+3
-2
@@ -868,7 +868,7 @@
|
||||
<xs:documentation>Container element for HTTP security configuration. Multiple elements can now be defined,
|
||||
each with a specific pattern to which the enclosed security configuration applies. A
|
||||
pattern can also be configured to bypass Spring Security's filters completely by setting
|
||||
the "secured" attribute to "false".
|
||||
the "security" attribute to "none".
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
@@ -1248,6 +1248,7 @@
|
||||
<xs:enumeration value="OPTIONS"/>
|
||||
<xs:enumeration value="POST"/>
|
||||
<xs:enumeration value="PUT"/>
|
||||
<xs:enumeration value="PATCH"/>
|
||||
<xs:enumeration value="TRACE"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
@@ -1795,7 +1796,7 @@
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="token-validity-seconds" type="xs:integer">
|
||||
<xs:attribute name="token-validity-seconds" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The period (in seconds) for which the remember-me cookie should be valid.
|
||||
</xs:documentation>
|
||||
|
||||
+33
@@ -87,4 +87,37 @@ class AuthenticationManagerBuilderTests extends BaseSpringSpec {
|
||||
.withUser("admin").password("password").roles("USER","ADMIN")
|
||||
}
|
||||
}
|
||||
|
||||
def "isConfigured with AuthenticationProvider"() {
|
||||
setup:
|
||||
ObjectPostProcessor opp = Mock()
|
||||
AuthenticationProvider provider = Mock()
|
||||
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
|
||||
when:
|
||||
auth
|
||||
.authenticationProvider(provider)
|
||||
then:
|
||||
auth.isConfigured()
|
||||
}
|
||||
|
||||
def "isConfigured with parent"() {
|
||||
setup:
|
||||
ObjectPostProcessor opp = Mock()
|
||||
AuthenticationManager parent = Mock()
|
||||
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
|
||||
when:
|
||||
auth
|
||||
.parentAuthenticationManager(parent)
|
||||
then:
|
||||
auth.isConfigured()
|
||||
}
|
||||
|
||||
def "isConfigured not configured"() {
|
||||
setup:
|
||||
ObjectPostProcessor opp = Mock()
|
||||
when:
|
||||
AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
|
||||
then:
|
||||
auth.isConfigured() == false
|
||||
}
|
||||
}
|
||||
|
||||
+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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 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.configuration;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactoryBean
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.core.Ordered
|
||||
import org.springframework.core.annotation.Order
|
||||
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.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
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.core.authority.AuthorityUtils
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager
|
||||
|
||||
class AuthenticationConfigurationTests extends BaseSpringSpec {
|
||||
|
||||
def "Ordering Autowired on EnableGlobalMethodSecurity"() {
|
||||
setup:
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
when:
|
||||
loadConfig(GlobalMethodSecurityAutowiredConfigAndServicesConfig)
|
||||
then:
|
||||
context.getBean(Service).run()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import([GlobalMethodSecurityAutowiredConfig,ServicesConfig])
|
||||
static class GlobalMethodSecurityAutowiredConfigAndServicesConfig {}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
static class GlobalMethodSecurityAutowiredConfig {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
|
||||
def "Ordering Autowired on EnableWebSecurity"() {
|
||||
setup:
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
when:
|
||||
loadConfig(GlobalMethodSecurityConfigAndServicesConfig)
|
||||
then:
|
||||
context.getBean(Service).run()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import([GlobalMethodSecurityConfig,WebSecurityConfig,ServicesConfig])
|
||||
static class GlobalMethodSecurityConfigAndServicesConfig {}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(securedEnabled = true)
|
||||
static class GlobalMethodSecurityConfig {}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
def "Ordering Autowired on EnableWebMvcSecurity"() {
|
||||
setup:
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
when:
|
||||
loadConfig(GlobalMethodSecurityMvcSecurityAndServicesConfig)
|
||||
then:
|
||||
context.getBean(Service).run()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import([GlobalMethodSecurityConfig,WebMvcSecurityConfig,ServicesConfig])
|
||||
static class GlobalMethodSecurityMvcSecurityAndServicesConfig {}
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvcSecurity
|
||||
static class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
def "no authentication getAuthenticationManager falls back to null"() {
|
||||
when:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
|
||||
then:
|
||||
context.getBean(AuthenticationConfiguration).authenticationManager == null
|
||||
}
|
||||
|
||||
def "QuiesentGlobalAuthenticationConfiguererAdapter falls back to null"() {
|
||||
when:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,QuiesentGlobalAuthenticationConfiguererAdapter)
|
||||
then:
|
||||
context.getBean(AuthenticationConfiguration).authenticationManager == null
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class QuiesentGlobalAuthenticationConfiguererAdapter extends GlobalAuthenticationConfigurerAdapter {}
|
||||
|
||||
//
|
||||
|
||||
def "GlobalAuthenticationConfiguererAdapterImpl configures authentication successfully"() {
|
||||
setup:
|
||||
def token = new UsernamePasswordAuthenticationToken("user", "password")
|
||||
when:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,GlobalAuthenticationConfiguererAdapterImpl)
|
||||
then:
|
||||
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token)?.name == "user"
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class GlobalAuthenticationConfiguererAdapterImpl extends GlobalAuthenticationConfigurerAdapter {
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
def "AuthenticationManagerBean configures authentication successfully"() {
|
||||
setup:
|
||||
def token = new UsernamePasswordAuthenticationToken("user", "password")
|
||||
def auth = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
|
||||
AuthenticationManagerBeanConfig.AM = Mock(AuthenticationManager)
|
||||
1 * AuthenticationManagerBeanConfig.AM.authenticate(token) >> auth
|
||||
when:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,AuthenticationManagerBeanConfig)
|
||||
then:
|
||||
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token).name == auth.name
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AuthenticationManagerBeanConfig {
|
||||
static AuthenticationManager AM
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() {
|
||||
AM
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Configuration
|
||||
static class ServicesConfig {
|
||||
@Bean
|
||||
public Service service() {
|
||||
return new ServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
static interface Service {
|
||||
public void run();
|
||||
}
|
||||
|
||||
static class ServiceImpl implements Service {
|
||||
@Secured("ROLE_USER")
|
||||
public void run() {}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
def "GlobalAuthenticationConfigurerAdapter are ordered"() {
|
||||
setup:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
|
||||
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
|
||||
config.setGlobalAuthenticationConfigurers([new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()])
|
||||
when:
|
||||
config.getAuthenticationManager()
|
||||
then:
|
||||
DefaultOrderGlobalAuthenticationConfigurerAdapter.inits == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
|
||||
DefaultOrderGlobalAuthenticationConfigurerAdapter.configs == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
|
||||
|
||||
}
|
||||
|
||||
static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
|
||||
static List inits = []
|
||||
static List configs = []
|
||||
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
inits.add(getClass())
|
||||
}
|
||||
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
configs.add(getClass())
|
||||
}
|
||||
}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
|
||||
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
|
||||
|
||||
//
|
||||
|
||||
def "Spring Boot not triggered when already configured"() {
|
||||
setup:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
|
||||
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
|
||||
config.setGlobalAuthenticationConfigurers([new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()])
|
||||
AuthenticationManager authenticationManager = config.authenticationManager
|
||||
when:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
|
||||
then:
|
||||
noExceptionThrown()
|
||||
when:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
|
||||
then:
|
||||
thrown(AuthenticationException)
|
||||
}
|
||||
|
||||
|
||||
def "Spring Boot is triggered when not already configured"() {
|
||||
setup:
|
||||
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
|
||||
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
|
||||
config.setGlobalAuthenticationConfigurers([new BootGlobalAuthenticationConfigurerAdapter()])
|
||||
AuthenticationManager authenticationManager = config.authenticationManager
|
||||
when:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
}
|
||||
}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter())
|
||||
}
|
||||
}
|
||||
|
||||
static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
if(auth.isConfigured()) {
|
||||
return;
|
||||
}
|
||||
|
||||
User user = new User("boot","password", AuthorityUtils.createAuthorityList("ROLE_USER"))
|
||||
|
||||
List<User> users = Arrays.asList(user);
|
||||
InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
|
||||
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
|
||||
provider.userDetailsService = inMemory
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.issue50;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.security.config.annotation.issue50.domain.User;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableJpaRepositories("org.springframework.security.config.annotation.issue50.repo")
|
||||
@EnableTransactionManagement
|
||||
public class ApplicationConfig {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
vendorAdapter.setDatabase(Database.HSQL);
|
||||
vendorAdapter.setGenerateDdl(true);
|
||||
vendorAdapter.setShowSql(true);
|
||||
|
||||
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
|
||||
factory.setJpaVendorAdapter(vendorAdapter);
|
||||
factory.setPackagesToScan(User.class.getPackage().getName());
|
||||
factory.setDataSource(dataSource());
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
JpaTransactionManager txManager = new JpaTransactionManager();
|
||||
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
|
||||
return txManager;
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.issue50;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.BadCredentialsException
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.config.annotation.issue50.domain.User
|
||||
import org.springframework.security.config.annotation.issue50.repo.UserRepository
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||
import org.springframework.security.web.FilterChainProxy
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration(classes=[ApplicationConfig,SecurityConfig])
|
||||
@Transactional
|
||||
class Issue50Tests extends Specification {
|
||||
@Autowired
|
||||
private FilterChainProxy springSecurityFilterChain
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager
|
||||
@Autowired
|
||||
private UserRepository userRepo
|
||||
|
||||
def setup() {
|
||||
SecurityContextHolder.context.authentication = new TestingAuthenticationToken("test",null,"ROLE_ADMIN")
|
||||
}
|
||||
|
||||
def cleanup() {
|
||||
SecurityContextHolder.clearContext()
|
||||
}
|
||||
|
||||
// https://github.com/SpringSource/spring-security-javaconfig/issues/50
|
||||
def "#50 - GlobalMethodSecurityConfiguration should load AuthenticationManager lazily"() {
|
||||
when:
|
||||
"Configuration Loads"
|
||||
then: "GlobalMethodSecurityConfiguration loads AuthenticationManager lazily"
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
def "AuthenticationManager will not authenticate missing user"() {
|
||||
when:
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("test", "password"))
|
||||
then:
|
||||
thrown(UsernameNotFoundException)
|
||||
}
|
||||
|
||||
def "AuthenticationManager will not authenticate with invalid password"() {
|
||||
when:
|
||||
User user = new User(username:"test",password:"password")
|
||||
userRepo.save(user)
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , "invalid"))
|
||||
then:
|
||||
thrown(BadCredentialsException)
|
||||
}
|
||||
|
||||
def "AuthenticationManager can be used to authenticate a user"() {
|
||||
when:
|
||||
User user = new User(username:"test",password:"password")
|
||||
userRepo.save(user)
|
||||
Authentication result = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , user.password))
|
||||
then:
|
||||
result.principal == user.username
|
||||
}
|
||||
|
||||
def "Global Method Security is enabled and works"() {
|
||||
setup:
|
||||
SecurityContextHolder.context.authentication = new TestingAuthenticationToken("test",null,"ROLE_USER")
|
||||
when:
|
||||
User user = new User(username:"denied",password:"password")
|
||||
userRepo.save(user)
|
||||
Authentication result = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.username , user.password))
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.issue50;
|
||||
|
||||
import org.spockframework.util.Assert;
|
||||
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;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.issue50.domain.User;
|
||||
import org.springframework.security.config.annotation.issue50.repo.UserRepository;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
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.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Configuration
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
private UserRepository myUserRepository;
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.authenticationProvider(authenticationProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/*").permitAll();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean()
|
||||
throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationProvider authenticationProvider() {
|
||||
Assert.notNull(myUserRepository);
|
||||
return new AuthenticationProvider() {
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return true;
|
||||
}
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
Object principal = authentication.getPrincipal();
|
||||
String username = String.valueOf(principal);
|
||||
User user = myUserRepository.findByUsername(username);
|
||||
if(user == null) {
|
||||
throw new UsernameNotFoundException("No user for principal "+principal);
|
||||
}
|
||||
if(!authentication.getCredentials().equals(user.getPassword())) {
|
||||
throw new BadCredentialsException("Invalid password");
|
||||
}
|
||||
return new TestingAuthenticationToken(principal, null, "ROLE_USER");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.issue50.domain;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
}
|
||||
+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.config.annotation.issue50.repo;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.config.annotation.issue50.domain.User;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
public interface UserRepository extends CrudRepository<User, String> {
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
User findByUsername(String username);
|
||||
}
|
||||
+69
@@ -19,8 +19,10 @@ import static org.fest.assertions.Assertions.assertThat
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
@@ -270,4 +272,71 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2425: EnableGlobalMethodSecurity works on superclass"() {
|
||||
setup:
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
loadConfig(ParentConfig)
|
||||
MethodSecurityService service = context.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
}
|
||||
|
||||
static class ChildConfig extends ParentConfig {}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
static class ParentConfig {
|
||||
|
||||
@Autowired
|
||||
protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MethodSecurityService service() {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2479: Support AuthenticationManager in parent"() {
|
||||
setup:
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "password","ROLE_USER"))
|
||||
loadConfig(Sec2479ParentConfig)
|
||||
def child = new AnnotationConfigApplicationContext()
|
||||
child.register(Sec2479ChildConfig)
|
||||
child.parent = context
|
||||
child.refresh()
|
||||
MethodSecurityService service = child.getBean(MethodSecurityService)
|
||||
when:
|
||||
service.preAuthorize()
|
||||
then:
|
||||
thrown(AccessDeniedException)
|
||||
cleanup:
|
||||
child?.close()
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Sec2479ParentConfig {
|
||||
static AuthenticationManager AM
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager am() {
|
||||
AM
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
static class Sec2479ChildConfig {
|
||||
@Bean
|
||||
public MethodSecurityService service() {
|
||||
new MethodSecurityServiceImpl()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -27,6 +27,9 @@ import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.Ordered
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator
|
||||
import org.springframework.core.annotation.Order
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver
|
||||
@@ -283,4 +286,18 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
|
||||
return TR
|
||||
}
|
||||
}
|
||||
|
||||
def "WebSecurityConfigurerAdapter has Ordered between 0 and lowest priority"() {
|
||||
when:
|
||||
def lowestConfig = new LowestPriorityWebSecurityConfig()
|
||||
def defaultConfig = new DefaultOrderWebSecurityConfig()
|
||||
def compare = new AnnotationAwareOrderComparator()
|
||||
then: "the default ordering is between 0 and lowest priority (Boot adapters)"
|
||||
compare.compare(lowestConfig, defaultConfig) > 0
|
||||
}
|
||||
|
||||
class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {}
|
||||
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {}
|
||||
}
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.builders;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.BaseWebConfig;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class DisableUseExpressionsConfig extends BaseWebConfig {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// This config is also on UrlAuthorizationConfigurer javadoc
|
||||
http
|
||||
.apply(new UrlAuthorizationConfigurer<HttpSecurity>()).getRegistry()
|
||||
.antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
.antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
.anyRequest().hasRole("USER");
|
||||
}
|
||||
}
|
||||
-12
@@ -501,16 +501,4 @@ public class NamespaceHttpTests extends BaseSpringSpec {
|
||||
findFilter(FilterSecurityInterceptor).securityMetadataSource.class == DefaultFilterInvocationSecurityMetadataSource
|
||||
findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [RoleVoter, AuthenticatedVoter]
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class DisableUseExpressionsConfig extends BaseWebConfig {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.apply(new UrlAuthorizationConfigurer()).getRegistry()
|
||||
.antMatchers("/users**","/sessions/**").hasRole("USER")
|
||||
.antMatchers("/signup").hasRole("ANONYMOUS")
|
||||
.anyRequest().hasRole("USER")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.FatalBeanException;
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
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 "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()
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
-14
@@ -17,31 +17,28 @@ package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.annotation.Order
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.expression.ExpressionParser
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity
|
||||
import org.springframework.security.web.FilterChainProxy
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.access.expression.WebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator
|
||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
|
||||
import org.springframework.security.web.access.expression.WebSecurityExpressionHandler
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.util.ReflectionTestUtils
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@@ -313,4 +310,36 @@ class WebSecurityConfigurationTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2461: Multiple WebSecurityConfiguration instances cause null springSecurityFilterChain"() {
|
||||
setup:
|
||||
def parent = loadConfig(ParentConfig)
|
||||
def child = new AnnotationConfigApplicationContext()
|
||||
child.register(ChildConfig)
|
||||
child.parent = parent
|
||||
when:
|
||||
child.refresh()
|
||||
then: "springSecurityFilterChain can be found in parent and child"
|
||||
parent.getBean("springSecurityFilterChain")
|
||||
child.getBean("springSecurityFilterChain")
|
||||
and: "springSecurityFilterChain is defined in both parent and child (don't search parent)"
|
||||
parent.containsBeanDefinition("springSecurityFilterChain")
|
||||
child.containsBeanDefinition("springSecurityFilterChain")
|
||||
cleanup:
|
||||
child?.close()
|
||||
// parent.close() is in superclass
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class ParentConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.inMemoryAuthentication()
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class ChildConfig extends WebSecurityConfigurerAdapter { }
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration.sec2377;
|
||||
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.web.configuration.sec2377.a.*
|
||||
import org.springframework.security.config.annotation.web.configuration.sec2377.b.*
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||
|
||||
public class Sec2377Tests extends BaseSpringSpec {
|
||||
|
||||
def "SEC-2377: Error reporting with multiple EnableWebSecurity from other packages"() {
|
||||
when:
|
||||
AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()
|
||||
parent.register(Sec2377AConfig)
|
||||
parent.refresh()
|
||||
|
||||
AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()
|
||||
child.register(Sec2377BConfig)
|
||||
child.parent = parent
|
||||
child.refresh()
|
||||
then:
|
||||
noExceptionThrown();
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration.sec2377.a;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class Sec2377AConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configuration.sec2377.b;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class Sec2377BConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.event.AuthorizedEvent;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class AuthorizedRequestsWithPostProcessorConfig extends WebSecurityConfigurerAdapter {
|
||||
static ApplicationListener<AuthorizedEvent> AL;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().permitAll()
|
||||
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
|
||||
public <O extends FilterSecurityInterceptor> O postProcess(
|
||||
O fsi) {
|
||||
fsi.setPublishAuthorizationSuccess(true);
|
||||
return fsi;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApplicationListener<AuthorizedEvent> applicationListener() {
|
||||
return AL;
|
||||
}
|
||||
}
|
||||
+89
-13
@@ -18,19 +18,21 @@ package org.springframework.security.config.annotation.web.configurers
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
import org.springframework.security.web.csrf.CsrfFilter
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor
|
||||
|
||||
import spock.lang.Unroll;
|
||||
import spock.lang.Unroll
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -69,7 +71,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvcSecurity
|
||||
static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@@ -100,6 +102,80 @@ 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)
|
||||
request.session.clearAttributes()
|
||||
request.setParameter("_csrf","abc")
|
||||
request.method = "POST"
|
||||
when: "No existing expected CsrfToken (session times out) and a POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the session timeout page page"
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/error/sessionError"
|
||||
when: "Existing expected CsrfToken and a POST (invalid token provided)"
|
||||
response = new MockHttpServletResponse()
|
||||
request = new MockHttpServletRequest(session: request.session, method:'POST')
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "Access Denied occurs"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf().and()
|
||||
.sessionManagement()
|
||||
.invalidSessionUrl("/error/sessionError")
|
||||
}
|
||||
}
|
||||
|
||||
def "csrf requireCsrfProtectionMatcher"() {
|
||||
setup:
|
||||
RequireCsrfProtectionMatcherConfig.matcher = Mock(RequestMatcher)
|
||||
@@ -158,7 +234,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
def "csrf clears on login"() {
|
||||
setup:
|
||||
CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
|
||||
1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
|
||||
loadConfig(CsrfTokenRepositoryConfig)
|
||||
request.method = "POST"
|
||||
request.getSession()
|
||||
@@ -169,7 +245,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.redirectedUrl == "/"
|
||||
1 * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
|
||||
(1.._) * CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -282,7 +358,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
when: "CSRF passes and our session times out"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the login page"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "http://localhost/login"
|
||||
when: "authenticate successfully"
|
||||
@@ -293,7 +369,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
request.method = "POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/"
|
||||
}
|
||||
@@ -308,7 +384,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
when: "CSRF passes and our session times out"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the login page"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "http://localhost/login"
|
||||
when: "authenticate successfully"
|
||||
@@ -319,7 +395,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
|
||||
request.method = "POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to original URL since it was a GET"
|
||||
1 * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "http://localhost/some-url"
|
||||
}
|
||||
|
||||
+93
@@ -18,16 +18,23 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.SecurityExpressionOperations;
|
||||
import org.springframework.security.access.vote.AffirmativeBased;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
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.core.Authentication;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
import org.springframework.security.web.access.expression.WebExpressionVoter;
|
||||
import org.springframework.security.web.access.expression.WebSecurityExpressionRoot;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -60,4 +67,90 @@ public class ExpressionUrlAuthorizationConfigurerConfigs {
|
||||
.formLogin();
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class UseBeansInExpressions extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/admin/**").hasRole("ADMIN")
|
||||
.antMatchers("/user/**").hasRole("USER")
|
||||
.antMatchers("/allow/**").access("@permission.check(authentication,'user')")
|
||||
.anyRequest().access("@permission.check(authentication,'admin')");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Checker permission() {
|
||||
return new Checker();
|
||||
}
|
||||
|
||||
static class Checker {
|
||||
public boolean check(Authentication authentication, String customArg) {
|
||||
return authentication.getName().contains(customArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class CustomExpressionRootConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.expressionHandler(expressionHandler())
|
||||
.antMatchers("/admin/**").hasRole("ADMIN")
|
||||
.antMatchers("/user/**").hasRole("USER")
|
||||
.antMatchers("/allow/**").access("check('user')")
|
||||
.anyRequest().access("check('admin')");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CustomExpressionHandler expressionHandler() {
|
||||
return new CustomExpressionHandler();
|
||||
}
|
||||
|
||||
static class CustomExpressionHandler extends DefaultWebSecurityExpressionHandler {
|
||||
|
||||
@Override
|
||||
protected SecurityExpressionOperations createSecurityExpressionRoot(
|
||||
Authentication authentication, FilterInvocation fi) {
|
||||
WebSecurityExpressionRoot root = new CustomExpressionRoot(authentication, fi);
|
||||
root.setPermissionEvaluator(getPermissionEvaluator());
|
||||
root.setTrustResolver(new AuthenticationTrustResolverImpl());
|
||||
root.setRoleHierarchy(getRoleHierarchy());
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
static class CustomExpressionRoot extends WebSecurityExpressionRoot {
|
||||
|
||||
public CustomExpressionRoot(Authentication a, FilterInvocation fi) {
|
||||
super(a, fi);
|
||||
}
|
||||
|
||||
public boolean check(String customArg) {
|
||||
Authentication auth = this.getAuthentication();
|
||||
return auth.getName().contains(customArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+78
@@ -20,7 +20,9 @@ import static org.springframework.security.config.annotation.web.configurers.Exp
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.access.event.AuthorizedEvent
|
||||
import org.springframework.security.access.vote.AffirmativeBased
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
@@ -29,6 +31,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurerConfigs.CustomExpressionRootConfig;
|
||||
import org.springframework.security.core.authority.AuthorityUtils
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor
|
||||
|
||||
@@ -462,4 +465,79 @@ public class ExpressionUrlAuthorizationConfigurerTests extends BaseSpringSpec {
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
|
||||
def "AuthorizedRequests withPostProcessor"() {
|
||||
setup:
|
||||
ApplicationListener al = Mock()
|
||||
AuthorizedRequestsWithPostProcessorConfig.AL = al
|
||||
loadConfig(AuthorizedRequestsWithPostProcessorConfig)
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then:
|
||||
1 * al.onApplicationEvent(_ as AuthorizedEvent)
|
||||
}
|
||||
|
||||
def "Use @permission.check in access"() {
|
||||
setup:
|
||||
loadConfig(UseBeansInExpressions)
|
||||
when: "invoke standard expression that denies access"
|
||||
login()
|
||||
request.servletPath = "/admin/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "standard expression works - get forbidden"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
when: "invoke standard expression that allows access"
|
||||
super.setup()
|
||||
login()
|
||||
request.servletPath = "/user/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "standard expression works - get ok"
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
when: "invoke custom bean as expression that allows access"
|
||||
super.setup()
|
||||
login()
|
||||
request.servletPath = "/allow/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "custom bean expression allows access"
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
when: "invoke custom bean as expression that denies access"
|
||||
super.setup()
|
||||
login()
|
||||
request.servletPath = "/deny/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "custom bean expression denies access"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
|
||||
def "Use custom expressionroot in access"() {
|
||||
setup:
|
||||
loadConfig(CustomExpressionRootConfig)
|
||||
when: "invoke standard expression that denies access"
|
||||
login()
|
||||
request.servletPath = "/admin/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "standard expression works - get forbidden"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
when: "invoke standard expression that allows access"
|
||||
super.setup()
|
||||
login()
|
||||
request.servletPath = "/user/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "standard expression works - get ok"
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
when: "invoke custom bean as expression that allows access"
|
||||
super.setup()
|
||||
login()
|
||||
request.servletPath = "/allow/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "custom bean expression allows access"
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
when: "invoke custom bean as expression that denies access"
|
||||
super.setup()
|
||||
login()
|
||||
request.servletPath = "/deny/1"
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: "custom bean expression denies access"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -186,6 +186,45 @@ class FormLoginConfigurerTests extends BaseSpringSpec {
|
||||
}
|
||||
}
|
||||
|
||||
def "FormLogin loginProcessingUrl"() {
|
||||
setup:
|
||||
loadConfig(FormLoginLoginProcessingUrlConfig)
|
||||
request.servletPath = "/loginCheck"
|
||||
request.method = "POST"
|
||||
request.parameters.username = ["user"] as String[]
|
||||
request.parameters.password = ["password"] as String[]
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
|
||||
then:
|
||||
response.redirectedUrl == "/"
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class FormLoginLoginProcessingUrlConfig extends BaseWebConfig {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginProcessingUrl("/loginCheck")
|
||||
.loginPage("/login")
|
||||
//.failureUrl("/loginFailure")
|
||||
.defaultSuccessUrl("/", true)
|
||||
.passwordParameter("password")
|
||||
.usernameParameter("username")
|
||||
.permitAll()
|
||||
.and()
|
||||
.logout()
|
||||
.logoutSuccessUrl("/login")
|
||||
.logoutUrl("/logout")
|
||||
.deleteCookies("JSESSIONID")
|
||||
}
|
||||
}
|
||||
|
||||
def "FormLogin uses PortMapper"() {
|
||||
when: "load formLogin() with permitAll"
|
||||
FormLoginUsesPortMapperConfig.PORT_MAPPER = Mock(PortMapper)
|
||||
|
||||
+14
-8
@@ -19,6 +19,7 @@ import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
@@ -36,11 +37,13 @@ import org.springframework.stereotype.Component
|
||||
class Issue55Tests extends BaseSpringSpec {
|
||||
|
||||
def "WebSecurityConfigurerAdapter defaults to @Autowired"() {
|
||||
setup:
|
||||
TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this")
|
||||
when:
|
||||
loadConfig(WebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
|
||||
loadConfig(WebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
|
||||
then:
|
||||
context.getBean(FilterChainProxy)
|
||||
findFilter(FilterSecurityInterceptor).authenticationManager.parent.class == CustomAuthenticationManager
|
||||
context.getBean(FilterChainProxy)
|
||||
findFilter(FilterSecurityInterceptor).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -66,12 +69,14 @@ class Issue55Tests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
def "multi http WebSecurityConfigurerAdapter defaults to @Autowired"() {
|
||||
setup:
|
||||
TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this")
|
||||
when:
|
||||
loadConfig(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
|
||||
loadConfig(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig)
|
||||
then:
|
||||
context.getBean(FilterChainProxy)
|
||||
findFilter(FilterSecurityInterceptor).authenticationManager.parent.class == CustomAuthenticationManager
|
||||
findFilter(FilterSecurityInterceptor,1).authenticationManager.parent.class == CustomAuthenticationManager
|
||||
context.getBean(FilterChainProxy)
|
||||
findFilter(FilterSecurityInterceptor).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
|
||||
findFilter(FilterSecurityInterceptor,1).authenticationManager.authenticate(token) == CustomAuthenticationManager.RESULT
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -107,8 +112,9 @@ class Issue55Tests extends BaseSpringSpec {
|
||||
}
|
||||
|
||||
static class CustomAuthenticationManager implements AuthenticationManager {
|
||||
static Authentication RESULT = new TestingAuthenticationToken("test", "this","ROLE_USER")
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
return null;
|
||||
return RESULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+72
-14
@@ -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
|
||||
|
||||
@@ -174,6 +176,28 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
response.redirectedUrl == "http://localhost/some-url"
|
||||
}
|
||||
|
||||
def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'csrf'()
|
||||
'session-management'('invalid-session-url': '/error/sessionError')
|
||||
}
|
||||
createAppContext()
|
||||
request.setParameter("_csrf","abc")
|
||||
request.method = "POST"
|
||||
when: "No existing expected CsrfToken (session times out) and a POST"
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "sent to the session timeout page page"
|
||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||
response.redirectedUrl == "/error/sessionError"
|
||||
when: "Existing expected CsrfToken and a POST (invalid token provided)"
|
||||
response = new MockHttpServletResponse()
|
||||
request = new MockHttpServletRequest(session: request.session, method:'POST')
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: "Access Denied occurs"
|
||||
response.status == HttpServletResponse.SC_FORBIDDEN
|
||||
}
|
||||
|
||||
def "csrf requireCsrfProtectionMatcher"() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
@@ -181,6 +205,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)
|
||||
@@ -235,7 +260,7 @@ class CsrfConfigTests extends AbstractHttpConfigTests {
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
verify(repo).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
|
||||
verify(repo, atLeastOnce()).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
|
||||
}
|
||||
|
||||
def "csrf clears on logout"() {
|
||||
@@ -250,10 +275,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
|
||||
}
|
||||
}
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package org.springframework.security.config.http
|
||||
|
||||
import org.springframework.mock.web.MockFilterChain
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
import org.springframework.mock.web.MockHttpServletResponse
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
class FormLoginBeanDefinitionParserTests extends AbstractHttpConfigTests {
|
||||
|
||||
def 'form-login default login page'() {
|
||||
setup:
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/spring_security_login')
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
MockFilterChain chain = new MockFilterChain()
|
||||
httpAutoConfig {
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.j_username.focus();'>
|
||||
<h3>Login with Username and Password</h3><form name='f' action='/j_spring_security_check' method='POST'>
|
||||
<table>
|
||||
<tr><td>User:</td><td><input type='text' name='j_username' value=''></td></tr>
|
||||
<tr><td>Password:</td><td><input type='password' name='j_password'/></td></tr>
|
||||
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
</form></body></html>"""
|
||||
}
|
||||
|
||||
def 'form-login default login page custom attributes'() {
|
||||
setup:
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/spring_security_login')
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
MockFilterChain chain = new MockFilterChain()
|
||||
httpAutoConfig {
|
||||
'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
|
||||
<h3>Login with Username and Password</h3><form name='f' action='/login_custom' method='POST'>
|
||||
<table>
|
||||
<tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
|
||||
<tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
|
||||
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
</form></body></html>"""
|
||||
}
|
||||
|
||||
def 'openid-login default login page'() {
|
||||
setup:
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/spring_security_login')
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
MockFilterChain chain = new MockFilterChain()
|
||||
httpAutoConfig {
|
||||
'openid-login'()
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.j_username.focus();'>
|
||||
<h3>Login with Username and Password</h3><form name='f' action='/j_spring_security_check' method='POST'>
|
||||
<table>
|
||||
<tr><td>User:</td><td><input type='text' name='j_username' value=''></td></tr>
|
||||
<tr><td>Password:</td><td><input type='password' name='j_password'/></td></tr>
|
||||
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/j_spring_openid_security_check' method='POST'>
|
||||
<table>
|
||||
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
|
||||
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
</form></body></html>"""
|
||||
}
|
||||
|
||||
def 'openid-login default login page custom attributes'() {
|
||||
setup:
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/spring_security_login')
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
MockFilterChain chain = new MockFilterChain()
|
||||
httpAutoConfig {
|
||||
'openid-login'('login-processing-url':'/login_custom')
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.j_username.focus();'>
|
||||
<h3>Login with Username and Password</h3><form name='f' action='/j_spring_security_check' method='POST'>
|
||||
<table>
|
||||
<tr><td>User:</td><td><input type='text' name='j_username' value=''></td></tr>
|
||||
<tr><td>Password:</td><td><input type='password' name='j_password'/></td></tr>
|
||||
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
</form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login_custom' method='POST'>
|
||||
<table>
|
||||
<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
|
||||
<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
|
||||
</table>
|
||||
</form></body></html>"""
|
||||
}
|
||||
}
|
||||
+16
@@ -6,6 +6,8 @@ import org.springframework.security.web.access.ExceptionTranslationFilter
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -102,4 +104,18 @@ class FormLoginConfigTests extends AbstractHttpConfigTests {
|
||||
apf.usernameParameter == 'xname';
|
||||
apf.passwordParameter == 'xpass'
|
||||
}
|
||||
|
||||
def 'SEC-2455: http@login-processing-url'() {
|
||||
when:
|
||||
xml.http {
|
||||
'form-login'('login-processing-url':'/authenticate')
|
||||
}
|
||||
createAppContext()
|
||||
|
||||
def apf = getFilter(UsernamePasswordAuthenticationFilter);
|
||||
|
||||
then:
|
||||
apf.filterProcessesUrl == null // SEC-2455 setFilterProcessesUrl was not invoked
|
||||
FieldUtils.getFieldValue(apf,'requiresAuthenticationRequestMatcher.filterProcessesUrl') == '/authenticate'
|
||||
}
|
||||
}
|
||||
|
||||
+26
@@ -17,7 +17,10 @@ package org.springframework.security.config.http;
|
||||
|
||||
|
||||
import java.security.Principal
|
||||
|
||||
import javax.servlet.Filter
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.BeansException
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
|
||||
@@ -98,4 +101,27 @@ class InterceptUrlConfigTests extends AbstractHttpConfigTests {
|
||||
attrsPost.size() == 1
|
||||
attrsPost.contains(new SecurityConfig("ROLE_USER"))
|
||||
}
|
||||
|
||||
def "SEC-2355: intercept-url support patch"() {
|
||||
setup:
|
||||
MockHttpServletRequest request = new MockHttpServletRequest(method:'GET')
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
MockFilterChain chain = new MockFilterChain()
|
||||
xml.http() {
|
||||
'http-basic'()
|
||||
'intercept-url'(pattern: '/**', 'method':'PATCH',access: 'ROLE_ADMIN')
|
||||
}
|
||||
createAppContext()
|
||||
when: 'Method other than PATCH is used'
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then: 'The response is OK'
|
||||
response.status == HttpServletResponse.SC_OK
|
||||
when: 'Method of PATCH is used'
|
||||
request = new MockHttpServletRequest(method:'PATCH')
|
||||
response = new MockHttpServletResponse()
|
||||
chain = new MockFilterChain()
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then: 'The response is unauthorized'
|
||||
response.status == HttpServletResponse.SC_UNAUTHORIZED
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package org.springframework.security.config.http
|
||||
|
||||
import org.springframework.security.util.FieldUtils
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class LogoutConfigTests extends AbstractHttpConfigTests {
|
||||
|
||||
def 'SEC-2455: logout@logout-url'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'logout'('logout-url':'/logout')
|
||||
}
|
||||
createAppContext()
|
||||
|
||||
def lf = getFilter(LogoutFilter);
|
||||
|
||||
then:
|
||||
lf.filterProcessesUrl == null // SEC-2455 setFilterProcessesUrl was not invoked
|
||||
FieldUtils.getFieldValue(lf,'logoutRequestMatcher.filterProcessesUrl') == '/logout'
|
||||
}
|
||||
}
|
||||
+31
-1
@@ -17,6 +17,10 @@ package org.springframework.security.config.http
|
||||
|
||||
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML
|
||||
|
||||
import javax.sql.DataSource
|
||||
|
||||
import org.springframework.beans.FatalBeanException
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
|
||||
import org.springframework.security.TestDataSource
|
||||
import org.springframework.security.authentication.ProviderManager
|
||||
@@ -26,7 +30,7 @@ import org.springframework.security.util.FieldUtils
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
|
||||
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl
|
||||
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices
|
||||
@@ -154,6 +158,32 @@ class RememberMeConfigTests extends AbstractHttpConfigTests {
|
||||
rememberMeServices().tokenValiditySeconds == -1
|
||||
}
|
||||
|
||||
def 'remember-me@token-validity-seconds denies for persistent implementation'() {
|
||||
setup:
|
||||
httpAutoConfig () {
|
||||
'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'dataSource' : 'dataSource')
|
||||
}
|
||||
mockBean(DataSource)
|
||||
when:
|
||||
createAppContext(AUTH_PROVIDER_XML)
|
||||
then:
|
||||
thrown(FatalBeanException)
|
||||
}
|
||||
|
||||
def 'SEC-2165: remember-me@token-validity-seconds allows property placeholders'() {
|
||||
when:
|
||||
httpAutoConfig () {
|
||||
'remember-me'('key': 'ourkey', 'token-validity-seconds':'${security.rememberme.ttl}')
|
||||
}
|
||||
xml.'b:bean'(class: PropertyPlaceholderConfigurer.name) {
|
||||
'b:property'(name:'properties', value:'security.rememberme.ttl=30')
|
||||
}
|
||||
|
||||
createAppContext(AUTH_PROVIDER_XML)
|
||||
then:
|
||||
rememberMeServices().tokenValiditySeconds == 30
|
||||
}
|
||||
|
||||
def rememberMeSecureCookieAttributeIsSetCorrectly() {
|
||||
httpAutoConfig () {
|
||||
'remember-me'('key': 'ourkey', 'use-secure-cookie':'true')
|
||||
|
||||
@@ -34,7 +34,7 @@ public class DataSourcePopulator implements InitializingBean {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(template, "dataSource required");
|
||||
|
||||
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);");
|
||||
template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);");
|
||||
template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
|
||||
template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
+13
-16
@@ -16,30 +16,21 @@
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.powermock.api.mockito.PowerMockito.spy;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({ClassUtils.class})
|
||||
public class CsrfConfigurerNoWebMvcTests {
|
||||
ConfigurableApplicationContext context;
|
||||
|
||||
@@ -52,24 +43,30 @@ public class CsrfConfigurerNoWebMvcTests {
|
||||
|
||||
@Test
|
||||
public void missingDispatcherServletPreventsCsrfRequestDataValueProcessor() {
|
||||
spy(ClassUtils.class);
|
||||
when(ClassUtils.isPresent(eq("org.springframework.web.servlet.DispatcherServlet"), any(ClassLoader.class))).thenReturn(false);
|
||||
|
||||
loadContext(CsrfDefaultsConfig.class);
|
||||
loadContext(EnableWebConfig.class);
|
||||
|
||||
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDispatcherServletPreventsCsrfRequestDataValueProcessor() {
|
||||
loadContext(CsrfDefaultsConfig.class);
|
||||
loadContext(EnableWebMvcConfig.class);
|
||||
|
||||
assertThat(context.containsBeanDefinition("requestDataValueProcessor")).isTrue();
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
static class CsrfDefaultsConfig extends WebSecurityConfigurerAdapter {
|
||||
static class EnableWebConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebMvcSecurity
|
||||
@Configuration
|
||||
static class EnableWebMvcConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
+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>
|
||||
+1
-1
@@ -30,7 +30,7 @@ dependencies {
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
powerMockDependencies
|
||||
|
||||
testRuntime "hsqldb:hsqldb:$hsqlVersion",
|
||||
testRuntime "org.hsqldb:hsqldb:$hsqlVersion",
|
||||
"cglib:cglib-nodep:$cglibVersion"
|
||||
}
|
||||
|
||||
|
||||
+22
-28
@@ -4,13 +4,13 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>3.2.0.CI-SNAPSHOT</version>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
<name>spring-security-core</name>
|
||||
<description>spring-security-core</description>
|
||||
<url>http://springsource.org/spring-security</url>
|
||||
<url>http://spring.io/spring-security</url>
|
||||
<organization>
|
||||
<name>SpringSource</name>
|
||||
<url>http://springsource.org/</url>
|
||||
<name>spring.io</name>
|
||||
<url>http://spring.io/</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -23,13 +23,13 @@
|
||||
<developer>
|
||||
<id>rwinch</id>
|
||||
<name>Rob Winch</name>
|
||||
<email>rwinch@vmware.com</email>
|
||||
<email>rwinch@gopivotal.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/SpringSource/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/SpringSource/spring-security</developerConnection>
|
||||
<url>https://github.com/SpringSource/spring-security</url>
|
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection>
|
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>
|
||||
<url>https://github.com/spring-projects/spring-security</url>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -42,12 +42,6 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snasphot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
@@ -58,25 +52,25 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -88,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -122,14 +116,14 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -151,12 +145,6 @@
|
||||
<version>3.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -169,6 +157,12 @@
|
||||
<version>1.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
@@ -220,7 +214,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.2.4.RELEASE</version>
|
||||
<version>3.2.8.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+61
@@ -12,30 +12,91 @@ import org.springframework.security.core.Authentication;
|
||||
*/
|
||||
public interface SecurityExpressionOperations {
|
||||
|
||||
/**
|
||||
* Gets the {@link Authentication} used for evaluating the expressions
|
||||
* @return the {@link Authentication} for evaluating the expressions
|
||||
*/
|
||||
Authentication getAuthentication();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has a particular authority within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAuthority(String)}.
|
||||
* @param authority the authority to test (i.e. "ROLE_USER")
|
||||
* @return true if the authority is found, else false
|
||||
*/
|
||||
boolean hasAuthority(String authority);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has any of the specified authorities within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAnyRole(String...)}.
|
||||
* @param authorities the authorities to test (i.e. "ROLE_USER", "ROLE_ADMIN")
|
||||
* @return true if any of the authorities is found, else false
|
||||
*/
|
||||
boolean hasAnyAuthority(String... authorities);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has a particular authority within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAuthority(String)}.
|
||||
* @param authority the authority to test (i.e. "ROLE_USER")
|
||||
* @return true if the authority is found, else false
|
||||
*/
|
||||
boolean hasRole(String role);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has any of the specified authorities within {@link Authentication#getAuthorities()}. This is a synonym for {@link #hasAnyAuthority(String...)}.
|
||||
* @param authorities the authorities to test (i.e. "ROLE_USER", "ROLE_ADMIN")
|
||||
* @return true if any of the authorities is found, else false
|
||||
*/
|
||||
boolean hasAnyRole(String... roles);
|
||||
|
||||
/**
|
||||
* Always grants access.
|
||||
* @return true
|
||||
*/
|
||||
boolean permitAll();
|
||||
|
||||
/**
|
||||
* Always denies access
|
||||
* @return false
|
||||
*/
|
||||
boolean denyAll();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} is anonymous
|
||||
* @return true if the user is anonymous, else false
|
||||
*/
|
||||
boolean isAnonymous();
|
||||
|
||||
/**
|
||||
* Determines ifthe {@link #getAuthentication()} is authenticated
|
||||
* @return true if the {@link #getAuthentication()} is authenticated, else false
|
||||
*/
|
||||
boolean isAuthenticated();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} was authenticated using remember me
|
||||
* @return true if the {@link #getAuthentication()} authenticated using remember me, else false
|
||||
*/
|
||||
boolean isRememberMe();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} authenticated without the use of remember me
|
||||
* @return true if the {@link #getAuthentication()} authenticated without the use of remember me, else false
|
||||
*/
|
||||
boolean isFullyAuthenticated();
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has permission to access the target given the permission
|
||||
* @param target the target domain object to check permission on
|
||||
* @param permission the permission to check on the domain object (i.e. "read", "write", etc).
|
||||
* @return true if permission is granted to the {@link #getAuthentication()}, else false
|
||||
*/
|
||||
boolean hasPermission(Object target, Object permission);
|
||||
|
||||
/**
|
||||
* Determines if the {@link #getAuthentication()} has permission to access the domain object with a given id, type, and permission.
|
||||
* @param targetId the identifier of the domain object to determine access
|
||||
* @param targetType the type (i.e. com.example.domain.Message)
|
||||
* @param permission the perission to check on the domain object (i.e. "read", "write", etc)
|
||||
* @return true if permission is granted to the {@link #getAuthentication()}, else false
|
||||
*/
|
||||
boolean hasPermission(Object targetId, String targetType, Object permission);
|
||||
|
||||
}
|
||||
|
||||
+11
-4
@@ -5,7 +5,6 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
@@ -38,11 +37,15 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
|
||||
public final String delete = "delete";
|
||||
public final String admin = "administration";
|
||||
|
||||
public SecurityExpressionRoot(Authentication a) {
|
||||
if (a == null) {
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param authentication the {@link Authentication} to use. Cannot be null.
|
||||
*/
|
||||
public SecurityExpressionRoot(Authentication authentication) {
|
||||
if (authentication == null) {
|
||||
throw new IllegalArgumentException("Authentication object cannot be null");
|
||||
}
|
||||
this.authentication = a;
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
public final boolean hasAuthority(String authority) {
|
||||
@@ -97,6 +100,10 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
|
||||
return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to access {@link Authentication#getPrincipal()} from {@link #getAuthentication()}
|
||||
* @return
|
||||
*/
|
||||
public Object getPrincipal() {
|
||||
return authentication.getPrincipal();
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ package org.springframework.security.authentication;
|
||||
* Thrown if an authentication request could not be processed due to a system problem that occurred internally. It
|
||||
* differs from {@link AuthenticationServiceException} in that it would not be thrown if an external system has an
|
||||
* internal error or failure. This ensures that we can handle errors that are within our control distinctly from errors
|
||||
* of other systems. The advantage to this distinction is that the unrusted external system should not be able to fill
|
||||
* of other systems. The advantage to this distinction is that the untrusted external system should not be able to fill
|
||||
* up logs and cause excessive IO. However, an internal system should report errors.
|
||||
* </p>
|
||||
* <p>
|
||||
|
||||
@@ -163,6 +163,9 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
|
||||
prepareException(e, authentication);
|
||||
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
|
||||
throw e;
|
||||
} catch (InternalAuthenticationServiceException e) {
|
||||
prepareException(e, authentication);
|
||||
throw e;
|
||||
} catch (AuthenticationException e) {
|
||||
lastException = e;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user