Compare commits
143 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa4c5449e7 | |||
| 2a3845a7ed | |||
| ff96a7b5ad | |||
| c37ff42234 | |||
| 0a00d84838 | |||
| 96c6751a1d | |||
| 8ee9c32788 | |||
| 7a5fb9eaf7 | |||
| 8cbb972cef | |||
| 539a11d0a4 | |||
| e97c5a533b | |||
| e0fa644b08 | |||
| 592db9180d | |||
| aca3fc2412 | |||
| 07f9afe057 | |||
| d7077b441a | |||
| 101f11ba94 | |||
| 18b903f6e3 | |||
| 038266a94f | |||
| cf559ab224 | |||
| 649428b49a | |||
| 0355e960d7 | |||
| fdad14af63 | |||
| 077c9e0b3e | |||
| dc648cf79f | |||
| c2d2914a4f | |||
| a40f73521c | |||
| 70863952ae | |||
| af95be34c6 | |||
| 71478c2534 | |||
| b289d12aad | |||
| e2361c5c79 | |||
| 8b9c8ca96c | |||
| 44e672d969 | |||
| 330f0f050d | |||
| e45dcb3ab2 | |||
| d3a451fffb | |||
| 9d378103b0 | |||
| 2031f101dc | |||
| 2a2c2dd209 | |||
| fa0e06ebdc | |||
| 6724627b50 | |||
| 4aab7b06a9 | |||
| d0d4d58c48 | |||
| 29be60d035 | |||
| 5024103b07 | |||
| d0327807a7 | |||
| f880f1ba26 | |||
| 71dafc0c06 | |||
| 7d9357b871 | |||
| 0b02bbecd1 | |||
| 932a5cc8b4 | |||
| e4a321511a | |||
| 4ee5800ec9 | |||
| c67632225d | |||
| 6e45a376cd | |||
| 70b67cd2f1 | |||
| 304e89041c | |||
| f1a76efc2d | |||
| 963251314b | |||
| ee061f3659 | |||
| 440ffce2eb | |||
| 47871562ca | |||
| f0c548cee7 | |||
| 1a32b399e6 | |||
| e9f3da94fc | |||
| 4fb6f936a7 | |||
| c431b5479e | |||
| fc03950afd | |||
| 516b5fed4a | |||
| 165e29e585 | |||
| 0be3e86b21 | |||
| 96d229a6d1 | |||
| 5098cad9cf | |||
| 883c480af0 | |||
| 0f83e40427 | |||
| ad6ef6e4c7 | |||
| 94201e46f1 | |||
| 910e198cee | |||
| 45a88fc391 | |||
| 8f01efb9e3 | |||
| f53c65b3a0 | |||
| 0be772ff5b | |||
| ac990afa5d | |||
| 55cccbf727 | |||
| a095ea75a2 | |||
| a041e7c943 | |||
| 4f3072b3d9 | |||
| 13c467734a | |||
| c01b2b946b | |||
| 549f9dab64 | |||
| 58090c37ea | |||
| 38344e8de6 | |||
| 6f319f0b13 | |||
| 4e71b26ea4 | |||
| 04f3bbcefa | |||
| c67ee6f2a8 | |||
| 4b590ce31f | |||
| 5902b46e9b | |||
| 62449d6fa2 | |||
| aa06088077 | |||
| 2a60776c8a | |||
| f411ecada2 | |||
| 8eeacf4a36 | |||
| 20c252982e | |||
| 6c5ac0d8ec | |||
| e1cb375fbf | |||
| e7e3f06044 | |||
| 994e93741b | |||
| 04e1a11e35 | |||
| 547056d5cc | |||
| 1fa35fb9a8 | |||
| a49914e631 | |||
| 783a43ea35 | |||
| 07a176d11e | |||
| c664fbc1a3 | |||
| af412c4d65 | |||
| e38bf6e554 | |||
| 624e0da669 | |||
| b28aa6c647 | |||
| 9e83b4be25 | |||
| e9854c91ef | |||
| 0345e29afb | |||
| 8bd5795f8e | |||
| 4fbc98dcd2 | |||
| 44cdbd6cf3 | |||
| a9af8c4128 | |||
| 28c81af788 | |||
| 3a956daf0c | |||
| 9c245865d7 | |||
| 86ed937a47 | |||
| 32ec8c3ae4 | |||
| c7ffd2513a | |||
| b3e0f167ff | |||
| 8c063f8ccb | |||
| f1ca42e501 | |||
| 719149f01d | |||
| ccd30607a9 | |||
| aa1ef46d84 | |||
| 16a21264d0 | |||
| 1c0f092176 | |||
| 32d79f3f4e | |||
| 088a24cf59 |
@@ -42,7 +42,7 @@ import org.springframework.security.acls.domain.AuditLogger;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
||||
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.domain.PermissionFactory;
|
||||
import org.springframework.security.acls.domain.PrincipalSid;
|
||||
import org.springframework.security.acls.model.AccessControlEntry;
|
||||
@@ -51,7 +51,6 @@ import org.springframework.security.acls.model.AclCache;
|
||||
import org.springframework.security.acls.model.MutableAcl;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.ObjectIdentityGenerator;
|
||||
import org.springframework.security.acls.model.Permission;
|
||||
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
@@ -110,8 +109,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
|
||||
private final AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||
|
||||
private ObjectIdentityGenerator objectIdentityGenerator;
|
||||
|
||||
private PermissionFactory permissionFactory = new DefaultPermissionFactory();
|
||||
|
||||
private final AclCache aclCache;
|
||||
@@ -165,7 +162,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
this.aclCache = aclCache;
|
||||
this.aclAuthorizationStrategy = aclAuthorizationStrategy;
|
||||
this.grantingStrategy = grantingStrategy;
|
||||
this.objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
|
||||
this.aclClassIdUtils = new AclClassIdUtils();
|
||||
this.fieldAces.setAccessible(true);
|
||||
this.fieldAcl.setAccessible(true);
|
||||
@@ -492,11 +488,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
public final void setObjectIdentityGenerator(ObjectIdentityGenerator objectIdentityGenerator) {
|
||||
Assert.notNull(objectIdentityGenerator, "objectIdentityGenerator cannot be null");
|
||||
this.objectIdentityGenerator = objectIdentityGenerator;
|
||||
}
|
||||
|
||||
public final void setConversionService(ConversionService conversionService) {
|
||||
this.aclClassIdUtils = new AclClassIdUtils(conversionService);
|
||||
}
|
||||
@@ -578,8 +569,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
||||
// target id type, e.g. UUID.
|
||||
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
|
||||
identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs);
|
||||
ObjectIdentity objectIdentity = BasicLookupStrategy.this.objectIdentityGenerator
|
||||
.createObjectIdentity(identifier, rs.getString("class"));
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"), identifier);
|
||||
|
||||
Acl parentAcl = null;
|
||||
long parentAclId = rs.getLong("parent_object");
|
||||
|
||||
@@ -31,12 +31,11 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
|
||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
||||
import org.springframework.security.acls.model.Acl;
|
||||
import org.springframework.security.acls.model.AclService;
|
||||
import org.springframework.security.acls.model.NotFoundException;
|
||||
import org.springframework.security.acls.model.ObjectIdentity;
|
||||
import org.springframework.security.acls.model.ObjectIdentityGenerator;
|
||||
import org.springframework.security.acls.model.Sid;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -82,8 +81,6 @@ public class JdbcAclService implements AclService {
|
||||
|
||||
private AclClassIdUtils aclClassIdUtils;
|
||||
|
||||
private ObjectIdentityGenerator objectIdentityGenerator;
|
||||
|
||||
public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) {
|
||||
this(new JdbcTemplate(dataSource), lookupStrategy);
|
||||
}
|
||||
@@ -94,7 +91,6 @@ public class JdbcAclService implements AclService {
|
||||
this.jdbcOperations = jdbcOperations;
|
||||
this.lookupStrategy = lookupStrategy;
|
||||
this.aclClassIdUtils = new AclClassIdUtils();
|
||||
this.objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,7 +105,7 @@ public class JdbcAclService implements AclService {
|
||||
String javaType = rs.getString("class");
|
||||
Serializable identifier = (Serializable) rs.getObject("obj_id");
|
||||
identifier = this.aclClassIdUtils.identifierFrom(identifier, rs);
|
||||
return this.objectIdentityGenerator.createObjectIdentity(identifier, javaType);
|
||||
return new ObjectIdentityImpl(javaType, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -169,11 +165,6 @@ public class JdbcAclService implements AclService {
|
||||
this.aclClassIdUtils = new AclClassIdUtils(conversionService);
|
||||
}
|
||||
|
||||
public void setObjectIdentityGenerator(ObjectIdentityGenerator objectIdentityGenerator) {
|
||||
Assert.notNull(objectIdentityGenerator, "objectIdentityGenerator cannot be null");
|
||||
this.objectIdentityGenerator = objectIdentityGenerator;
|
||||
}
|
||||
|
||||
protected boolean isAclClassIdSupported() {
|
||||
return this.aclClassIdSupported;
|
||||
}
|
||||
|
||||
-9
@@ -318,13 +318,4 @@ public abstract class AbstractBasicLookupStrategyTests {
|
||||
assertThat(((GrantedAuthoritySid) result).getGrantedAuthority()).isEqualTo("sid");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setObjectIdentityGeneratorWhenNullThenThrowsIllegalArgumentException() {
|
||||
// @formatter:off
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.strategy.setObjectIdentityGenerator(null))
|
||||
.withMessage("objectIdentityGenerator cannot be null");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ import org.springframework.security.acls.model.Sid;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@@ -171,26 +170,6 @@ public class JdbcAclServiceTests {
|
||||
.isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setObjectIdentityGeneratorWhenNullThenThrowsIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.aclServiceIntegration.setObjectIdentityGenerator(null))
|
||||
.withMessage("objectIdentityGenerator cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findChildrenWhenObjectIdentityGeneratorSetThenUsed() {
|
||||
this.aclServiceIntegration
|
||||
.setObjectIdentityGenerator((id, type) -> new ObjectIdentityImpl(type, "prefix:" + id));
|
||||
|
||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl("location", "US");
|
||||
this.aclServiceIntegration.setAclClassIdSupported(true);
|
||||
List<ObjectIdentity> objectIdentities = this.aclServiceIntegration.findChildren(objectIdentity);
|
||||
assertThat(objectIdentities.size()).isEqualTo(1);
|
||||
assertThat(objectIdentities.get(0).getType()).isEqualTo("location");
|
||||
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo("prefix:US-PAL");
|
||||
}
|
||||
|
||||
class MockLongIdDomainObject {
|
||||
|
||||
private Object id;
|
||||
|
||||
@@ -27,3 +27,7 @@ sourceSets.test.aspectj.srcDir "src/test/java"
|
||||
sourceSets.test.java.srcDirs = files()
|
||||
|
||||
compileAspectj.ajcOptions.outxmlfile = "META-INF/aop.xml"
|
||||
|
||||
aspectj {
|
||||
version = aspectjVersion
|
||||
}
|
||||
|
||||
+4
-11
@@ -2,12 +2,13 @@ buildscript {
|
||||
dependencies {
|
||||
classpath "io.spring.javaformat:spring-javaformat-gradle-plugin:$springJavaformatVersion"
|
||||
classpath 'io.spring.nohttp:nohttp-gradle:0.0.10'
|
||||
classpath "io.freefair.gradle:aspectj-plugin:6.4.3.1"
|
||||
classpath "io.freefair.gradle:aspectj-plugin:6.2.0"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
classpath "com.netflix.nebula:nebula-project-plugin:8.2.0"
|
||||
}
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
maven { url 'https://repo.spring.io/plugins-snapshot' }
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +22,6 @@ apply plugin: 'org.springframework.security.update-dependencies'
|
||||
apply plugin: 'org.springframework.security.sagan'
|
||||
apply plugin: 'org.springframework.github.milestone'
|
||||
apply plugin: 'org.springframework.github.changelog'
|
||||
apply plugin: 'org.springframework.github.release'
|
||||
|
||||
group = 'org.springframework.security'
|
||||
description = 'Spring Security'
|
||||
@@ -46,13 +46,6 @@ tasks.named("gitHubCheckMilestoneHasNoOpenIssues") {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("createGitHubRelease") {
|
||||
repository {
|
||||
owner = "spring-projects"
|
||||
name = "spring-security"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("updateDependencies") {
|
||||
// we aren't Gradle 7 compatible yet
|
||||
checkForGradleUpdate = false
|
||||
@@ -71,9 +64,9 @@ updateDependenciesSettings {
|
||||
dependencyExcludes {
|
||||
majorVersionBump()
|
||||
minorVersionBump()
|
||||
alphaBetaVersions()
|
||||
releaseCandidatesVersions()
|
||||
milestoneVersions()
|
||||
alphaBetaVersions()
|
||||
snapshotVersions()
|
||||
addRule { components ->
|
||||
components.withModule("commons-codec:commons-codec") { selection ->
|
||||
|
||||
@@ -59,10 +59,6 @@ gradlePlugin {
|
||||
id = "org.springframework.github.changelog"
|
||||
implementationClass = "org.springframework.gradle.github.changelog.GitHubChangelogPlugin"
|
||||
}
|
||||
githubRelease {
|
||||
id = "org.springframework.github.release"
|
||||
implementationClass = "org.springframework.gradle.github.release.GitHubReleasePlugin"
|
||||
}
|
||||
s101 {
|
||||
id = "s101"
|
||||
implementationClass = "s101.S101Plugin"
|
||||
@@ -84,7 +80,7 @@ dependencies {
|
||||
implementation localGroovy()
|
||||
|
||||
implementation 'io.github.gradle-nexus:publish-plugin:1.1.0'
|
||||
implementation 'io.projectreactor:reactor-core:3.5.0-M1'
|
||||
implementation 'io.projectreactor:reactor-core:3.4.19'
|
||||
implementation 'gradle.plugin.org.gretty:gretty:3.0.1'
|
||||
implementation 'com.apollographql.apollo:apollo-runtime:2.4.5'
|
||||
implementation 'com.github.ben-manes:gradle-versions-plugin:0.38.0'
|
||||
|
||||
@@ -59,22 +59,14 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
||||
integrationTestRuntime {
|
||||
extendsFrom integrationTestCompile, testRuntime, testRuntimeOnly
|
||||
}
|
||||
integrationTestCompileClasspath {
|
||||
extendsFrom integrationTestCompile
|
||||
canBeResolved = true
|
||||
}
|
||||
integrationTestRuntimeClasspath {
|
||||
extendsFrom integrationTestRuntime
|
||||
canBeResolved = true
|
||||
}
|
||||
}
|
||||
|
||||
project.sourceSets {
|
||||
integrationTest {
|
||||
java.srcDir project.file('src/integration-test/java')
|
||||
resources.srcDir project.file('src/integration-test/resources')
|
||||
compileClasspath = project.sourceSets.main.output + project.sourceSets.test.output + project.configurations.integrationTestCompileClasspath
|
||||
runtimeClasspath = output + compileClasspath + project.configurations.integrationTestRuntimeClasspath
|
||||
compileClasspath = project.sourceSets.main.output + project.sourceSets.test.output + project.configurations.integrationTestCompile
|
||||
runtimeClasspath = output + compileClasspath + project.configurations.integrationTestRuntime
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +85,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
||||
project.idea {
|
||||
module {
|
||||
testSourceDirs += project.file('src/integration-test/java')
|
||||
scopes.TEST.plus += [ project.configurations.integrationTestCompileClasspath ]
|
||||
scopes.TEST.plus += [ project.configurations.integrationTestCompile ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,7 +115,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
||||
|
||||
project.plugins.withType(EclipsePlugin) {
|
||||
project.eclipse.classpath {
|
||||
plusConfigurations += [ project.configurations.integrationTestCompileClasspath ]
|
||||
plusConfigurations += [ project.configurations.integrationTestCompile ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.gradle.github.changelog;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
@@ -31,10 +28,12 @@ import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
|
||||
import org.gradle.api.artifacts.repositories.IvyPatternRepositoryLayout;
|
||||
import org.gradle.api.tasks.JavaExec;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class GitHubChangelogPlugin implements Plugin<Project> {
|
||||
|
||||
public static final String CHANGELOG_GENERATOR_CONFIGURATION_NAME = "changelogGenerator";
|
||||
public static final String RELEASE_NOTES_PATH = "changelog/release-notes.md";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
@@ -43,7 +42,7 @@ public class GitHubChangelogPlugin implements Plugin<Project> {
|
||||
project.getTasks().register("generateChangelog", JavaExec.class, new Action<JavaExec>() {
|
||||
@Override
|
||||
public void execute(JavaExec generateChangelog) {
|
||||
File outputFile = project.file(Paths.get(project.getBuildDir().getPath(), RELEASE_NOTES_PATH));
|
||||
File outputFile = project.file(Paths.get(project.getBuildDir().getPath(), "changelog/release-notes.md"));
|
||||
outputFile.getParentFile().mkdirs();
|
||||
generateChangelog.setGroup("Release");
|
||||
generateChangelog.setDescription("Generates the changelog");
|
||||
|
||||
+2
-4
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.gradle.github.milestones;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import okhttp3.Interceptor;
|
||||
@@ -26,7 +23,8 @@ import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class GitHubMilestoneApi {
|
||||
private String baseUrl = "https://api.github.com";
|
||||
|
||||
-2
@@ -21,8 +21,6 @@ import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
|
||||
public class GitHubMilestoneHasNoOpenIssuesTask extends DefaultTask {
|
||||
@Input
|
||||
private RepositoryRef repository = new RepositoryRef();
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class GitHubMilestonePlugin implements Plugin<Project> {
|
||||
githubCheckMilestoneHasNoOpenIssues.setGroup("Release");
|
||||
githubCheckMilestoneHasNoOpenIssues.setDescription("Checks if there are any open issues for the specified repository and milestone");
|
||||
githubCheckMilestoneHasNoOpenIssues.setMilestoneTitle((String) project.findProperty("nextVersion"));
|
||||
if (project.hasProperty("gitHubAccessToken")) {
|
||||
if (project.hasProperty("githubAccessToken")) {
|
||||
githubCheckMilestoneHasNoOpenIssues.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,11 +1,10 @@
|
||||
package org.springframework.gradle.github;
|
||||
|
||||
package org.springframework.gradle.github.milestones;
|
||||
public class RepositoryRef {
|
||||
private String owner;
|
||||
|
||||
private String name;
|
||||
|
||||
public RepositoryRef() {
|
||||
RepositoryRef() {
|
||||
}
|
||||
|
||||
public RepositoryRef(String owner, String name) {
|
||||
@@ -63,3 +62,4 @@ public class RepositoryRef {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-130
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.gradle.github.release;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
import org.springframework.gradle.github.changelog.GitHubChangelogPlugin;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class CreateGitHubReleaseTask extends DefaultTask {
|
||||
@Input
|
||||
private RepositoryRef repository = new RepositoryRef();
|
||||
|
||||
@Input @Optional
|
||||
private String gitHubAccessToken;
|
||||
|
||||
@Input
|
||||
private String version;
|
||||
|
||||
@Input @Optional
|
||||
private String branch = "main";
|
||||
|
||||
@Input
|
||||
private boolean createRelease = false;
|
||||
|
||||
@TaskAction
|
||||
public void createGitHubRelease() {
|
||||
String body = readReleaseNotes();
|
||||
Release release = Release.tag(this.version)
|
||||
.commit(this.branch)
|
||||
.name(this.version)
|
||||
.body(body)
|
||||
.preRelease(this.version.contains("-"))
|
||||
.build();
|
||||
|
||||
System.out.printf("%sCreating GitHub release for %s/%s@%s\n",
|
||||
this.createRelease ? "" : "[DRY RUN] ",
|
||||
this.repository.getOwner(),
|
||||
this.repository.getName(),
|
||||
this.version
|
||||
);
|
||||
System.out.printf(" Release Notes:\n\n----\n%s\n----\n\n", body.trim());
|
||||
|
||||
if (this.createRelease) {
|
||||
GitHubReleaseApi github = new GitHubReleaseApi(this.gitHubAccessToken);
|
||||
github.publishRelease(this.repository, release);
|
||||
}
|
||||
}
|
||||
|
||||
private String readReleaseNotes() {
|
||||
Project project = getProject();
|
||||
File inputFile = project.file(Paths.get(project.getBuildDir().getPath(), GitHubChangelogPlugin.RELEASE_NOTES_PATH));
|
||||
try {
|
||||
return Files.readString(inputFile.toPath());
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Unable to read release notes from " + inputFile, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public RepositoryRef getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
public void repository(Action<RepositoryRef> repository) {
|
||||
repository.execute(this.repository);
|
||||
}
|
||||
|
||||
public void setRepository(RepositoryRef repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public String getGitHubAccessToken() {
|
||||
return gitHubAccessToken;
|
||||
}
|
||||
|
||||
public void setGitHubAccessToken(String gitHubAccessToken) {
|
||||
this.gitHubAccessToken = gitHubAccessToken;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getBranch() {
|
||||
return branch;
|
||||
}
|
||||
|
||||
public void setBranch(String branch) {
|
||||
this.branch = branch;
|
||||
}
|
||||
|
||||
public boolean isCreateRelease() {
|
||||
return createRelease;
|
||||
}
|
||||
|
||||
public void setCreateRelease(boolean createRelease) {
|
||||
this.createRelease = createRelease;
|
||||
}
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.gradle.github.release;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
|
||||
/**
|
||||
* Manage GitHub releases.
|
||||
*
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class GitHubReleaseApi {
|
||||
private String baseUrl = "https://api.github.com";
|
||||
|
||||
private final OkHttpClient httpClient;
|
||||
private Gson gson = new Gson();
|
||||
|
||||
public GitHubReleaseApi(String gitHubAccessToken) {
|
||||
this.httpClient = new OkHttpClient.Builder()
|
||||
.addInterceptor(new AuthorizationInterceptor(gitHubAccessToken))
|
||||
.build();
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a release with no binary attachments.
|
||||
*
|
||||
* @param repository The repository owner/name
|
||||
* @param release The contents of the release
|
||||
*/
|
||||
public void publishRelease(RepositoryRef repository, Release release) {
|
||||
String url = this.baseUrl + "/repos/" + repository.getOwner() + "/" + repository.getName() + "/releases";
|
||||
String json = this.gson.toJson(release);
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"), json);
|
||||
Request request = new Request.Builder().url(url).post(body).build();
|
||||
try {
|
||||
Response response = this.httpClient.newCall(request).execute();
|
||||
if (!response.isSuccessful()) {
|
||||
throw new RuntimeException(String.format("Could not create release %s for repository %s/%s. Got response %s",
|
||||
release.getName(), repository.getOwner(), repository.getName(), response));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(String.format("Could not create release %s for repository %s/%s",
|
||||
release.getName(), repository.getOwner(), repository.getName()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AuthorizationInterceptor implements Interceptor {
|
||||
private final String token;
|
||||
|
||||
public AuthorizationInterceptor(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request request = chain.request().newBuilder()
|
||||
.addHeader("Authorization", "Bearer " + this.token)
|
||||
.build();
|
||||
|
||||
return chain.proceed(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.gradle.github.release;
|
||||
|
||||
import groovy.lang.MissingPropertyException;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class GitHubReleasePlugin implements Plugin<Project> {
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.getTasks().register("createGitHubRelease", CreateGitHubReleaseTask.class, new Action<CreateGitHubReleaseTask>() {
|
||||
@Override
|
||||
public void execute(CreateGitHubReleaseTask createGitHubRelease) {
|
||||
createGitHubRelease.setGroup("Release");
|
||||
createGitHubRelease.setDescription("Create a github release");
|
||||
createGitHubRelease.dependsOn("generateChangelog");
|
||||
|
||||
createGitHubRelease.setCreateRelease("true".equals(project.findProperty("createRelease")));
|
||||
createGitHubRelease.setVersion((String) project.findProperty("nextVersion"));
|
||||
if (project.hasProperty("branch")) {
|
||||
createGitHubRelease.setBranch((String) project.findProperty("branch"));
|
||||
}
|
||||
createGitHubRelease.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
|
||||
if (createGitHubRelease.isCreateRelease() && createGitHubRelease.getGitHubAccessToken() == null) {
|
||||
throw new MissingPropertyException("Please provide an access token with -PgitHubAccessToken=...");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.gradle.github.release;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class Release {
|
||||
@SerializedName("tag_name")
|
||||
private final String tag;
|
||||
|
||||
@SerializedName("target_commitish")
|
||||
private final String commit;
|
||||
|
||||
@SerializedName("name")
|
||||
private final String name;
|
||||
|
||||
@SerializedName("body")
|
||||
private final String body;
|
||||
|
||||
@SerializedName("draft")
|
||||
private final boolean draft;
|
||||
|
||||
@SerializedName("prerelease")
|
||||
private final boolean preRelease;
|
||||
|
||||
@SerializedName("generate_release_notes")
|
||||
private final boolean generateReleaseNotes;
|
||||
|
||||
private Release(String tag, String commit, String name, String body, boolean draft, boolean preRelease, boolean generateReleaseNotes) {
|
||||
this.tag = tag;
|
||||
this.commit = commit;
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
this.draft = draft;
|
||||
this.preRelease = preRelease;
|
||||
this.generateReleaseNotes = generateReleaseNotes;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public String getCommit() {
|
||||
return commit;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public boolean isDraft() {
|
||||
return draft;
|
||||
}
|
||||
|
||||
public boolean isPreRelease() {
|
||||
return preRelease;
|
||||
}
|
||||
|
||||
public boolean isGenerateReleaseNotes() {
|
||||
return generateReleaseNotes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Release{" +
|
||||
"tag='" + tag + '\'' +
|
||||
", commit='" + commit + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", body='" + body + '\'' +
|
||||
", draft=" + draft +
|
||||
", preRelease=" + preRelease +
|
||||
", generateReleaseNotes=" + generateReleaseNotes +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static Builder tag(String tag) {
|
||||
return new Builder().tag(tag);
|
||||
}
|
||||
|
||||
public static Builder commit(String commit) {
|
||||
return new Builder().commit(commit);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String tag;
|
||||
private String commit;
|
||||
private String name;
|
||||
private String body;
|
||||
private boolean draft;
|
||||
private boolean preRelease;
|
||||
private boolean generateReleaseNotes;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder tag(String tag) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder commit(String commit) {
|
||||
this.commit = commit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder body(String body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder draft(boolean draft) {
|
||||
this.draft = draft;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder preRelease(boolean preRelease) {
|
||||
this.preRelease = preRelease;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder generateReleaseNotes(boolean generateReleaseNotes) {
|
||||
this.generateReleaseNotes = generateReleaseNotes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Release build() {
|
||||
return new Release(tag, commit, name, body, draft, preRelease, generateReleaseNotes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,18 +164,14 @@ public class S101Configurer {
|
||||
String source = "https://structure101.com/binaries/v6";
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
HtmlPage page = webClient.getPage(source);
|
||||
Matcher matcher = null;
|
||||
for (HtmlAnchor anchor : page.getAnchors()) {
|
||||
Matcher candidate = Pattern.compile("(structure101-build-java-all-)(.*).zip").matcher(anchor.getHrefAttribute());
|
||||
if (candidate.find()) {
|
||||
matcher = candidate;
|
||||
Matcher matcher = Pattern.compile("(structure101-build-java-all-)(.*).zip").matcher(anchor.getHrefAttribute());
|
||||
if (matcher.find()) {
|
||||
copyZipToFilesystem(source, installationDirectory, matcher.group(1) + matcher.group(2));
|
||||
return matcher.group(2);
|
||||
}
|
||||
}
|
||||
if (matcher == null) {
|
||||
return null;
|
||||
}
|
||||
copyZipToFilesystem(source, installationDirectory, matcher.group(1) + matcher.group(2));
|
||||
return matcher.group(2);
|
||||
return null;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,16 +1,15 @@
|
||||
package io.spring.gradle.github.milestones;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
import org.springframework.gradle.github.milestones.GitHubMilestoneApi;
|
||||
import org.springframework.gradle.github.milestones.RepositoryRef;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
+1
-3
@@ -1,7 +1,5 @@
|
||||
package org.springframework.gradle.github.milestones;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
@@ -9,7 +7,7 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
-151
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.gradle.github.release;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import org.springframework.gradle.github.RepositoryRef;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Steve Riesenberg
|
||||
*/
|
||||
public class GitHubReleaseApiTests {
|
||||
private GitHubReleaseApi github;
|
||||
|
||||
private RepositoryRef repository = new RepositoryRef("spring-projects", "spring-security");
|
||||
|
||||
private MockWebServer server;
|
||||
|
||||
private String baseUrl;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
this.server = new MockWebServer();
|
||||
this.server.start();
|
||||
this.github = new GitHubReleaseApi("mock-oauth-token");
|
||||
this.baseUrl = this.server.url("/api").toString();
|
||||
this.github.setBaseUrl(this.baseUrl);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() throws Exception {
|
||||
this.server.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishReleaseWhenValidParametersThenSuccess() throws Exception {
|
||||
String responseJson = "{\n" +
|
||||
" \"url\": \"https://api.github.com/spring-projects/spring-security/releases/1\",\n" +
|
||||
" \"html_url\": \"https://github.com/spring-projects/spring-security/releases/tags/v1.0.0\",\n" +
|
||||
" \"assets_url\": \"https://api.github.com/spring-projects/spring-security/releases/1/assets\",\n" +
|
||||
" \"upload_url\": \"https://uploads.github.com/spring-projects/spring-security/releases/1/assets{?name,label}\",\n" +
|
||||
" \"tarball_url\": \"https://api.github.com/spring-projects/spring-security/tarball/v1.0.0\",\n" +
|
||||
" \"zipball_url\": \"https://api.github.com/spring-projects/spring-security/zipball/v1.0.0\",\n" +
|
||||
" \"discussion_url\": \"https://github.com/spring-projects/spring-security/discussions/90\",\n" +
|
||||
" \"id\": 1,\n" +
|
||||
" \"node_id\": \"MDc6UmVsZWFzZTE=\",\n" +
|
||||
" \"tag_name\": \"v1.0.0\",\n" +
|
||||
" \"target_commitish\": \"main\",\n" +
|
||||
" \"name\": \"v1.0.0\",\n" +
|
||||
" \"body\": \"Description of the release\",\n" +
|
||||
" \"draft\": false,\n" +
|
||||
" \"prerelease\": false,\n" +
|
||||
" \"created_at\": \"2013-02-27T19:35:32Z\",\n" +
|
||||
" \"published_at\": \"2013-02-27T19:35:32Z\",\n" +
|
||||
" \"author\": {\n" +
|
||||
" \"login\": \"sjohnr\",\n" +
|
||||
" \"id\": 1,\n" +
|
||||
" \"node_id\": \"MDQ6VXNlcjE=\",\n" +
|
||||
" \"avatar_url\": \"https://github.com/images/avatar.gif\",\n" +
|
||||
" \"gravatar_id\": \"\",\n" +
|
||||
" \"url\": \"https://api.github.com/users/sjohnr\",\n" +
|
||||
" \"html_url\": \"https://github.com/sjohnr\",\n" +
|
||||
" \"followers_url\": \"https://api.github.com/users/sjohnr/followers\",\n" +
|
||||
" \"following_url\": \"https://api.github.com/users/sjohnr/following{/other_user}\",\n" +
|
||||
" \"gists_url\": \"https://api.github.com/users/sjohnr/gists{/gist_id}\",\n" +
|
||||
" \"starred_url\": \"https://api.github.com/users/sjohnr/starred{/owner}{/repo}\",\n" +
|
||||
" \"subscriptions_url\": \"https://api.github.com/users/sjohnr/subscriptions\",\n" +
|
||||
" \"organizations_url\": \"https://api.github.com/users/sjohnr/orgs\",\n" +
|
||||
" \"repos_url\": \"https://api.github.com/users/sjohnr/repos\",\n" +
|
||||
" \"events_url\": \"https://api.github.com/users/sjohnr/events{/privacy}\",\n" +
|
||||
" \"received_events_url\": \"https://api.github.com/users/sjohnr/received_events\",\n" +
|
||||
" \"type\": \"User\",\n" +
|
||||
" \"site_admin\": false\n" +
|
||||
" },\n" +
|
||||
" \"assets\": [\n" +
|
||||
" {\n" +
|
||||
" \"url\": \"https://api.github.com/spring-projects/spring-security/releases/assets/1\",\n" +
|
||||
" \"browser_download_url\": \"https://github.com/spring-projects/spring-security/releases/download/v1.0.0/example.zip\",\n" +
|
||||
" \"id\": 1,\n" +
|
||||
" \"node_id\": \"MDEyOlJlbGVhc2VBc3NldDE=\",\n" +
|
||||
" \"name\": \"example.zip\",\n" +
|
||||
" \"label\": \"short description\",\n" +
|
||||
" \"state\": \"uploaded\",\n" +
|
||||
" \"content_type\": \"application/zip\",\n" +
|
||||
" \"size\": 1024,\n" +
|
||||
" \"download_count\": 42,\n" +
|
||||
" \"created_at\": \"2013-02-27T19:35:32Z\",\n" +
|
||||
" \"updated_at\": \"2013-02-27T19:35:32Z\",\n" +
|
||||
" \"uploader\": {\n" +
|
||||
" \"login\": \"sjohnr\",\n" +
|
||||
" \"id\": 1,\n" +
|
||||
" \"node_id\": \"MDQ6VXNlcjE=\",\n" +
|
||||
" \"avatar_url\": \"https://github.com/images/avatar.gif\",\n" +
|
||||
" \"gravatar_id\": \"\",\n" +
|
||||
" \"url\": \"https://api.github.com/users/sjohnr\",\n" +
|
||||
" \"html_url\": \"https://github.com/sjohnr\",\n" +
|
||||
" \"followers_url\": \"https://api.github.com/users/sjohnr/followers\",\n" +
|
||||
" \"following_url\": \"https://api.github.com/users/sjohnr/following{/other_user}\",\n" +
|
||||
" \"gists_url\": \"https://api.github.com/users/sjohnr/gists{/gist_id}\",\n" +
|
||||
" \"starred_url\": \"https://api.github.com/users/sjohnr/starred{/owner}{/repo}\",\n" +
|
||||
" \"subscriptions_url\": \"https://api.github.com/users/sjohnr/subscriptions\",\n" +
|
||||
" \"organizations_url\": \"https://api.github.com/users/sjohnr/orgs\",\n" +
|
||||
" \"repos_url\": \"https://api.github.com/users/sjohnr/repos\",\n" +
|
||||
" \"events_url\": \"https://api.github.com/users/sjohnr/events{/privacy}\",\n" +
|
||||
" \"received_events_url\": \"https://api.github.com/users/sjohnr/received_events\",\n" +
|
||||
" \"type\": \"User\",\n" +
|
||||
" \"site_admin\": false\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
this.server.enqueue(new MockResponse().setBody(responseJson));
|
||||
this.github.publishRelease(this.repository, Release.tag("1.0.0").build());
|
||||
|
||||
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
|
||||
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("post");
|
||||
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/releases");
|
||||
assertThat(recordedRequest.getBody().toString()).isEqualTo("{\"tag_name\":\"1.0.0\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishReleaseWhenErrorResponseThenException() throws Exception {
|
||||
this.server.enqueue(new MockResponse().setResponseCode(400));
|
||||
assertThatExceptionOfType(RuntimeException.class)
|
||||
.isThrownBy(() -> this.github.publishRelease(this.repository, Release.tag("1.0.0").build()));
|
||||
}
|
||||
}
|
||||
+1
-19
@@ -42,8 +42,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.context.NullSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -207,8 +205,6 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
|
||||
private AuthenticationFailureHandler proxyFailureHandler = new SimpleUrlAuthenticationFailureHandler();
|
||||
|
||||
private SecurityContextRepository securityContextRepository = new NullSecurityContextRepository();
|
||||
|
||||
public CasAuthenticationFilter() {
|
||||
super("/login/cas");
|
||||
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
|
||||
@@ -227,7 +223,6 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(authResult);
|
||||
SecurityContextHolder.setContext(context);
|
||||
this.securityContextRepository.saveContext(context, request, response);
|
||||
if (this.eventPublisher != null) {
|
||||
this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
|
||||
}
|
||||
@@ -251,8 +246,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
this.logger.debug("Failed to obtain an artifact (cas ticket)");
|
||||
password = "";
|
||||
}
|
||||
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
|
||||
password);
|
||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
|
||||
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
return this.getAuthenticationManager().authenticate(authRequest);
|
||||
}
|
||||
@@ -280,18 +274,6 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link SecurityContextRepository} to save the {@link SecurityContext} on
|
||||
* authentication success. The default action is not to save the
|
||||
* {@link SecurityContext}.
|
||||
* @param securityContextRepository the {@link SecurityContextRepository} to use.
|
||||
* Cannot be null.
|
||||
*/
|
||||
public void setSecurityContextRepository(SecurityContextRepository securityContextRepository) {
|
||||
Assert.notNull(securityContextRepository, "securityContextRepository cannot be null");
|
||||
this.securityContextRepository = securityContextRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationFailureHandler} for proxy requests.
|
||||
* @param proxyFailureHandler
|
||||
|
||||
+12
-12
@@ -87,8 +87,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setServiceProperties(makeServiceProperties());
|
||||
cap.setTicketValidator(new MockTicketValidator(true));
|
||||
cap.afterPropertiesSet();
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "ST-123");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
|
||||
CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "ST-123");
|
||||
token.setDetails("details");
|
||||
Authentication result = cap.authenticate(token);
|
||||
// Confirm ST-123 was NOT added to the cache
|
||||
@@ -120,8 +120,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setTicketValidator(new MockTicketValidator(true));
|
||||
cap.setServiceProperties(makeServiceProperties());
|
||||
cap.afterPropertiesSet();
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, "ST-456");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
|
||||
CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, "ST-456");
|
||||
token.setDetails("details");
|
||||
Authentication result = cap.authenticate(token);
|
||||
// Confirm ST-456 was added to the cache
|
||||
@@ -157,8 +157,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setServiceProperties(serviceProperties);
|
||||
cap.afterPropertiesSet();
|
||||
String ticket = "ST-456";
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
|
||||
CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
|
||||
Authentication result = cap.authenticate(token);
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setServiceProperties(serviceProperties);
|
||||
cap.afterPropertiesSet();
|
||||
String ticket = "ST-456";
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
|
||||
CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
|
||||
Authentication result = cap.authenticate(token);
|
||||
verify(validator).validate(ticket, serviceProperties.getService());
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
@@ -211,8 +211,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setTicketValidator(new MockTicketValidator(true));
|
||||
cap.setServiceProperties(makeServiceProperties());
|
||||
cap.afterPropertiesSet();
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
|
||||
.unauthenticated(CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
|
||||
CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "");
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> cap.authenticate(token));
|
||||
}
|
||||
|
||||
@@ -314,8 +314,8 @@ public class CasAuthenticationProviderTests {
|
||||
cap.setTicketValidator(new MockTicketValidator(true));
|
||||
cap.setServiceProperties(makeServiceProperties());
|
||||
cap.afterPropertiesSet();
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
|
||||
.authenticated("some_normal_user", "password", AuthorityUtils.createAuthorityList("ROLE_A"));
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("some_normal_user",
|
||||
"password", AuthorityUtils.createAuthorityList("ROLE_A"));
|
||||
assertThat(cap.authenticate(token)).isNull();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -121,8 +121,8 @@ public class CasAuthenticationTokenTests {
|
||||
final Assertion assertion = new AssertionImpl("test");
|
||||
CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
|
||||
makeUserDetails(), assertion);
|
||||
UsernamePasswordAuthenticationToken token2 = UsernamePasswordAuthenticationToken.authenticated("Test",
|
||||
"Password", this.ROLES);
|
||||
UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
this.ROLES);
|
||||
assertThat(!token1.equals(token2)).isTrue();
|
||||
}
|
||||
|
||||
|
||||
-36
@@ -21,7 +21,6 @@ import javax.servlet.FilterChain;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -33,15 +32,12 @@ import org.springframework.security.cas.ServiceProperties;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -186,38 +182,6 @@ public class CasAuthenticationFilterTests {
|
||||
verify(successHandler).onAuthenticationSuccess(request, response, authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurityContextHolder() throws Exception {
|
||||
SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class);
|
||||
AuthenticationManager manager = mock(AuthenticationManager.class);
|
||||
Authentication authentication = new TestingAuthenticationToken("un", "pwd", "ROLE_USER");
|
||||
given(manager.authenticate(any(Authentication.class))).willReturn(authentication);
|
||||
ServiceProperties serviceProperties = new ServiceProperties();
|
||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setParameter("ticket", "ST-1-123");
|
||||
request.setServletPath("/authenticate");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain chain = mock(FilterChain.class);
|
||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||
filter.setServiceProperties(serviceProperties);
|
||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||
filter.setAuthenticationManager(manager);
|
||||
filter.setSecurityContextRepository(securityContextRepository);
|
||||
filter.afterPropertiesSet();
|
||||
filter.doFilter(request, response, chain);
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull()
|
||||
.withFailMessage("Authentication should not be null");
|
||||
verify(chain).doFilter(request, response);
|
||||
// validate for when the filterProcessUrl matches
|
||||
filter.setFilterProcessesUrl(request.getServletPath());
|
||||
SecurityContextHolder.clearContext();
|
||||
filter.doFilter(request, response, chain);
|
||||
ArgumentCaptor<SecurityContext> contextArg = ArgumentCaptor.forClass(SecurityContext.class);
|
||||
verify(securityContextRepository).saveContext(contextArg.capture(), eq(request), eq(response));
|
||||
assertThat(contextArg.getValue().getAuthentication().getPrincipal()).isEqualTo(authentication.getName());
|
||||
}
|
||||
|
||||
// SEC-1592
|
||||
@Test
|
||||
public void testChainNotInvokedForProxyReceptor() throws Exception {
|
||||
|
||||
@@ -76,7 +76,6 @@ dependencies {
|
||||
testImplementation "org.apache.directory.server:apacheds-protocol-ldap"
|
||||
testImplementation "org.apache.directory.server:apacheds-server-jndi"
|
||||
testImplementation 'org.apache.directory.shared:shared-ldap'
|
||||
testImplementation "com.unboundid:unboundid-ldapsdk"
|
||||
testImplementation 'org.eclipse.persistence:javax.persistence'
|
||||
testImplementation('org.hibernate:hibernate-entitymanager') {
|
||||
exclude group: 'javax.activation', module: 'javax.activation-api'
|
||||
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.ldap.core.support.LdapContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class EmbeddedLdapServerContextSourceFactoryBeanITests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void contextSourceFactoryBeanWhenEmbeddedServerThenAuthenticates() throws Exception {
|
||||
this.spring.register(FromEmbeddedLdapServerConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextSourceFactoryBeanWhenPortZeroThenAuthenticates() throws Exception {
|
||||
this.spring.register(PortZeroConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextSourceFactoryBeanWhenCustomLdifAndRootThenAuthenticates() throws Exception {
|
||||
this.spring.register(CustomLdifAndRootConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("pg").password("password")).andExpect(authenticated().withUsername("pg"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextSourceFactoryBeanWhenCustomManagerDnThenAuthenticates() throws Exception {
|
||||
this.spring.register(CustomManagerDnConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextSourceFactoryBeanWhenManagerDnAndNoPasswordThenException() {
|
||||
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
|
||||
.isThrownBy(() -> this.spring.register(CustomManagerDnNoPasswordConfig.class).autowire())
|
||||
.withRootCauseInstanceOf(IllegalStateException.class)
|
||||
.withMessageContaining("managerPassword is required if managerDn is supplied");
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class FromEmbeddedLdapServerConfig {
|
||||
|
||||
@Bean
|
||||
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
|
||||
return EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(LdapContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class PortZeroConfig {
|
||||
|
||||
@Bean
|
||||
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
|
||||
EmbeddedLdapServerContextSourceFactoryBean factoryBean = EmbeddedLdapServerContextSourceFactoryBean
|
||||
.fromEmbeddedLdapServer();
|
||||
factoryBean.setPort(0);
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(LdapContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomLdifAndRootConfig {
|
||||
|
||||
@Bean
|
||||
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
|
||||
EmbeddedLdapServerContextSourceFactoryBean factoryBean = EmbeddedLdapServerContextSourceFactoryBean
|
||||
.fromEmbeddedLdapServer();
|
||||
factoryBean.setLdif("classpath*:test-server2.xldif");
|
||||
factoryBean.setRoot("dc=monkeymachine,dc=co,dc=uk");
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(LdapContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=gorillas");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomManagerDnConfig {
|
||||
|
||||
@Bean
|
||||
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
|
||||
EmbeddedLdapServerContextSourceFactoryBean factoryBean = EmbeddedLdapServerContextSourceFactoryBean
|
||||
.fromEmbeddedLdapServer();
|
||||
factoryBean.setManagerDn("uid=admin,ou=system");
|
||||
factoryBean.setManagerPassword("secret");
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(LdapContextSource contextSource) {
|
||||
LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(
|
||||
contextSource, NoOpPasswordEncoder.getInstance());
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomManagerDnNoPasswordConfig {
|
||||
|
||||
@Bean
|
||||
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
|
||||
EmbeddedLdapServerContextSourceFactoryBean factoryBean = EmbeddedLdapServerContextSourceFactoryBean
|
||||
.fromEmbeddedLdapServer();
|
||||
factoryBean.setManagerDn("uid=admin,ou=system");
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(LdapContextSource contextSource) {
|
||||
LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(
|
||||
contextSource, NoOpPasswordEncoder.getInstance());
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-241
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.ldap.core.support.LdapContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class LdapBindAuthenticationManagerFactoryITests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenFromContextSourceThenAuthenticates() throws Exception {
|
||||
this.spring.register(FromContextSourceConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ldapAuthenticationProviderCustomLdapAuthoritiesPopulator() throws Exception {
|
||||
CustomAuthoritiesPopulatorConfig.LAP = new DefaultLdapAuthoritiesPopulator(mock(LdapContextSource.class),
|
||||
null) {
|
||||
@Override
|
||||
protected Set<GrantedAuthority> getAdditionalRoles(DirContextOperations user, String username) {
|
||||
return new HashSet<>(AuthorityUtils.createAuthorityList("ROLE_EXTRA"));
|
||||
}
|
||||
};
|
||||
|
||||
this.spring.register(CustomAuthoritiesPopulatorConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(
|
||||
authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenCustomAuthoritiesMapperThenUsed() throws Exception {
|
||||
CustomAuthoritiesMapperConfig.AUTHORITIES_MAPPER = ((authorities) -> AuthorityUtils
|
||||
.createAuthorityList("ROLE_CUSTOM"));
|
||||
|
||||
this.spring.register(CustomAuthoritiesMapperConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(
|
||||
authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_CUSTOM"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenCustomUserDetailsContextMapperThenUsed() throws Exception {
|
||||
CustomUserDetailsContextMapperConfig.CONTEXT_MAPPER = new UserDetailsContextMapper() {
|
||||
@Override
|
||||
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
|
||||
Collection<? extends GrantedAuthority> authorities) {
|
||||
return User.withUsername("other").password("password").roles("USER").build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
|
||||
}
|
||||
};
|
||||
|
||||
this.spring.register(CustomUserDetailsContextMapperConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("other"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenCustomUserDnPatternsThenUsed() throws Exception {
|
||||
this.spring.register(CustomUserDnPatternsConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenCustomUserSearchThenUsed() throws Exception {
|
||||
this.spring.register(CustomUserSearchConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class FromContextSourceConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomAuthoritiesMapperConfig extends BaseLdapServerConfig {
|
||||
|
||||
static GrantedAuthoritiesMapper AUTHORITIES_MAPPER;
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
factory.setAuthoritiesMapper(AUTHORITIES_MAPPER);
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomAuthoritiesPopulatorConfig extends BaseLdapServerConfig {
|
||||
|
||||
static LdapAuthoritiesPopulator LAP;
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
factory.setLdapAuthoritiesPopulator(LAP);
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomUserDetailsContextMapperConfig extends BaseLdapServerConfig {
|
||||
|
||||
static UserDetailsContextMapper CONTEXT_MAPPER;
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
factory.setUserDetailsContextMapper(CONTEXT_MAPPER);
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomUserDnPatternsConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomUserSearchConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserSearchFilter("uid={0}");
|
||||
factory.setUserSearchBase("ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
abstract static class BaseLdapServerConfig implements DisposableBean {
|
||||
|
||||
private ApacheDSContainer container;
|
||||
|
||||
@Bean
|
||||
ApacheDSContainer ldapServer() throws Exception {
|
||||
this.container = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
||||
this.container.setPort(0);
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
BaseLdapPathContextSource contextSource(ApacheDSContainer container) {
|
||||
int port = container.getLocalPort();
|
||||
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.container.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-114
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class LdapPasswordComparisonAuthenticationManagerFactoryITests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenCustomPasswordEncoderThenUsed() throws Exception {
|
||||
this.spring.register(CustomPasswordEncoderConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
|
||||
.andExpect(authenticated().withUsername("bcrypt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerFactoryWhenCustomPasswordAttributeThenUsed() throws Exception {
|
||||
this.spring.register(CustomPasswordAttributeConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bob")).andExpect(authenticated().withUsername("bob"));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomPasswordEncoderConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(
|
||||
contextSource, new BCryptPasswordEncoder());
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomPasswordAttributeConfig extends BaseLdapServerConfig {
|
||||
|
||||
@Bean
|
||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapPasswordComparisonAuthenticationManagerFactory factory = new LdapPasswordComparisonAuthenticationManagerFactory(
|
||||
contextSource, NoOpPasswordEncoder.getInstance());
|
||||
factory.setPasswordAttribute("uid");
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
abstract static class BaseLdapServerConfig implements DisposableBean {
|
||||
|
||||
private ApacheDSContainer container;
|
||||
|
||||
@Bean
|
||||
ApacheDSContainer ldapServer() throws Exception {
|
||||
this.container = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
||||
this.container.setPort(0);
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
BaseLdapPathContextSource contextSource(ApacheDSContainer container) {
|
||||
int port = container.getLocalPort();
|
||||
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.container.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -56,7 +56,7 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("ben", "benspassword"));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
UserDetails ben = (UserDetails) auth.getPrincipal();
|
||||
assertThat(ben.getAuthorities()).hasSize(3);
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("ben", "benspassword"));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
|
||||
|
||||
assertThat(auth).isNotNull();
|
||||
}
|
||||
@@ -104,8 +104,7 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("ben", "ben"));
|
||||
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"));
|
||||
|
||||
assertThat(auth).isNotNull();
|
||||
}
|
||||
@@ -122,7 +121,7 @@ public class LdapProviderBeanDefinitionParserTests {
|
||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||
AuthenticationManager.class);
|
||||
Authentication auth = authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("bcrypt", "password"));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", "password"));
|
||||
|
||||
assertThat(auth).isNotNull();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -138,10 +138,4 @@ public abstract class Elements {
|
||||
|
||||
public static final String PASSWORD_MANAGEMENT = "password-management";
|
||||
|
||||
public static final String RELYING_PARTY_REGISTRATIONS = "relying-party-registrations";
|
||||
|
||||
public static final String SAML2_LOGIN = "saml2-login";
|
||||
|
||||
public static final String SAML2_LOGOUT = "saml2-logout";
|
||||
|
||||
}
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2009-2022 the original author or authors.
|
||||
* Copyright 2009-2020 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.
|
||||
@@ -47,7 +47,6 @@ import org.springframework.security.config.method.InterceptMethodsBeanDefinition
|
||||
import org.springframework.security.config.method.MethodSecurityBeanDefinitionParser;
|
||||
import org.springframework.security.config.method.MethodSecurityMetadataSourceBeanDefinitionParser;
|
||||
import org.springframework.security.config.oauth2.client.ClientRegistrationsBeanDefinitionParser;
|
||||
import org.springframework.security.config.saml2.RelyingPartyRegistrationsBeanDefinitionParser;
|
||||
import org.springframework.security.config.websocket.WebSocketMessageBrokerSecurityBeanDefinitionParser;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -95,7 +94,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
if (!namespaceMatchesVersion(element)) {
|
||||
pc.getReaderContext().fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or "
|
||||
+ "spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
|
||||
+ "with Spring Security 5.7. Please update your schema declarations to the 5.7 schema.", element);
|
||||
+ "with Spring Security 5.6. Please update your schema declarations to the 5.6 schema.", element);
|
||||
}
|
||||
String name = pc.getDelegate().getLocalName(element);
|
||||
BeanDefinitionParser parser = this.parsers.get(name);
|
||||
@@ -191,7 +190,6 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
this.parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
|
||||
this.filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
|
||||
this.parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser());
|
||||
this.parsers.put(Elements.RELYING_PARTY_REGISTRATIONS, new RelyingPartyRegistrationsBeanDefinitionParser());
|
||||
}
|
||||
|
||||
private void loadWebSocketParsers() {
|
||||
@@ -217,7 +215,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
||||
|
||||
private boolean matchesVersionInternal(Element element) {
|
||||
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||
return schemaLocation.matches("(?m).*spring-security-5\\.7.*.xsd.*")
|
||||
return schemaLocation.matches("(?m).*spring-security-5\\.6.*.xsd.*")
|
||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||
}
|
||||
|
||||
+23
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -17,16 +17,16 @@
|
||||
package org.springframework.security.config.annotation.method.configuration;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
|
||||
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
||||
import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager;
|
||||
@@ -45,64 +45,59 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
final class PrePostMethodSecurityConfiguration {
|
||||
final class PrePostMethodSecurityConfiguration implements ApplicationContextAware {
|
||||
|
||||
private final PreFilterAuthorizationMethodInterceptor preFilterAuthorizationMethodInterceptor = new PreFilterAuthorizationMethodInterceptor();
|
||||
|
||||
private final AuthorizationManagerBeforeMethodInterceptor preAuthorizeAuthorizationMethodInterceptor;
|
||||
|
||||
private final PreAuthorizeAuthorizationManager preAuthorizeAuthorizationManager = new PreAuthorizeAuthorizationManager();
|
||||
|
||||
private final AuthorizationManagerAfterMethodInterceptor postAuthorizeAuthorizaitonMethodInterceptor;
|
||||
|
||||
private final PostAuthorizeAuthorizationManager postAuthorizeAuthorizationManager = new PostAuthorizeAuthorizationManager();
|
||||
|
||||
private final PostFilterAuthorizationMethodInterceptor postFilterAuthorizationMethodInterceptor = new PostFilterAuthorizationMethodInterceptor();
|
||||
|
||||
private final DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
|
||||
@Autowired
|
||||
PrePostMethodSecurityConfiguration(ApplicationContext context) {
|
||||
this.preAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||
this.preAuthorizeAuthorizationMethodInterceptor = AuthorizationManagerBeforeMethodInterceptor
|
||||
.preAuthorize(this.preAuthorizeAuthorizationManager);
|
||||
this.postAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||
this.postAuthorizeAuthorizaitonMethodInterceptor = AuthorizationManagerAfterMethodInterceptor
|
||||
.postAuthorize(this.postAuthorizeAuthorizationManager);
|
||||
this.preFilterAuthorizationMethodInterceptor.setExpressionHandler(this.expressionHandler);
|
||||
this.postFilterAuthorizationMethodInterceptor.setExpressionHandler(this.expressionHandler);
|
||||
this.expressionHandler.setApplicationContext(context);
|
||||
AuthorizationEventPublisher publisher = new SpringAuthorizationEventPublisher(context);
|
||||
this.preAuthorizeAuthorizationMethodInterceptor.setAuthorizationEventPublisher(publisher);
|
||||
this.postAuthorizeAuthorizaitonMethodInterceptor.setAuthorizationEventPublisher(publisher);
|
||||
}
|
||||
private boolean customMethodSecurityExpressionHandler = false;
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
Advisor preFilterAuthorizationMethodInterceptor() {
|
||||
if (!this.customMethodSecurityExpressionHandler) {
|
||||
this.preAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||
}
|
||||
return this.preFilterAuthorizationMethodInterceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
Advisor preAuthorizeAuthorizationMethodInterceptor() {
|
||||
return this.preAuthorizeAuthorizationMethodInterceptor;
|
||||
if (!this.customMethodSecurityExpressionHandler) {
|
||||
this.preAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||
}
|
||||
return AuthorizationManagerBeforeMethodInterceptor.preAuthorize(this.preAuthorizeAuthorizationManager);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
Advisor postAuthorizeAuthorizationMethodInterceptor() {
|
||||
return this.postAuthorizeAuthorizaitonMethodInterceptor;
|
||||
if (!this.customMethodSecurityExpressionHandler) {
|
||||
this.postAuthorizeAuthorizationManager.setExpressionHandler(this.expressionHandler);
|
||||
}
|
||||
return AuthorizationManagerAfterMethodInterceptor.postAuthorize(this.postAuthorizeAuthorizationManager);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
Advisor postFilterAuthorizationMethodInterceptor() {
|
||||
if (!this.customMethodSecurityExpressionHandler) {
|
||||
this.postFilterAuthorizationMethodInterceptor.setExpressionHandler(this.expressionHandler);
|
||||
}
|
||||
return this.postFilterAuthorizationMethodInterceptor;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setMethodSecurityExpressionHandler(MethodSecurityExpressionHandler methodSecurityExpressionHandler) {
|
||||
this.customMethodSecurityExpressionHandler = true;
|
||||
this.preFilterAuthorizationMethodInterceptor.setExpressionHandler(methodSecurityExpressionHandler);
|
||||
this.preAuthorizeAuthorizationManager.setExpressionHandler(methodSecurityExpressionHandler);
|
||||
this.postAuthorizeAuthorizationManager.setExpressionHandler(methodSecurityExpressionHandler);
|
||||
@@ -114,10 +109,9 @@ final class PrePostMethodSecurityConfiguration {
|
||||
this.expressionHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix());
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setAuthorizationEventPublisher(AuthorizationEventPublisher eventPublisher) {
|
||||
this.preAuthorizeAuthorizationMethodInterceptor.setAuthorizationEventPublisher(eventPublisher);
|
||||
this.postAuthorizeAuthorizaitonMethodInterceptor.setAuthorizationEventPublisher(eventPublisher);
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.expressionHandler.setApplicationContext(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-4
@@ -42,8 +42,6 @@ import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.DisableEncodeUrlFilter;
|
||||
import org.springframework.security.web.session.ForceEagerSessionCreationFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
|
||||
/**
|
||||
@@ -126,8 +124,6 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>>
|
||||
* The ordering of the Filters is:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link ForceEagerSessionCreationFilter}</li>
|
||||
* <li>{@link DisableEncodeUrlFilter}</li>
|
||||
* <li>{@link ChannelProcessingFilter}</li>
|
||||
* <li>{@link SecurityContextPersistenceFilter}</li>
|
||||
* <li>{@link LogoutFilter}</li>
|
||||
|
||||
-6
@@ -37,7 +37,6 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera
|
||||
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;
|
||||
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
@@ -46,8 +45,6 @@ import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.DisableEncodeUrlFilter;
|
||||
import org.springframework.security.web.session.ForceEagerSessionCreationFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
@@ -70,12 +67,9 @@ final class FilterOrderRegistration {
|
||||
|
||||
FilterOrderRegistration() {
|
||||
Step order = new Step(INITIAL_ORDER, ORDER_STEP);
|
||||
put(DisableEncodeUrlFilter.class, order.next());
|
||||
put(ForceEagerSessionCreationFilter.class, order.next());
|
||||
put(ChannelProcessingFilter.class, order.next());
|
||||
order.next(); // gh-8105
|
||||
put(WebAsyncManagerIntegrationFilter.class, order.next());
|
||||
put(SecurityContextHolderFilter.class, order.next());
|
||||
put(SecurityContextPersistenceFilter.class, order.next());
|
||||
put(HeaderWriterFilter.class, order.next());
|
||||
put(CorsFilter.class, order.next());
|
||||
|
||||
-7
@@ -2889,15 +2889,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected DefaultSecurityFilterChain performBuild() {
|
||||
ExpressionUrlAuthorizationConfigurer<?> expressionConfigurer = getConfigurer(
|
||||
ExpressionUrlAuthorizationConfigurer.class);
|
||||
AuthorizeHttpRequestsConfigurer<?> httpConfigurer = getConfigurer(AuthorizeHttpRequestsConfigurer.class);
|
||||
boolean oneConfigurerPresent = expressionConfigurer == null ^ httpConfigurer == null;
|
||||
Assert.state((expressionConfigurer == null && httpConfigurer == null) || oneConfigurerPresent,
|
||||
"authorizeHttpRequests cannot be used in conjunction with authorizeRequests. Please select just one.");
|
||||
this.filters.sort(OrderComparator.INSTANCE);
|
||||
List<Filter> sortedFilters = new ArrayList<>(this.filters.size());
|
||||
for (Filter filter : this.filters) {
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -279,19 +279,6 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handler to handle
|
||||
* {@link org.springframework.security.web.firewall.RequestRejectedException}
|
||||
* @param requestRejectedHandler
|
||||
* @return the {@link WebSecurity} for further customizations
|
||||
* @since 5.7
|
||||
*/
|
||||
public WebSecurity requestRejectedHandler(RequestRejectedHandler requestRejectedHandler) {
|
||||
Assert.notNull(requestRejectedHandler, "requestRejectedHandler cannot be null");
|
||||
this.requestRejectedHandler = requestRejectedHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Filter performBuild() throws Exception {
|
||||
Assert.state(!this.securityFilterChainBuilders.isEmpty(),
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -25,13 +24,11 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
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.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
|
||||
@@ -100,7 +97,6 @@ class HttpSecurityConfiguration {
|
||||
.apply(new DefaultLoginPageConfigurer<>());
|
||||
http.logout(withDefaults());
|
||||
// @formatter:on
|
||||
applyDefaultConfigurers(http);
|
||||
return http;
|
||||
}
|
||||
|
||||
@@ -109,15 +105,6 @@ class HttpSecurityConfiguration {
|
||||
: this.authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
private void applyDefaultConfigurers(HttpSecurity http) throws Exception {
|
||||
ClassLoader classLoader = this.context.getClassLoader();
|
||||
List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader
|
||||
.loadFactories(AbstractHttpConfigurer.class, classLoader);
|
||||
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
|
||||
http.apply(configurer);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Class<?>, Object> createSharedObjects() {
|
||||
Map<Class<?>, Object> sharedObjects = new HashMap<>();
|
||||
sharedObjects.put(ApplicationContext.class, this.context);
|
||||
|
||||
+31
-142
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -16,14 +16,10 @@
|
||||
|
||||
package org.springframework.security.config.annotation.web.configuration;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -71,22 +67,17 @@ class SecurityReactorContextConfiguration {
|
||||
|
||||
private static final String SECURITY_REACTOR_CONTEXT_OPERATOR_KEY = "org.springframework.security.SECURITY_REACTOR_CONTEXT_OPERATOR";
|
||||
|
||||
private static final Map<Object, Supplier<Object>> CONTEXT_ATTRIBUTE_VALUE_LOADERS = new HashMap<>();
|
||||
|
||||
static {
|
||||
CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(HttpServletRequest.class,
|
||||
SecurityReactorContextSubscriberRegistrar::getRequest);
|
||||
CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(HttpServletResponse.class,
|
||||
SecurityReactorContextSubscriberRegistrar::getResponse);
|
||||
CONTEXT_ATTRIBUTE_VALUE_LOADERS.put(Authentication.class,
|
||||
SecurityReactorContextSubscriberRegistrar::getAuthentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Function<? super Publisher<Object>, ? extends Publisher<Object>> lifter = Operators
|
||||
.liftPublisher((pub, sub) -> createSubscriberIfNecessary(sub));
|
||||
Hooks.onLastOperator(SECURITY_REACTOR_CONTEXT_OPERATOR_KEY, lifter::apply);
|
||||
Hooks.onLastOperator(SECURITY_REACTOR_CONTEXT_OPERATOR_KEY, (pub) -> {
|
||||
if (!contextAttributesAvailable()) {
|
||||
// No need to decorate so return original Publisher
|
||||
return pub;
|
||||
}
|
||||
return lifter.apply(pub);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,30 +93,36 @@ class SecurityReactorContextConfiguration {
|
||||
return new SecurityReactorContextSubscriber<>(delegate, getContextAttributes());
|
||||
}
|
||||
|
||||
private static boolean contextAttributesAvailable() {
|
||||
return SecurityContextHolder.getContext().getAuthentication() != null
|
||||
|| RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes;
|
||||
}
|
||||
|
||||
private static Map<Object, Object> getContextAttributes() {
|
||||
return new LoadingMap<>(CONTEXT_ATTRIBUTE_VALUE_LOADERS);
|
||||
}
|
||||
|
||||
private static HttpServletRequest getRequest() {
|
||||
HttpServletRequest servletRequest = null;
|
||||
HttpServletResponse servletResponse = null;
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
if (requestAttributes instanceof ServletRequestAttributes) {
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
|
||||
return servletRequestAttributes.getRequest();
|
||||
servletRequest = servletRequestAttributes.getRequest();
|
||||
servletResponse = servletRequestAttributes.getResponse(); // possible null
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HttpServletResponse getResponse() {
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
if (requestAttributes instanceof ServletRequestAttributes) {
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
|
||||
return servletRequestAttributes.getResponse(); // possible null
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication == null && servletRequest == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<Object, Object> contextAttributes = new HashMap<>();
|
||||
if (servletRequest != null) {
|
||||
contextAttributes.put(HttpServletRequest.class, servletRequest);
|
||||
}
|
||||
if (servletResponse != null) {
|
||||
contextAttributes.put(HttpServletResponse.class, servletResponse);
|
||||
}
|
||||
if (authentication != null) {
|
||||
contextAttributes.put(Authentication.class, authentication);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Authentication getAuthentication() {
|
||||
return SecurityContextHolder.getContext().getAuthentication();
|
||||
return contextAttributes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -178,112 +175,4 @@ class SecurityReactorContextConfiguration {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A map that computes each value when {@link #get} is invoked
|
||||
*/
|
||||
static class LoadingMap<K, V> implements Map<K, V> {
|
||||
|
||||
private final Map<K, V> loaded = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<K, Supplier<V>> loaders;
|
||||
|
||||
LoadingMap(Map<K, Supplier<V>> loaders) {
|
||||
this.loaders = Collections.unmodifiableMap(new HashMap<>(loaders));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.loaders.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.loaders.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return this.loaders.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return this.loaders.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
if (!this.loaders.containsKey(key)) {
|
||||
throw new IllegalArgumentException(
|
||||
"This map only supports the following keys: " + this.loaders.keySet());
|
||||
}
|
||||
return this.loaded.computeIfAbsent((K) key, (k) -> this.loaders.get(k).get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
if (!this.loaders.containsKey(key)) {
|
||||
throw new IllegalArgumentException(
|
||||
"This map only supports the following keys: " + this.loaders.keySet());
|
||||
}
|
||||
return this.loaded.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
if (!this.loaders.containsKey(key)) {
|
||||
throw new IllegalArgumentException(
|
||||
"This map only supports the following keys: " + this.loaders.keySet());
|
||||
}
|
||||
return this.loaded.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.loaded.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return this.loaded.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return this.loaded.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return this.loaded.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LoadingMap<?, ?> that = (LoadingMap<?, ?>) o;
|
||||
|
||||
return this.loaded.equals(that.loaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.loaded.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -24,6 +24,7 @@ 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.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -142,20 +143,19 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
* instances used to create the web configuration.
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} used to create a
|
||||
* {@link WebSecurity} instance
|
||||
* @param beanFactory the bean factory to use to retrieve the relevant
|
||||
* @param webSecurityConfigurers the
|
||||
* {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>} instances used to
|
||||
* create the web configuration
|
||||
* @throws Exception
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
|
||||
ConfigurableListableBeanFactory beanFactory) throws Exception {
|
||||
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
|
||||
throws Exception {
|
||||
this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
|
||||
if (this.debugEnabled != null) {
|
||||
this.webSecurity.debug(this.debugEnabled);
|
||||
}
|
||||
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new AutowiredWebSecurityConfigurersIgnoreParents(
|
||||
beanFactory).getWebSecurityConfigurers();
|
||||
webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
|
||||
Integer previousOrder = null;
|
||||
Object previousConfig = null;
|
||||
@@ -189,6 +189,12 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
|
||||
return new RsaKeyConversionServicePostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
Map<String, Object> enableWebSecurityAttrMap = importMetadata
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -89,12 +89,8 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @see EnableWebSecurity
|
||||
* @deprecated Use a {@link org.springframework.security.web.SecurityFilterChain} Bean to
|
||||
* configure {@link HttpSecurity} or a {@link WebSecurityCustomizer} Bean to configure
|
||||
* {@link WebSecurity}
|
||||
*/
|
||||
@Order(100)
|
||||
@Deprecated
|
||||
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {
|
||||
|
||||
private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class);
|
||||
|
||||
-12
@@ -38,7 +38,6 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
@@ -147,11 +146,6 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T securityContextRepository(SecurityContextRepository securityContextRepository) {
|
||||
this.authFilter.setSecurityContextRepository(securityContextRepository);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the {@link RequestMatcher} given a loginProcessingUrl
|
||||
* @param loginProcessingUrl creates the {@link RequestMatcher} based upon the
|
||||
@@ -293,12 +287,6 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
||||
if (rememberMeServices != null) {
|
||||
this.authFilter.setRememberMeServices(rememberMeServices);
|
||||
}
|
||||
SecurityContextConfigurer securityContextConfigurer = http.getConfigurer(SecurityContextConfigurer.class);
|
||||
if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {
|
||||
SecurityContextRepository securityContextRepository = securityContextConfigurer
|
||||
.getSecurityContextRepository();
|
||||
this.authFilter.setSecurityContextRepository(securityContextRepository);
|
||||
}
|
||||
F filter = postProcess(this.authFilter);
|
||||
http.addFilter(filter);
|
||||
}
|
||||
|
||||
+2
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -25,9 +25,7 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
@@ -36,7 +34,6 @@ import org.springframework.security.web.access.intercept.RequestAuthorizationCon
|
||||
import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -49,25 +46,14 @@ import org.springframework.util.Assert;
|
||||
public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
extends AbstractHttpConfigurer<AuthorizeHttpRequestsConfigurer<H>, H> {
|
||||
|
||||
static final AuthorizationManager<RequestAuthorizationContext> permitAllAuthorizationManager = (a,
|
||||
o) -> new AuthorizationDecision(true);
|
||||
|
||||
private final AuthorizationManagerRequestMatcherRegistry registry;
|
||||
|
||||
private final AuthorizationEventPublisher publisher;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
* @param context the {@link ApplicationContext} to use
|
||||
*/
|
||||
public AuthorizeHttpRequestsConfigurer(ApplicationContext context) {
|
||||
this.registry = new AuthorizationManagerRequestMatcherRegistry(context);
|
||||
if (context.getBeanNamesForType(AuthorizationEventPublisher.class).length > 0) {
|
||||
this.publisher = context.getBean(AuthorizationEventPublisher.class);
|
||||
}
|
||||
else {
|
||||
this.publisher = new SpringAuthorizationEventPublisher(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,8 +70,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
public void configure(H http) {
|
||||
AuthorizationManager<HttpServletRequest> authorizationManager = this.registry.createAuthorizationManager();
|
||||
AuthorizationFilter authorizationFilter = new AuthorizationFilter(authorizationManager);
|
||||
authorizationFilter.setAuthorizationEventPublisher(this.publisher);
|
||||
authorizationFilter.setShouldFilterAllDispatcherTypes(this.registry.shouldFilterAllDispatcherTypes);
|
||||
http.addFilter(postProcess(authorizationFilter));
|
||||
}
|
||||
|
||||
@@ -97,12 +81,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
AuthorizationManagerRequestMatcherRegistry addFirst(RequestMatcher matcher,
|
||||
AuthorizationManager<RequestAuthorizationContext> manager) {
|
||||
this.registry.addFirst(matcher, manager);
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registry for mapping a {@link RequestMatcher} to an {@link AuthorizationManager}.
|
||||
*
|
||||
@@ -118,8 +96,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
|
||||
private int mappingCount;
|
||||
|
||||
private boolean shouldFilterAllDispatcherTypes = false;
|
||||
|
||||
private AuthorizationManagerRequestMatcherRegistry(ApplicationContext context) {
|
||||
setApplicationContext(context);
|
||||
}
|
||||
@@ -130,12 +106,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
this.mappingCount++;
|
||||
}
|
||||
|
||||
private void addFirst(RequestMatcher matcher, AuthorizationManager<RequestAuthorizationContext> manager) {
|
||||
this.unmappedMatchers = null;
|
||||
this.managerBuilder.mappings((m) -> m.add(0, new RequestMatcherEntry<>(matcher, manager)));
|
||||
this.mappingCount++;
|
||||
}
|
||||
|
||||
private AuthorizationManager<HttpServletRequest> createAuthorizationManager() {
|
||||
Assert.state(this.unmappedMatchers == null,
|
||||
() -> "An incomplete mapping was found for " + this.unmappedMatchers
|
||||
@@ -173,19 +143,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether all dispatcher types should be filtered.
|
||||
* @param shouldFilter should filter all dispatcher types. Default is
|
||||
* {@code false}
|
||||
* @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
|
||||
* customizations
|
||||
* @since 5.7
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry shouldFilterAllDispatcherTypes(boolean shouldFilter) {
|
||||
this.shouldFilterAllDispatcherTypes = shouldFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link HttpSecurityBuilder} when done using the
|
||||
* {@link AuthorizeHttpRequestsConfigurer}. This is useful for method chaining.
|
||||
@@ -252,7 +209,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
||||
* customizations
|
||||
*/
|
||||
public AuthorizationManagerRequestMatcherRegistry permitAll() {
|
||||
return access(permitAllAuthorizationManager);
|
||||
return access((a, o) -> new AuthorizationDecision(true));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,9 +30,7 @@ import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
|
||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||
import org.springframework.security.web.access.channel.ChannelProcessor;
|
||||
@@ -77,7 +75,6 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
*
|
||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured
|
||||
* @author Rob Winch
|
||||
* @author Onur Kagan Ozcan
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
@@ -89,8 +86,6 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
private List<ChannelProcessor> channelProcessors;
|
||||
|
||||
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
private final ChannelRequestMatcherRegistry REGISTRY;
|
||||
|
||||
/**
|
||||
@@ -128,11 +123,9 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
if (portMapper != null) {
|
||||
RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint();
|
||||
httpEntryPoint.setPortMapper(portMapper);
|
||||
httpEntryPoint.setRedirectStrategy(this.redirectStrategy);
|
||||
insecureChannelProcessor.setEntryPoint(httpEntryPoint);
|
||||
RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint();
|
||||
httpsEntryPoint.setPortMapper(portMapper);
|
||||
httpsEntryPoint.setRedirectStrategy(this.redirectStrategy);
|
||||
secureChannelProcessor.setEntryPoint(httpsEntryPoint);
|
||||
}
|
||||
insecureChannelProcessor = postProcess(insecureChannelProcessor);
|
||||
@@ -192,17 +185,6 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RedirectStrategy} instances to use in
|
||||
* {@link RetryWithHttpEntryPoint} and {@link RetryWithHttpsEntryPoint}
|
||||
* @param redirectStrategy
|
||||
* @return the {@link ChannelSecurityConfigurer} for further customizations
|
||||
*/
|
||||
public ChannelRequestMatcherRegistry redirectStrategy(RedirectStrategy redirectStrategy) {
|
||||
ChannelSecurityConfigurer.this.redirectStrategy = redirectStrategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link SecurityBuilder} when done using the
|
||||
* {@link SecurityConfigurer}. This is useful for method chaining.
|
||||
|
||||
+3
-3
@@ -237,8 +237,8 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
/**
|
||||
* Gets the default {@link AccessDeniedHandler} from the
|
||||
* {@link ExceptionHandlingConfigurer#getAccessDeniedHandler(HttpSecurityBuilder)} or
|
||||
* create a {@link AccessDeniedHandlerImpl} if not available.
|
||||
* {@link ExceptionHandlingConfigurer#getAccessDeniedHandler()} or create a
|
||||
* {@link AccessDeniedHandlerImpl} if not available.
|
||||
* @param http the {@link HttpSecurityBuilder}
|
||||
* @return the {@link AccessDeniedHandler}
|
||||
*/
|
||||
@@ -247,7 +247,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
ExceptionHandlingConfigurer<H> exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
AccessDeniedHandler handler = null;
|
||||
if (exceptionConfig != null) {
|
||||
handler = exceptionConfig.getAccessDeniedHandler(http);
|
||||
handler = exceptionConfig.getAccessDeniedHandler();
|
||||
}
|
||||
if (handler == null) {
|
||||
handler = new AccessDeniedHandlerImpl();
|
||||
|
||||
+3
-1
@@ -369,7 +369,9 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs requires a specific IP Address or subnet.
|
||||
* Specify that URLs requires a specific IP Address or <a href=
|
||||
* "https://forum.spring.io/showthread.php?102783-How-to-use-hasIpAddress&p=343971#post343971"
|
||||
* >subnet</a>.
|
||||
* @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet
|
||||
* (i.e. 192.168.0/24)
|
||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
||||
|
||||
+1
-228
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -31,9 +31,6 @@ import org.springframework.security.web.header.HeaderWriter;
|
||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
||||
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.FeaturePolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.HpkpHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.HstsHeaderWriter;
|
||||
@@ -100,12 +97,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
private final PermissionsPolicyConfig permissionsPolicy = new PermissionsPolicyConfig();
|
||||
|
||||
private final CrossOriginOpenerPolicyConfig crossOriginOpenerPolicy = new CrossOriginOpenerPolicyConfig();
|
||||
|
||||
private final CrossOriginEmbedderPolicyConfig crossOriginEmbedderPolicy = new CrossOriginEmbedderPolicyConfig();
|
||||
|
||||
private final CrossOriginResourcePolicyConfig crossOriginResourcePolicy = new CrossOriginResourcePolicyConfig();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
@@ -401,9 +392,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
addIfNotNull(writers, this.referrerPolicy.writer);
|
||||
addIfNotNull(writers, this.featurePolicy.writer);
|
||||
addIfNotNull(writers, this.permissionsPolicy.writer);
|
||||
addIfNotNull(writers, this.crossOriginOpenerPolicy.writer);
|
||||
addIfNotNull(writers, this.crossOriginEmbedderPolicy.writer);
|
||||
addIfNotNull(writers, this.crossOriginResourcePolicy.writer);
|
||||
writers.addAll(this.headerWriters);
|
||||
return writers;
|
||||
}
|
||||
@@ -556,129 +544,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
return this.permissionsPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||
* Cross-Origin-Opener-Policy</a> header.
|
||||
* <p>
|
||||
* Configuration is provided to the {@link CrossOriginOpenerPolicyHeaderWriter} which
|
||||
* responsible for writing the header.
|
||||
* </p>
|
||||
* @return the {@link CrossOriginOpenerPolicyConfig} for additional confniguration
|
||||
* @since 5.7
|
||||
* @see CrossOriginOpenerPolicyHeaderWriter
|
||||
*/
|
||||
public CrossOriginOpenerPolicyConfig crossOriginOpenerPolicy() {
|
||||
this.crossOriginOpenerPolicy.writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||
return this.crossOriginOpenerPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||
* Cross-Origin-Opener-Policy</a> header.
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the
|
||||
* {@code Cross-Origin-Opener-Policy} header in the response using the supplied
|
||||
* policy.
|
||||
* <p>
|
||||
* <p>
|
||||
* Configuration is provided to the {@link CrossOriginOpenerPolicyHeaderWriter} which
|
||||
* responsible for writing the header.
|
||||
* </p>
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
* @since 5.7
|
||||
* @see CrossOriginOpenerPolicyHeaderWriter
|
||||
*/
|
||||
public HeadersConfigurer<H> crossOriginOpenerPolicy(
|
||||
Customizer<CrossOriginOpenerPolicyConfig> crossOriginOpenerPolicyCustomizer) {
|
||||
this.crossOriginOpenerPolicy.writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||
crossOriginOpenerPolicyCustomizer.customize(this.crossOriginOpenerPolicy);
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||
* Cross-Origin-Embedder-Policy</a> header.
|
||||
* <p>
|
||||
* Configuration is provided to the {@link CrossOriginEmbedderPolicyHeaderWriter}
|
||||
* which is responsible for writing the header.
|
||||
* </p>
|
||||
* @return the {@link CrossOriginEmbedderPolicyConfig} for additional customizations
|
||||
* @since 5.7
|
||||
* @see CrossOriginEmbedderPolicyHeaderWriter
|
||||
*/
|
||||
public CrossOriginEmbedderPolicyConfig crossOriginEmbedderPolicy() {
|
||||
this.crossOriginEmbedderPolicy.writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||
return this.crossOriginEmbedderPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||
* Cross-Origin-Embedder-Policy</a> header.
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the
|
||||
* {@code Cross-Origin-Embedder-Policy} header in the response using the supplied
|
||||
* policy.
|
||||
* <p>
|
||||
* <p>
|
||||
* Configuration is provided to the {@link CrossOriginEmbedderPolicyHeaderWriter}
|
||||
* which is responsible for writing the header.
|
||||
* </p>
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
* @since 5.7
|
||||
* @see CrossOriginEmbedderPolicyHeaderWriter
|
||||
*/
|
||||
public HeadersConfigurer<H> crossOriginEmbedderPolicy(
|
||||
Customizer<CrossOriginEmbedderPolicyConfig> crossOriginEmbedderPolicyCustomizer) {
|
||||
this.crossOriginEmbedderPolicy.writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||
crossOriginEmbedderPolicyCustomizer.customize(this.crossOriginEmbedderPolicy);
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||
* Cross-Origin-Resource-Policy</a> header.
|
||||
* <p>
|
||||
* Configuration is provided to the {@link CrossOriginResourcePolicyHeaderWriter}
|
||||
* which is responsible for writing the header:
|
||||
* </p>
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
* @since 5.7
|
||||
* @see CrossOriginResourcePolicyHeaderWriter
|
||||
*/
|
||||
public CrossOriginResourcePolicyConfig crossOriginResourcePolicy() {
|
||||
this.crossOriginResourcePolicy.writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||
return this.crossOriginResourcePolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||
* Cross-Origin-Resource-Policy</a> header.
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the
|
||||
* {@code Cross-Origin-Resource-Policy} header in the response using the supplied
|
||||
* policy.
|
||||
* <p>
|
||||
* <p>
|
||||
* Configuration is provided to the {@link CrossOriginResourcePolicyHeaderWriter}
|
||||
* which is responsible for writing the header:
|
||||
* </p>
|
||||
* @return the {@link HeadersConfigurer} for additional customizations
|
||||
* @since 5.7
|
||||
* @see CrossOriginResourcePolicyHeaderWriter
|
||||
*/
|
||||
public HeadersConfigurer<H> crossOriginResourcePolicy(
|
||||
Customizer<CrossOriginResourcePolicyConfig> crossOriginResourcePolicyCustomizer) {
|
||||
this.crossOriginResourcePolicy.writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||
crossOriginResourcePolicyCustomizer.customize(this.crossOriginResourcePolicy);
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
public final class ContentTypeOptionsConfig {
|
||||
|
||||
private XContentTypeOptionsHeaderWriter writer;
|
||||
@@ -1277,96 +1142,4 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
}
|
||||
|
||||
public final class CrossOriginOpenerPolicyConfig {
|
||||
|
||||
private CrossOriginOpenerPolicyHeaderWriter writer;
|
||||
|
||||
public CrossOriginOpenerPolicyConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the policy to be used in the {@code Cross-Origin-Opener-Policy} header
|
||||
* @param openerPolicy a {@code Cross-Origin-Opener-Policy}
|
||||
* @return the {@link CrossOriginOpenerPolicyConfig} for additional configuration
|
||||
* @throws IllegalArgumentException if openerPolicy is null
|
||||
*/
|
||||
public CrossOriginOpenerPolicyConfig policy(
|
||||
CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy openerPolicy) {
|
||||
this.writer.setPolicy(openerPolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows completing configuration of Cross Origin Opener Policy and continuing
|
||||
* configuration of headers.
|
||||
* @return the {@link HeadersConfigurer} for additional configuration
|
||||
*/
|
||||
public HeadersConfigurer<H> and() {
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class CrossOriginEmbedderPolicyConfig {
|
||||
|
||||
private CrossOriginEmbedderPolicyHeaderWriter writer;
|
||||
|
||||
public CrossOriginEmbedderPolicyConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the policy to be used in the {@code Cross-Origin-Embedder-Policy} header
|
||||
* @param embedderPolicy a {@code Cross-Origin-Embedder-Policy}
|
||||
* @return the {@link CrossOriginEmbedderPolicyConfig} for additional
|
||||
* configuration
|
||||
* @throws IllegalArgumentException if embedderPolicy is null
|
||||
*/
|
||||
public CrossOriginEmbedderPolicyConfig policy(
|
||||
CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy embedderPolicy) {
|
||||
this.writer.setPolicy(embedderPolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows completing configuration of Cross-Origin-Embedder-Policy and continuing
|
||||
* configuration of headers.
|
||||
* @return the {@link HeadersConfigurer} for additional configuration
|
||||
*/
|
||||
public HeadersConfigurer<H> and() {
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class CrossOriginResourcePolicyConfig {
|
||||
|
||||
private CrossOriginResourcePolicyHeaderWriter writer;
|
||||
|
||||
public CrossOriginResourcePolicyConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the policy to be used in the {@code Cross-Origin-Resource-Policy} header
|
||||
* @param resourcePolicy a {@code Cross-Origin-Resource-Policy}
|
||||
* @return the {@link CrossOriginResourcePolicyConfig} for additional
|
||||
* configuration
|
||||
* @throws IllegalArgumentException if resourcePolicy is null
|
||||
*/
|
||||
public CrossOriginResourcePolicyConfig policy(
|
||||
CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy resourcePolicy) {
|
||||
this.writer.setPolicy(resourcePolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows completing configuration of Cross-Origin-Resource-Policy and continuing
|
||||
* configuration of headers.
|
||||
* @return the {@link HeadersConfigurer} for additional configuration
|
||||
*/
|
||||
public HeadersConfigurer<H> and() {
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,22 +48,11 @@ final class PermitAllSupport {
|
||||
RequestMatcher... requestMatchers) {
|
||||
ExpressionUrlAuthorizationConfigurer<?> configurer = http
|
||||
.getConfigurer(ExpressionUrlAuthorizationConfigurer.class);
|
||||
AuthorizeHttpRequestsConfigurer<?> httpConfigurer = http.getConfigurer(AuthorizeHttpRequestsConfigurer.class);
|
||||
|
||||
boolean oneConfigurerPresent = configurer == null ^ httpConfigurer == null;
|
||||
Assert.state(oneConfigurerPresent,
|
||||
"permitAll only works with either HttpSecurity.authorizeRequests() or HttpSecurity.authorizeHttpRequests(). "
|
||||
+ "Please define one or the other but not both.");
|
||||
|
||||
Assert.state(configurer != null, "permitAll only works with HttpSecurity.authorizeRequests()");
|
||||
for (RequestMatcher matcher : requestMatchers) {
|
||||
if (matcher != null) {
|
||||
if (configurer != null) {
|
||||
configurer.getRegistry().addMapping(0, new UrlMapping(matcher,
|
||||
SecurityConfig.createList(ExpressionUrlAuthorizationConfigurer.permitAll)));
|
||||
}
|
||||
else {
|
||||
httpConfigurer.addFirst(matcher, AuthorizeHttpRequestsConfigurer.permitAllAuthorizationManager);
|
||||
}
|
||||
configurer.getRegistry().addMapping(0, new UrlMapping(matcher,
|
||||
SecurityConfig.createList(ExpressionUrlAuthorizationConfigurer.permitAll)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,6 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
@@ -153,10 +151,8 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
* when a remember me token is valid. The default is to use the
|
||||
* {@link UserDetailsService} found by invoking
|
||||
* {@link HttpSecurity#getSharedObject(Class)} which is set when using
|
||||
* {@link WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder)}. When
|
||||
* using a {@link org.springframework.security.web.SecurityFilterChain} bean, the
|
||||
* default is to look for a {@link UserDetailsService} bean. Alternatively, one can
|
||||
* populate {@link #rememberMeServices(RememberMeServices)}.
|
||||
* {@link WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder)}.
|
||||
* Alternatively, one can populate {@link #rememberMeServices(RememberMeServices)}.
|
||||
* @param userDetailsService the {@link UserDetailsService} to configure
|
||||
* @return the {@link RememberMeConfigurer} for further customization
|
||||
* @see AbstractRememberMeServices
|
||||
@@ -399,16 +395,15 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link UserDetailsService} to use. Either the explicitly configured
|
||||
* {@link UserDetailsService} from {@link #userDetailsService(UserDetailsService)}, a
|
||||
* shared object from {@link HttpSecurity#getSharedObject(Class)} or the
|
||||
* {@link UserDetailsService} bean.
|
||||
* Gets the {@link UserDetailsService} to use. Either the explicitly configure
|
||||
* {@link UserDetailsService} from {@link #userDetailsService(UserDetailsService)} or
|
||||
* a shared object from {@link HttpSecurity#getSharedObject(Class)}.
|
||||
* @param http {@link HttpSecurity} to get the shared {@link UserDetailsService}
|
||||
* @return the {@link UserDetailsService} to use
|
||||
*/
|
||||
private UserDetailsService getUserDetailsService(H http) {
|
||||
if (this.userDetailsService == null) {
|
||||
this.userDetailsService = getSharedOrBean(http, UserDetailsService.class);
|
||||
this.userDetailsService = http.getSharedObject(UserDetailsService.class);
|
||||
}
|
||||
Assert.state(this.userDetailsService != null,
|
||||
() -> "userDetailsService cannot be null. Invoke " + RememberMeConfigurer.class.getSimpleName()
|
||||
@@ -436,25 +431,4 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
return this.key;
|
||||
}
|
||||
|
||||
private <C> C getSharedOrBean(H http, Class<C> type) {
|
||||
C shared = http.getSharedObject(type);
|
||||
if (shared != null) {
|
||||
return shared;
|
||||
}
|
||||
return getBeanOrNull(type);
|
||||
}
|
||||
|
||||
private <T> T getBeanOrNull(Class<T> type) {
|
||||
ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return context.getBean(type);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-39
@@ -22,10 +22,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.session.ForceEagerSessionCreationFilter;
|
||||
|
||||
/**
|
||||
* Allows persisting and restoring of the {@link SecurityContext} found on the
|
||||
@@ -64,8 +62,6 @@ import org.springframework.security.web.session.ForceEagerSessionCreationFilter;
|
||||
public final class SecurityContextConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
extends AbstractHttpConfigurer<SecurityContextConfigurer<H>, H> {
|
||||
|
||||
private boolean requireExplicitSave;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @see HttpSecurity#securityContext()
|
||||
@@ -83,46 +79,23 @@ public final class SecurityContextConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
return this;
|
||||
}
|
||||
|
||||
public SecurityContextConfigurer<H> requireExplicitSave(boolean requireExplicitSave) {
|
||||
this.requireExplicitSave = requireExplicitSave;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean isRequireExplicitSave() {
|
||||
return this.requireExplicitSave;
|
||||
}
|
||||
|
||||
SecurityContextRepository getSecurityContextRepository() {
|
||||
SecurityContextRepository securityContextRepository = getBuilder()
|
||||
.getSharedObject(SecurityContextRepository.class);
|
||||
if (securityContextRepository == null) {
|
||||
securityContextRepository = new HttpSessionSecurityContextRepository();
|
||||
}
|
||||
return securityContextRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configure(H http) {
|
||||
SecurityContextRepository securityContextRepository = getSecurityContextRepository();
|
||||
if (this.requireExplicitSave) {
|
||||
SecurityContextHolderFilter securityContextHolderFilter = postProcess(
|
||||
new SecurityContextHolderFilter(securityContextRepository));
|
||||
http.addFilter(securityContextHolderFilter);
|
||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
||||
if (securityContextRepository == null) {
|
||||
securityContextRepository = new HttpSessionSecurityContextRepository();
|
||||
}
|
||||
else {
|
||||
SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter(
|
||||
securityContextRepository);
|
||||
SessionManagementConfigurer<?> sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
|
||||
SessionCreationPolicy sessionCreationPolicy = (sessionManagement != null)
|
||||
? sessionManagement.getSessionCreationPolicy() : null;
|
||||
if (SessionCreationPolicy.ALWAYS == sessionCreationPolicy) {
|
||||
securityContextFilter.setForceEagerSessionCreation(true);
|
||||
http.addFilter(postProcess(new ForceEagerSessionCreationFilter()));
|
||||
}
|
||||
securityContextFilter = postProcess(securityContextFilter);
|
||||
http.addFilter(securityContextFilter);
|
||||
SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter(
|
||||
securityContextRepository);
|
||||
SessionManagementConfigurer<?> sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
|
||||
SessionCreationPolicy sessionCreationPolicy = (sessionManagement != null)
|
||||
? sessionManagement.getSessionCreationPolicy() : null;
|
||||
if (SessionCreationPolicy.ALWAYS == sessionCreationPolicy) {
|
||||
securityContextFilter.setForceEagerSessionCreation(true);
|
||||
}
|
||||
securityContextFilter = postProcess(securityContextFilter);
|
||||
http.addFilter(securityContextFilter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-14
@@ -52,8 +52,6 @@ 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.DisableEncodeUrlFilter;
|
||||
import org.springframework.security.web.session.ForceEagerSessionCreationFilter;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
@@ -203,12 +201,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
* {@link HttpServletResponse#encodeRedirectURL(String)} or
|
||||
* {@link HttpServletResponse#encodeURL(String)}, otherwise disallows HTTP sessions to
|
||||
* be included in the URL. This prevents leaking information to external domains.
|
||||
* <p>
|
||||
* This is achieved by guarding {@link HttpServletResponse#encodeURL} and
|
||||
* {@link HttpServletResponse#encodeRedirectURL} invocations. Any code that also
|
||||
* overrides either of these two methods, like
|
||||
* {@link org.springframework.web.servlet.resource.ResourceUrlEncodingFilter}, needs
|
||||
* to come after the security filter chain or risk being skipped.
|
||||
* @param enableSessionUrlRewriting true if should allow the JSESSIONID to be
|
||||
* rewritten into the URLs, else false (default)
|
||||
* @return the {@link SessionManagementConfigurer} for further customization
|
||||
@@ -378,12 +370,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
concurrentSessionFilter = postProcess(concurrentSessionFilter);
|
||||
http.addFilter(concurrentSessionFilter);
|
||||
}
|
||||
if (!this.enableSessionUrlRewriting) {
|
||||
http.addFilter(new DisableEncodeUrlFilter());
|
||||
}
|
||||
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
|
||||
http.addFilter(new ForceEagerSessionCreationFilter());
|
||||
}
|
||||
}
|
||||
|
||||
private ConcurrentSessionFilter createConcurrencyFilter(H http) {
|
||||
|
||||
+3
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -18,19 +18,15 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
@@ -145,9 +141,7 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
|
||||
/**
|
||||
* Specifies the {@link AuthenticationUserDetailsService} to use. If not specified,
|
||||
* the shared {@link UserDetailsService} will be used to create a
|
||||
* {@link UserDetailsByNameServiceWrapper}. If a {@link SecurityFilterChain} bean is
|
||||
* used instead of the {@link WebSecurityConfigurerAdapter}, then the
|
||||
* {@link UserDetailsService} bean will be used by default.
|
||||
* {@link UserDetailsByNameServiceWrapper}.
|
||||
* @param authenticationUserDetailsService the
|
||||
* {@link AuthenticationUserDetailsService} to use
|
||||
* @return the {@link X509Configurer} for further customizations
|
||||
@@ -206,30 +200,9 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
|
||||
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> getAuthenticationUserDetailsService(
|
||||
H http) {
|
||||
if (this.authenticationUserDetailsService == null) {
|
||||
userDetailsService(getSharedOrBean(http, UserDetailsService.class));
|
||||
userDetailsService(http.getSharedObject(UserDetailsService.class));
|
||||
}
|
||||
return this.authenticationUserDetailsService;
|
||||
}
|
||||
|
||||
private <C> C getSharedOrBean(H http, Class<C> type) {
|
||||
C shared = http.getSharedObject(type);
|
||||
if (shared != null) {
|
||||
return shared;
|
||||
}
|
||||
return getBeanOrNull(type);
|
||||
}
|
||||
|
||||
private <T> T getBeanOrNull(Class<T> type) {
|
||||
ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return context.getBean(type);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-15
@@ -18,9 +18,6 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.se
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -28,7 +25,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||
@@ -55,9 +51,6 @@ import org.springframework.security.oauth2.server.resource.web.DefaultBearerToke
|
||||
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
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.CsrfException;
|
||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
||||
@@ -160,19 +153,12 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
||||
|
||||
private OpaqueTokenConfigurer opaqueTokenConfigurer;
|
||||
|
||||
private AccessDeniedHandler accessDeniedHandler = new DelegatingAccessDeniedHandler(
|
||||
new LinkedHashMap<>(createAccessDeniedHandlers()), new BearerTokenAccessDeniedHandler());
|
||||
private AccessDeniedHandler accessDeniedHandler = new BearerTokenAccessDeniedHandler();
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint();
|
||||
|
||||
private BearerTokenRequestMatcher requestMatcher = new BearerTokenRequestMatcher();
|
||||
|
||||
private static Map<Class<? extends AccessDeniedException>, AccessDeniedHandler> createAccessDeniedHandlers() {
|
||||
Map<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers = new HashMap<>();
|
||||
handlers.put(CsrfException.class, new AccessDeniedHandlerImpl());
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public OAuth2ResourceServerConfigurer(ApplicationContext context) {
|
||||
Assert.notNull(context, "context cannot be null");
|
||||
this.context = context;
|
||||
|
||||
+54
-74
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -19,6 +19,8 @@ package org.springframework.security.config.annotation.web.configurers.saml2;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.opensaml.core.Version;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
@@ -48,7 +50,6 @@ import org.springframework.security.saml2.provider.service.web.RelyingPartyRegis
|
||||
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestContextResolver;
|
||||
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository;
|
||||
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
@@ -114,12 +115,10 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
|
||||
private String loginPage;
|
||||
|
||||
private String authenticationRequestUri = "/saml2/authenticate/{registrationId}";
|
||||
|
||||
private Saml2AuthenticationRequestResolver authenticationRequestResolver;
|
||||
|
||||
private String loginProcessingUrl = Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI;
|
||||
|
||||
private AuthenticationRequestEndpointConfig authenticationRequestEndpoint = new AuthenticationRequestEndpointConfig();
|
||||
|
||||
private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository;
|
||||
|
||||
private AuthenticationConverter authenticationConverter;
|
||||
@@ -177,20 +176,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this {@link Saml2AuthenticationRequestResolver} for generating SAML 2.0
|
||||
* Authentication Requests.
|
||||
* @param authenticationRequestResolver
|
||||
* @return the {@link Saml2LoginConfigurer} for further configuration
|
||||
* @since 5.7
|
||||
*/
|
||||
public Saml2LoginConfigurer<B> authenticationRequestResolver(
|
||||
Saml2AuthenticationRequestResolver authenticationRequestResolver) {
|
||||
Assert.notNull(authenticationRequestResolver, "authenticationRequestResolver cannot be null");
|
||||
this.authenticationRequestResolver = authenticationRequestResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the URL to validate the credentials. If specified a custom URL, consider
|
||||
* specifying a custom {@link AuthenticationConverter} via
|
||||
@@ -215,7 +200,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
*
|
||||
* Initializes this filter chain for SAML 2 Login. The following actions are taken:
|
||||
* <ul>
|
||||
* <li>The WebSSO endpoint has CSRF disabled, typically {@code /login/saml2/sso}</li>
|
||||
@@ -241,8 +226,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
super.init(http);
|
||||
}
|
||||
else {
|
||||
Map<String, String> providerUrlMap = getIdentityProviderUrlMap(this.authenticationRequestUri,
|
||||
this.relyingPartyRegistrationRepository);
|
||||
Map<String, String> providerUrlMap = getIdentityProviderUrlMap(
|
||||
this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository);
|
||||
boolean singleProvider = providerUrlMap.size() == 1;
|
||||
if (singleProvider) {
|
||||
// Setup auto-redirect to provider login page
|
||||
@@ -262,16 +247,14 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
*
|
||||
* During the {@code configure} phase, a
|
||||
* {@link Saml2WebSsoAuthenticationRequestFilter} is added to handle SAML 2.0
|
||||
* AuthNRequest redirects
|
||||
*/
|
||||
@Override
|
||||
public void configure(B http) throws Exception {
|
||||
Saml2WebSsoAuthenticationRequestFilter filter = getAuthenticationRequestFilter(http);
|
||||
filter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
|
||||
http.addFilter(postProcess(filter));
|
||||
http.addFilter(this.authenticationRequestEndpoint.build(http));
|
||||
super.configure(http);
|
||||
if (this.authenticationManager == null) {
|
||||
registerDefaultAuthenticationProvider(http);
|
||||
@@ -281,11 +264,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
}
|
||||
}
|
||||
|
||||
private RelyingPartyRegistrationResolver relyingPartyRegistrationResolver(B http) {
|
||||
RelyingPartyRegistrationRepository registrations = relyingPartyRegistrationRepository(http);
|
||||
return new DefaultRelyingPartyRegistrationResolver(registrations);
|
||||
}
|
||||
|
||||
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository(B http) {
|
||||
if (this.relyingPartyRegistrationRepository == null) {
|
||||
this.relyingPartyRegistrationRepository = getSharedOrBean(http, RelyingPartyRegistrationRepository.class);
|
||||
@@ -298,46 +276,6 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
saml2WebSsoAuthenticationFilter.setAuthenticationRequestRepository(getAuthenticationRequestRepository(http));
|
||||
}
|
||||
|
||||
private Saml2WebSsoAuthenticationRequestFilter getAuthenticationRequestFilter(B http) {
|
||||
Saml2AuthenticationRequestResolver authenticationRequestResolver = getAuthenticationRequestResolver(http);
|
||||
if (authenticationRequestResolver != null) {
|
||||
return new Saml2WebSsoAuthenticationRequestFilter(authenticationRequestResolver);
|
||||
}
|
||||
return new Saml2WebSsoAuthenticationRequestFilter(getAuthenticationRequestContextResolver(http),
|
||||
getAuthenticationRequestFactory(http));
|
||||
}
|
||||
|
||||
private Saml2AuthenticationRequestResolver getAuthenticationRequestResolver(B http) {
|
||||
if (this.authenticationRequestResolver != null) {
|
||||
return this.authenticationRequestResolver;
|
||||
}
|
||||
return getBeanOrNull(http, Saml2AuthenticationRequestResolver.class);
|
||||
}
|
||||
|
||||
private Saml2AuthenticationRequestFactory getAuthenticationRequestFactory(B http) {
|
||||
Saml2AuthenticationRequestFactory resolver = getSharedOrBean(http, Saml2AuthenticationRequestFactory.class);
|
||||
if (resolver != null) {
|
||||
return resolver;
|
||||
}
|
||||
if (version().startsWith("4")) {
|
||||
return new OpenSaml4AuthenticationRequestFactory();
|
||||
}
|
||||
else {
|
||||
return new OpenSamlAuthenticationRequestFactory();
|
||||
}
|
||||
}
|
||||
|
||||
private Saml2AuthenticationRequestContextResolver getAuthenticationRequestContextResolver(B http) {
|
||||
Saml2AuthenticationRequestContextResolver resolver = getBeanOrNull(http,
|
||||
Saml2AuthenticationRequestContextResolver.class);
|
||||
if (resolver != null) {
|
||||
return resolver;
|
||||
}
|
||||
RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(
|
||||
this.relyingPartyRegistrationRepository);
|
||||
return new DefaultSaml2AuthenticationRequestContextResolver(registrationResolver);
|
||||
}
|
||||
|
||||
private AuthenticationConverter getAuthenticationConverter(B http) {
|
||||
if (this.authenticationConverter != null) {
|
||||
return this.authenticationConverter;
|
||||
@@ -386,8 +324,8 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
return;
|
||||
}
|
||||
loginPageGeneratingFilter.setSaml2LoginEnabled(true);
|
||||
loginPageGeneratingFilter.setSaml2AuthenticationUrlToProviderName(
|
||||
this.getIdentityProviderUrlMap(this.authenticationRequestUri, this.relyingPartyRegistrationRepository));
|
||||
loginPageGeneratingFilter.setSaml2AuthenticationUrlToProviderName(this.getIdentityProviderUrlMap(
|
||||
this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository));
|
||||
loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage());
|
||||
loginPageGeneratingFilter.setFailureUrl(this.getFailureUrl());
|
||||
}
|
||||
@@ -441,4 +379,46 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||
}
|
||||
}
|
||||
|
||||
private final class AuthenticationRequestEndpointConfig {
|
||||
|
||||
private String filterProcessingUrl = "/saml2/authenticate/{registrationId}";
|
||||
|
||||
private AuthenticationRequestEndpointConfig() {
|
||||
}
|
||||
|
||||
private Filter build(B http) {
|
||||
Saml2AuthenticationRequestFactory authenticationRequestResolver = getResolver(http);
|
||||
Saml2AuthenticationRequestContextResolver contextResolver = getContextResolver(http);
|
||||
Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> repository = getAuthenticationRequestRepository(
|
||||
http);
|
||||
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(contextResolver,
|
||||
authenticationRequestResolver);
|
||||
filter.setAuthenticationRequestRepository(repository);
|
||||
return postProcess(filter);
|
||||
}
|
||||
|
||||
private Saml2AuthenticationRequestFactory getResolver(B http) {
|
||||
Saml2AuthenticationRequestFactory resolver = getSharedOrBean(http, Saml2AuthenticationRequestFactory.class);
|
||||
if (resolver == null) {
|
||||
if (version().startsWith("4")) {
|
||||
return new OpenSaml4AuthenticationRequestFactory();
|
||||
}
|
||||
return new OpenSamlAuthenticationRequestFactory();
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
|
||||
private Saml2AuthenticationRequestContextResolver getContextResolver(B http) {
|
||||
Saml2AuthenticationRequestContextResolver resolver = getBeanOrNull(http,
|
||||
Saml2AuthenticationRequestContextResolver.class);
|
||||
if (resolver == null) {
|
||||
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(
|
||||
Saml2LoginConfigurer.this.relyingPartyRegistrationRepository);
|
||||
return new DefaultSaml2AuthenticationRequestContextResolver(relyingPartyRegistrationResolver);
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
|
||||
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider;
|
||||
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder;
|
||||
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
|
||||
@@ -42,7 +41,6 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve
|
||||
* This {@code Configuration} is imported by {@link EnableWebFluxSecurity}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Alavudin Kuttikkattil
|
||||
* @since 5.1
|
||||
*/
|
||||
final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
|
||||
@@ -66,12 +64,14 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
|
||||
|
||||
private ReactiveOAuth2AuthorizedClientService authorizedClientService;
|
||||
|
||||
private ReactiveOAuth2AuthorizedClientManager authorizedClientManager;
|
||||
|
||||
@Override
|
||||
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||
ReactiveOAuth2AuthorizedClientManager authorizedClientManager = getAuthorizedClientManager();
|
||||
if (authorizedClientManager != null) {
|
||||
if (this.authorizedClientRepository != null && this.clientRegistrationRepository != null) {
|
||||
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
|
||||
.builder().authorizationCode().refreshToken().clientCredentials().password().build();
|
||||
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
|
||||
this.clientRegistrationRepository, getAuthorizedClientRepository());
|
||||
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
|
||||
configurer.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager));
|
||||
}
|
||||
}
|
||||
@@ -93,13 +93,6 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setAuthorizedClientManager(List<ReactiveOAuth2AuthorizedClientManager> authorizedClientManager) {
|
||||
if (authorizedClientManager.size() == 1) {
|
||||
this.authorizedClientManager = authorizedClientManager.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() {
|
||||
if (this.authorizedClientRepository != null) {
|
||||
return this.authorizedClientRepository;
|
||||
@@ -110,23 +103,6 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
|
||||
return null;
|
||||
}
|
||||
|
||||
private ReactiveOAuth2AuthorizedClientManager getAuthorizedClientManager() {
|
||||
if (this.authorizedClientManager != null) {
|
||||
return this.authorizedClientManager;
|
||||
}
|
||||
ReactiveOAuth2AuthorizedClientManager authorizedClientManager = null;
|
||||
if (this.authorizedClientRepository != null && this.clientRegistrationRepository != null) {
|
||||
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
|
||||
.builder().authorizationCode().refreshToken().clientCredentials().password().build();
|
||||
DefaultReactiveOAuth2AuthorizedClientManager defaultReactiveOAuth2AuthorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
|
||||
this.clientRegistrationRepository, getAuthorizedClientRepository());
|
||||
defaultReactiveOAuth2AuthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
|
||||
authorizedClientManager = defaultReactiveOAuth2AuthorizedClientManager;
|
||||
}
|
||||
|
||||
return authorizedClientManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-3
@@ -102,9 +102,7 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
||||
pc.getRegistry().registerAlias(id, alias);
|
||||
pc.getReaderContext().fireAliasRegistered(id, alias, pc.extractSource(element));
|
||||
}
|
||||
if (!BeanIds.AUTHENTICATION_MANAGER.equals(id)
|
||||
&& !pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)
|
||||
&& !pc.getRegistry().isAlias(BeanIds.AUTHENTICATION_MANAGER)) {
|
||||
if (!BeanIds.AUTHENTICATION_MANAGER.equals(id)) {
|
||||
pc.getRegistry().registerAlias(id, BeanIds.AUTHENTICATION_MANAGER);
|
||||
pc.getReaderContext().fireAliasRegistered(id, BeanIds.AUTHENTICATION_MANAGER, pc.extractSource(element));
|
||||
}
|
||||
|
||||
+15
-122
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -164,8 +164,6 @@ final class AuthenticationConfigBuilder {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ManagedList logoutHandlers;
|
||||
|
||||
private BeanMetadataElement logoutSuccessHandler;
|
||||
|
||||
private BeanDefinition loginPageGenerationFilter;
|
||||
|
||||
private BeanDefinition logoutPageGenerationFilter;
|
||||
@@ -204,20 +202,6 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
private BeanDefinition oauth2LoginLinks;
|
||||
|
||||
private BeanDefinition saml2AuthenticationUrlToProviderName;
|
||||
|
||||
private BeanDefinition saml2AuthorizationRequestFilter;
|
||||
|
||||
private String saml2AuthenticationFilterId;
|
||||
|
||||
private String saml2AuthenticationRequestFilterId;
|
||||
|
||||
private String saml2LogoutFilterId;
|
||||
|
||||
private String saml2LogoutRequestFilterId;
|
||||
|
||||
private String saml2LogoutResponseFilterId;
|
||||
|
||||
private boolean oauth2ClientEnabled;
|
||||
|
||||
private BeanDefinition authorizationRequestRedirectFilter;
|
||||
@@ -236,8 +220,8 @@ final class AuthenticationConfigBuilder {
|
||||
|
||||
AuthenticationConfigBuilder(Element element, boolean forceAutoConfig, ParserContext pc,
|
||||
SessionCreationPolicy sessionPolicy, BeanReference requestCache, BeanReference authenticationManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef, BeanReference sessionStrategy,
|
||||
BeanReference portMapper, BeanReference portResolver, BeanMetadataElement csrfLogoutHandler) {
|
||||
BeanReference sessionStrategy, BeanReference portMapper, BeanReference portResolver,
|
||||
BeanMetadataElement csrfLogoutHandler) {
|
||||
this.httpElt = element;
|
||||
this.pc = pc;
|
||||
this.requestCache = requestCache;
|
||||
@@ -251,16 +235,12 @@ final class AuthenticationConfigBuilder {
|
||||
createRememberMeFilter(authenticationManager);
|
||||
createBasicFilter(authenticationManager);
|
||||
createBearerTokenAuthenticationFilter(authenticationManager);
|
||||
createFormLoginFilter(sessionStrategy, authenticationManager, authenticationFilterSecurityContextRepositoryRef);
|
||||
createOAuth2ClientFilters(sessionStrategy, requestCache, authenticationManager,
|
||||
authenticationFilterSecurityContextRepositoryRef);
|
||||
createOpenIDLoginFilter(sessionStrategy, authenticationManager,
|
||||
authenticationFilterSecurityContextRepositoryRef);
|
||||
createSaml2LoginFilter(authenticationManager, authenticationFilterSecurityContextRepositoryRef);
|
||||
createFormLoginFilter(sessionStrategy, authenticationManager);
|
||||
createOAuth2ClientFilters(sessionStrategy, requestCache, authenticationManager);
|
||||
createOpenIDLoginFilter(sessionStrategy, authenticationManager);
|
||||
createX509Filter(authenticationManager);
|
||||
createJeeFilter(authenticationManager);
|
||||
createLogoutFilter();
|
||||
createSaml2LogoutFilter();
|
||||
createLoginPageFilterIfNeeded();
|
||||
createUserDetailsServiceFactory();
|
||||
createExceptionTranslationFilter();
|
||||
@@ -292,8 +272,7 @@ final class AuthenticationConfigBuilder {
|
||||
this.rememberMeProviderRef = new RuntimeBeanReference(id);
|
||||
}
|
||||
|
||||
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
|
||||
RootBeanDefinition formFilter = null;
|
||||
if (formLoginElt != null || this.autoConfig) {
|
||||
@@ -309,10 +288,6 @@ final class AuthenticationConfigBuilder {
|
||||
if (formFilter != null) {
|
||||
formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
if (authenticationFilterSecurityContextRepositoryRef != null) {
|
||||
formFilter.getPropertyValues().addPropertyValue("securityContextRepository",
|
||||
authenticationFilterSecurityContextRepositoryRef);
|
||||
}
|
||||
// Id is required by login page filter
|
||||
this.formFilterId = this.pc.getReaderContext().generateBeanName(formFilter);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(formFilter, this.formFilterId));
|
||||
@@ -321,15 +296,13 @@ final class AuthenticationConfigBuilder {
|
||||
}
|
||||
|
||||
void createOAuth2ClientFilters(BeanReference sessionStrategy, BeanReference requestCache,
|
||||
BeanReference authenticationManager, BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
createOAuth2LoginFilter(sessionStrategy, authenticationManager,
|
||||
authenticationFilterSecurityContextRepositoryRef);
|
||||
createOAuth2ClientFilter(requestCache, authenticationManager, authenticationFilterSecurityContextRepositoryRef);
|
||||
BeanReference authenticationManager) {
|
||||
createOAuth2LoginFilter(sessionStrategy, authenticationManager);
|
||||
createOAuth2ClientFilter(requestCache, authenticationManager);
|
||||
registerOAuth2ClientPostProcessors();
|
||||
}
|
||||
|
||||
void createOAuth2LoginFilter(BeanReference sessionStrategy, BeanReference authManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
void createOAuth2LoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
Element oauth2LoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_LOGIN);
|
||||
if (oauth2LoginElt == null) {
|
||||
return;
|
||||
@@ -341,10 +314,6 @@ final class AuthenticationConfigBuilder {
|
||||
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
|
||||
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
|
||||
oauth2LoginFilterBean.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
if (authenticationFilterSecurityContextRepositoryRef != null) {
|
||||
oauth2LoginFilterBean.getPropertyValues().addPropertyValue("securityContextRepository",
|
||||
authenticationFilterSecurityContextRepositoryRef);
|
||||
}
|
||||
|
||||
// retrieve the other bean result
|
||||
BeanDefinition oauth2LoginAuthProvider = parser.getOAuth2LoginAuthenticationProvider();
|
||||
@@ -374,15 +343,14 @@ final class AuthenticationConfigBuilder {
|
||||
this.oauth2LoginOidcAuthenticationProviderRef = new RuntimeBeanReference(oauth2LoginOidcAuthProviderId);
|
||||
}
|
||||
|
||||
void createOAuth2ClientFilter(BeanReference requestCache, BeanReference authenticationManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
void createOAuth2ClientFilter(BeanReference requestCache, BeanReference authenticationManager) {
|
||||
Element oauth2ClientElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OAUTH2_CLIENT);
|
||||
if (oauth2ClientElt == null) {
|
||||
return;
|
||||
}
|
||||
this.oauth2ClientEnabled = true;
|
||||
OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser(requestCache,
|
||||
authenticationManager, authenticationFilterSecurityContextRepositoryRef);
|
||||
authenticationManager);
|
||||
parser.parse(oauth2ClientElt, this.pc);
|
||||
BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository();
|
||||
registerDefaultAuthorizedClientRepositoryIfNecessary(defaultAuthorizedClientRepository);
|
||||
@@ -427,8 +395,7 @@ final class AuthenticationConfigBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
RootBeanDefinition openIDFilter = null;
|
||||
if (openIDLoginElt != null) {
|
||||
@@ -437,10 +404,6 @@ final class AuthenticationConfigBuilder {
|
||||
if (openIDFilter != null) {
|
||||
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
if (authenticationFilterSecurityContextRepositoryRef != null) {
|
||||
openIDFilter.getPropertyValues().addPropertyValue("securityContextRepository",
|
||||
authenticationFilterSecurityContextRepositoryRef);
|
||||
}
|
||||
// Required by login page filter
|
||||
this.openIDFilterId = this.pc.getReaderContext().generateBeanName(openIDFilter);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, this.openIDFilterId));
|
||||
@@ -449,31 +412,6 @@ final class AuthenticationConfigBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private void createSaml2LoginFilter(BeanReference authenticationManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
Element saml2LoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SAML2_LOGIN);
|
||||
if (saml2LoginElt == null) {
|
||||
return;
|
||||
}
|
||||
Saml2LoginBeanDefinitionParser parser = new Saml2LoginBeanDefinitionParser(this.csrfIgnoreRequestMatchers,
|
||||
this.portMapper, this.portResolver, this.requestCache, this.allowSessionCreation, authenticationManager,
|
||||
authenticationFilterSecurityContextRepositoryRef, this.authenticationProviders,
|
||||
this.defaultEntryPointMappings);
|
||||
BeanDefinition saml2WebSsoAuthenticationFilter = parser.parse(saml2LoginElt, this.pc);
|
||||
this.saml2AuthorizationRequestFilter = parser.getSaml2WebSsoAuthenticationRequestFilter();
|
||||
|
||||
this.saml2AuthenticationFilterId = this.pc.getReaderContext().generateBeanName(saml2WebSsoAuthenticationFilter);
|
||||
this.saml2AuthenticationRequestFilterId = this.pc.getReaderContext()
|
||||
.generateBeanName(this.saml2AuthorizationRequestFilter);
|
||||
this.saml2AuthenticationUrlToProviderName = parser.getSaml2AuthenticationUrlToProviderName();
|
||||
|
||||
// register the component
|
||||
this.pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(saml2WebSsoAuthenticationFilter, this.saml2AuthenticationFilterId));
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(this.saml2AuthorizationRequestFilter,
|
||||
this.saml2AuthenticationRequestFilterId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses OpenID 1.0 and 2.0 - related parts of configuration xmls
|
||||
* @param sessionStrategy sessionStrategy
|
||||
@@ -728,12 +666,6 @@ final class AuthenticationConfigBuilder {
|
||||
loginPageFilter.addPropertyValue("Oauth2LoginEnabled", true);
|
||||
loginPageFilter.addPropertyValue("Oauth2AuthenticationUrlToClientName", this.oauth2LoginLinks);
|
||||
}
|
||||
if (this.saml2AuthenticationFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(this.saml2AuthenticationFilterId);
|
||||
loginPageFilter.addPropertyValue("saml2LoginEnabled", true);
|
||||
loginPageFilter.addPropertyValue("saml2AuthenticationUrlToProviderName",
|
||||
this.saml2AuthenticationUrlToProviderName);
|
||||
}
|
||||
this.loginPageGenerationFilter = loginPageFilter.getBeanDefinition();
|
||||
this.logoutPageGenerationFilter = logoutPageFilter.getBeanDefinition();
|
||||
}
|
||||
@@ -750,33 +682,9 @@ final class AuthenticationConfigBuilder {
|
||||
this.rememberMeServicesId, this.csrfLogoutHandler);
|
||||
this.logoutFilter = logoutParser.parse(logoutElt, this.pc);
|
||||
this.logoutHandlers = logoutParser.getLogoutHandlers();
|
||||
this.logoutSuccessHandler = logoutParser.getLogoutSuccessHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void createSaml2LogoutFilter() {
|
||||
Element saml2LogoutElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.SAML2_LOGOUT);
|
||||
if (saml2LogoutElt == null) {
|
||||
return;
|
||||
}
|
||||
Saml2LogoutBeanDefinitionParser parser = new Saml2LogoutBeanDefinitionParser(this.logoutHandlers,
|
||||
this.logoutSuccessHandler);
|
||||
parser.parse(saml2LogoutElt, this.pc);
|
||||
BeanDefinition saml2LogoutFilter = parser.getLogoutFilter();
|
||||
BeanDefinition saml2LogoutRequestFilter = parser.getLogoutRequestFilter();
|
||||
BeanDefinition saml2LogoutResponseFilter = parser.getLogoutResponseFilter();
|
||||
this.saml2LogoutFilterId = this.pc.getReaderContext().generateBeanName(saml2LogoutFilter);
|
||||
this.saml2LogoutRequestFilterId = this.pc.getReaderContext().generateBeanName(saml2LogoutRequestFilter);
|
||||
this.saml2LogoutResponseFilterId = this.pc.getReaderContext().generateBeanName(saml2LogoutResponseFilter);
|
||||
|
||||
// register the component
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(saml2LogoutFilter, this.saml2LogoutFilterId));
|
||||
this.pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(saml2LogoutRequestFilter, this.saml2LogoutRequestFilterId));
|
||||
this.pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(saml2LogoutResponseFilter, this.saml2LogoutResponseFilterId));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
ManagedList getLogoutHandlers() {
|
||||
if (this.logoutHandlers == null && this.rememberMeProviderRef != null) {
|
||||
@@ -932,8 +840,7 @@ final class AuthenticationConfigBuilder {
|
||||
if (formLoginElt != null && this.oauth2LoginEntryPoint != null) {
|
||||
return this.formEntryPoint;
|
||||
}
|
||||
// If form login was enabled through auto-config, and Oauth2 login & Saml2
|
||||
// login was not
|
||||
// If form login was enabled through auto-config, and Oauth2 login was not
|
||||
// enabled then use form login
|
||||
if (this.oauth2LoginEntryPoint == null) {
|
||||
return this.formEntryPoint;
|
||||
@@ -1016,20 +923,6 @@ final class AuthenticationConfigBuilder {
|
||||
filters.add(new OrderDecorator(this.authorizationCodeGrantFilter,
|
||||
SecurityFilters.OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER));
|
||||
}
|
||||
if (this.saml2AuthenticationFilterId != null) {
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2AuthenticationFilterId),
|
||||
SecurityFilters.SAML2_AUTHENTICATION_FILTER));
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2AuthenticationRequestFilterId),
|
||||
SecurityFilters.SAML2_AUTHENTICATION_REQUEST_FILTER));
|
||||
}
|
||||
if (this.saml2LogoutFilterId != null) {
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2LogoutFilterId),
|
||||
SecurityFilters.SAML2_LOGOUT_FILTER));
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2LogoutRequestFilterId),
|
||||
SecurityFilters.SAML2_LOGOUT_REQUEST_FILTER));
|
||||
filters.add(new OrderDecorator(new RuntimeBeanReference(this.saml2LogoutResponseFilterId),
|
||||
SecurityFilters.SAML2_LOGOUT_RESPONSE_FILTER));
|
||||
}
|
||||
filters.add(new OrderDecorator(this.etf, SecurityFilters.EXCEPTION_TRANSLATION_FILTER));
|
||||
return filters;
|
||||
}
|
||||
|
||||
+1
-82
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -36,9 +36,6 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
||||
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.FeaturePolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.HpkpHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.HstsHeaderWriter;
|
||||
@@ -125,12 +122,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String PERMISSIONS_POLICY_ELEMENT = "permissions-policy";
|
||||
|
||||
private static final String CROSS_ORIGIN_OPENER_POLICY_ELEMENT = "cross-origin-opener-policy";
|
||||
|
||||
private static final String CROSS_ORIGIN_EMBEDDER_POLICY_ELEMENT = "cross-origin-embedder-policy";
|
||||
|
||||
private static final String CROSS_ORIGIN_RESOURCE_POLICY_ELEMENT = "cross-origin-resource-policy";
|
||||
|
||||
private static final String ALLOW_FROM = "ALLOW-FROM";
|
||||
|
||||
private ManagedList<BeanMetadataElement> headerWriters;
|
||||
@@ -153,9 +144,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
parseReferrerPolicyElement(element, parserContext);
|
||||
parseFeaturePolicyElement(element, parserContext);
|
||||
parsePermissionsPolicyElement(element, parserContext);
|
||||
parseCrossOriginOpenerPolicy(disabled, element);
|
||||
parseCrossOriginEmbedderPolicy(disabled, element);
|
||||
parseCrossOriginResourcePolicy(disabled, element);
|
||||
parseHeaderElements(element);
|
||||
boolean noWriters = this.headerWriters.isEmpty();
|
||||
if (disabled && !noWriters) {
|
||||
@@ -388,75 +376,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
this.headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void parseCrossOriginOpenerPolicy(boolean elementDisabled, Element element) {
|
||||
if (elementDisabled || element == null) {
|
||||
return;
|
||||
}
|
||||
CrossOriginOpenerPolicyHeaderWriter writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||
Element crossOriginOpenerPolicyElement = DomUtils.getChildElementByTagName(element,
|
||||
CROSS_ORIGIN_OPENER_POLICY_ELEMENT);
|
||||
if (crossOriginOpenerPolicyElement != null) {
|
||||
addCrossOriginOpenerPolicy(crossOriginOpenerPolicyElement, writer);
|
||||
}
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(CrossOriginOpenerPolicyHeaderWriter.class, () -> writer);
|
||||
this.headerWriters.add(builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void parseCrossOriginEmbedderPolicy(boolean elementDisabled, Element element) {
|
||||
if (elementDisabled || element == null) {
|
||||
return;
|
||||
}
|
||||
CrossOriginEmbedderPolicyHeaderWriter writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||
Element crossOriginEmbedderPolicyElement = DomUtils.getChildElementByTagName(element,
|
||||
CROSS_ORIGIN_EMBEDDER_POLICY_ELEMENT);
|
||||
if (crossOriginEmbedderPolicyElement != null) {
|
||||
addCrossOriginEmbedderPolicy(crossOriginEmbedderPolicyElement, writer);
|
||||
}
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(CrossOriginEmbedderPolicyHeaderWriter.class, () -> writer);
|
||||
this.headerWriters.add(builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void parseCrossOriginResourcePolicy(boolean elementDisabled, Element element) {
|
||||
if (elementDisabled || element == null) {
|
||||
return;
|
||||
}
|
||||
CrossOriginResourcePolicyHeaderWriter writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||
Element crossOriginResourcePolicyElement = DomUtils.getChildElementByTagName(element,
|
||||
CROSS_ORIGIN_RESOURCE_POLICY_ELEMENT);
|
||||
if (crossOriginResourcePolicyElement != null) {
|
||||
addCrossOriginResourcePolicy(crossOriginResourcePolicyElement, writer);
|
||||
}
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(CrossOriginResourcePolicyHeaderWriter.class, () -> writer);
|
||||
this.headerWriters.add(builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void addCrossOriginResourcePolicy(Element crossOriginResourcePolicyElement,
|
||||
CrossOriginResourcePolicyHeaderWriter writer) {
|
||||
String policy = crossOriginResourcePolicyElement.getAttribute(ATT_POLICY);
|
||||
if (StringUtils.hasText(policy)) {
|
||||
writer.setPolicy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.from(policy));
|
||||
}
|
||||
}
|
||||
|
||||
private void addCrossOriginEmbedderPolicy(Element crossOriginEmbedderPolicyElement,
|
||||
CrossOriginEmbedderPolicyHeaderWriter writer) {
|
||||
String policy = crossOriginEmbedderPolicyElement.getAttribute(ATT_POLICY);
|
||||
if (StringUtils.hasText(policy)) {
|
||||
writer.setPolicy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.from(policy));
|
||||
}
|
||||
}
|
||||
|
||||
private void addCrossOriginOpenerPolicy(Element crossOriginOpenerPolicyElement,
|
||||
CrossOriginOpenerPolicyHeaderWriter writer) {
|
||||
String policy = crossOriginOpenerPolicyElement.getAttribute(ATT_POLICY);
|
||||
if (StringUtils.hasText(policy)) {
|
||||
writer.setPolicy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.from(policy));
|
||||
}
|
||||
}
|
||||
|
||||
private void attrNotAllowed(ParserContext context, String attrName, String otherAttrName, Element element) {
|
||||
context.getReaderContext().error("Only one of '" + attrName + "' or '" + otherAttrName + "' can be set.",
|
||||
element);
|
||||
|
||||
+17
-78
@@ -59,7 +59,6 @@ import org.springframework.security.web.authentication.session.RegisterSessionAu
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.context.NullSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||
@@ -68,8 +67,6 @@ import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.DisableEncodeUrlFilter;
|
||||
import org.springframework.security.web.session.ForceEagerSessionCreationFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
|
||||
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
|
||||
@@ -107,8 +104,6 @@ class HttpConfigurationBuilder {
|
||||
|
||||
private static final String ATT_SECURITY_CONTEXT_REPOSITORY = "security-context-repository-ref";
|
||||
|
||||
private static final String ATT_SECURITY_CONTEXT_EXPLICIT_SAVE = "security-context-explicit-save";
|
||||
|
||||
private static final String ATT_INVALID_SESSION_STRATEGY_REF = "invalid-session-strategy-ref";
|
||||
|
||||
private static final String ATT_DISABLE_URL_REWRITING = "disable-url-rewriting";
|
||||
@@ -149,8 +144,6 @@ class HttpConfigurationBuilder {
|
||||
|
||||
private BeanDefinition securityContextPersistenceFilter;
|
||||
|
||||
private BeanDefinition forceEagerSessionCreationFilter;
|
||||
|
||||
private BeanReference contextRepoRef;
|
||||
|
||||
private BeanReference sessionRegistryRef;
|
||||
@@ -183,8 +176,6 @@ class HttpConfigurationBuilder {
|
||||
|
||||
private BeanDefinition csrfFilter;
|
||||
|
||||
private BeanDefinition disableUrlRewriteFilter;
|
||||
|
||||
private BeanDefinition wellKnownChangePasswordRedirectFilter;
|
||||
|
||||
private BeanMetadataElement csrfLogoutHandler;
|
||||
@@ -210,10 +201,8 @@ class HttpConfigurationBuilder {
|
||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||
this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED
|
||||
: createPolicy(createSession);
|
||||
createForceEagerSessionCreationFilter();
|
||||
createDisableEncodeUrlFilter();
|
||||
createCsrfFilter();
|
||||
createSecurityPersistence();
|
||||
createSecurityContextPersistenceFilter();
|
||||
createSessionManagementFilters();
|
||||
createWebAsyncManagerFilter();
|
||||
createRequestCacheFilter();
|
||||
@@ -289,51 +278,19 @@ class HttpConfigurationBuilder {
|
||||
return lowerCase ? path.toLowerCase() : path;
|
||||
}
|
||||
|
||||
BeanReference getSecurityContextRepositoryForAuthenticationFilters() {
|
||||
return (isExplicitSave()) ? this.contextRepoRef : null;
|
||||
}
|
||||
|
||||
private void createSecurityPersistence() {
|
||||
createSecurityContextRepository();
|
||||
if (isExplicitSave()) {
|
||||
createSecurityContextHolderFilter();
|
||||
}
|
||||
else {
|
||||
createSecurityContextPersistenceFilter();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExplicitSave() {
|
||||
String explicitSaveAttr = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_EXPLICIT_SAVE);
|
||||
return Boolean.parseBoolean(explicitSaveAttr);
|
||||
}
|
||||
|
||||
private void createForceEagerSessionCreationFilter() {
|
||||
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
|
||||
this.forceEagerSessionCreationFilter = new RootBeanDefinition(ForceEagerSessionCreationFilter.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void createSecurityContextPersistenceFilter() {
|
||||
BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class);
|
||||
switch (this.sessionPolicy) {
|
||||
case ALWAYS:
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
break;
|
||||
case NEVER:
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
break;
|
||||
default:
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
}
|
||||
scpf.addConstructorArgValue(this.contextRepoRef);
|
||||
|
||||
this.securityContextPersistenceFilter = scpf.getBeanDefinition();
|
||||
}
|
||||
|
||||
private void createSecurityContextRepository() {
|
||||
String repoRef = this.httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY);
|
||||
if (!StringUtils.hasText(repoRef)) {
|
||||
String disableUrlRewriting = this.httpElt.getAttribute(ATT_DISABLE_URL_REWRITING);
|
||||
if (!StringUtils.hasText(disableUrlRewriting)) {
|
||||
disableUrlRewriting = "true";
|
||||
}
|
||||
if (StringUtils.hasText(repoRef)) {
|
||||
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BeanDefinitionBuilder contextRepo;
|
||||
if (this.sessionPolicy == SessionCreationPolicy.STATELESS) {
|
||||
contextRepo = BeanDefinitionBuilder.rootBeanDefinition(NullSecurityContextRepository.class);
|
||||
@@ -343,14 +300,17 @@ class HttpConfigurationBuilder {
|
||||
switch (this.sessionPolicy) {
|
||||
case ALWAYS:
|
||||
contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||
break;
|
||||
case NEVER:
|
||||
contextRepo.addPropertyValue("allowSessionCreation", Boolean.FALSE);
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
break;
|
||||
default:
|
||||
contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||
scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE);
|
||||
}
|
||||
if (isDisableUrlRewriting()) {
|
||||
if ("true".equals(disableUrlRewriting)) {
|
||||
contextRepo.addPropertyValue("disableUrlRewriting", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
@@ -360,17 +320,9 @@ class HttpConfigurationBuilder {
|
||||
}
|
||||
|
||||
this.contextRepoRef = new RuntimeBeanReference(repoRef);
|
||||
}
|
||||
scpf.addConstructorArgValue(this.contextRepoRef);
|
||||
|
||||
private boolean isDisableUrlRewriting() {
|
||||
String disableUrlRewriting = this.httpElt.getAttribute(ATT_DISABLE_URL_REWRITING);
|
||||
return !"false".equals(disableUrlRewriting);
|
||||
}
|
||||
|
||||
private void createSecurityContextHolderFilter() {
|
||||
BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextHolderFilter.class);
|
||||
filter.addConstructorArgValue(this.contextRepoRef);
|
||||
this.securityContextPersistenceFilter = filter.getBeanDefinition();
|
||||
this.securityContextPersistenceFilter = scpf.getBeanDefinition();
|
||||
}
|
||||
|
||||
private void createSessionManagementFilters() {
|
||||
@@ -733,12 +685,6 @@ class HttpConfigurationBuilder {
|
||||
|
||||
}
|
||||
|
||||
private void createDisableEncodeUrlFilter() {
|
||||
if (isDisableUrlRewriting()) {
|
||||
this.disableUrlRewriteFilter = new RootBeanDefinition(DisableEncodeUrlFilter.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void createCsrfFilter() {
|
||||
Element elmt = DomUtils.getChildElementByTagName(this.httpElt, Elements.CSRF);
|
||||
this.csrfParser = new CsrfBeanDefinitionParser();
|
||||
@@ -778,13 +724,6 @@ class HttpConfigurationBuilder {
|
||||
|
||||
List<OrderDecorator> getFilters() {
|
||||
List<OrderDecorator> filters = new ArrayList<>();
|
||||
if (this.forceEagerSessionCreationFilter != null) {
|
||||
filters.add(new OrderDecorator(this.forceEagerSessionCreationFilter,
|
||||
SecurityFilters.FORCE_EAGER_SESSION_FILTER));
|
||||
}
|
||||
if (this.disableUrlRewriteFilter != null) {
|
||||
filters.add(new OrderDecorator(this.disableUrlRewriteFilter, SecurityFilters.DISABLE_ENCODE_URL_FILTER));
|
||||
}
|
||||
if (this.cpf != null) {
|
||||
filters.add(new OrderDecorator(this.cpf, SecurityFilters.CHANNEL_FILTER));
|
||||
}
|
||||
|
||||
+1
-3
@@ -144,11 +144,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||
boolean forceAutoConfig = isDefaultHttpConfig(element);
|
||||
HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, forceAutoConfig, pc, portMapper,
|
||||
portResolver, authenticationManager);
|
||||
httpBldr.getSecurityContextRepositoryForAuthenticationFilters();
|
||||
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, forceAutoConfig, pc,
|
||||
httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager,
|
||||
httpBldr.getSecurityContextRepositoryForAuthenticationFilters(), httpBldr.getSessionStrategy(),
|
||||
portMapper, portResolver, httpBldr.getCsrfLogoutHandler());
|
||||
httpBldr.getSessionStrategy(), portMapper, portResolver, httpBldr.getCsrfLogoutHandler());
|
||||
httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers());
|
||||
httpBldr.setEntryPoint(authBldr.getEntryPointBean());
|
||||
httpBldr.setAccessDeniedHandler(authBldr.getAccessDeniedHandlerBean());
|
||||
|
||||
-7
@@ -59,8 +59,6 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private boolean csrfEnabled;
|
||||
|
||||
private BeanMetadataElement logoutSuccessHandler;
|
||||
|
||||
LogoutBeanDefinitionParser(String loginPageUrl, String rememberMeServices, BeanMetadataElement csrfLogoutHandler) {
|
||||
this.defaultLogoutUrl = loginPageUrl + "?logout";
|
||||
this.rememberMeServices = rememberMeServices;
|
||||
@@ -100,7 +98,6 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
pc.extractSource(element));
|
||||
}
|
||||
builder.addConstructorArgReference(successHandlerRef);
|
||||
this.logoutSuccessHandler = new RuntimeBeanReference(successHandlerRef);
|
||||
}
|
||||
else {
|
||||
// Use the logout URL if no handler set
|
||||
@@ -140,8 +137,4 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return this.logoutHandlers;
|
||||
}
|
||||
|
||||
BeanMetadataElement getLogoutSuccessHandler() {
|
||||
return this.logoutSuccessHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-12
@@ -50,8 +50,6 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private final BeanReference authenticationManager;
|
||||
|
||||
private final BeanReference authenticationFilterSecurityContextRepositoryRef;
|
||||
|
||||
private BeanDefinition defaultAuthorizedClientRepository;
|
||||
|
||||
private BeanDefinition authorizationRequestRedirectFilter;
|
||||
@@ -60,11 +58,9 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private BeanDefinition authorizationCodeAuthenticationProvider;
|
||||
|
||||
OAuth2ClientBeanDefinitionParser(BeanReference requestCache, BeanReference authenticationManager,
|
||||
BeanReference authenticationFilterSecurityContextRepositoryRef) {
|
||||
OAuth2ClientBeanDefinitionParser(BeanReference requestCache, BeanReference authenticationManager) {
|
||||
this.requestCache = requestCache;
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.authenticationFilterSecurityContextRepositoryRef = authenticationFilterSecurityContextRepositoryRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,16 +92,11 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser {
|
||||
this.authorizationRequestRedirectFilter = authorizationRequestRedirectFilterBuilder
|
||||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository)
|
||||
.addPropertyValue("requestCache", this.requestCache).getBeanDefinition();
|
||||
BeanDefinitionBuilder authorizationCodeGrantFilterBldr = BeanDefinitionBuilder
|
||||
this.authorizationCodeGrantFilter = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OAuth2AuthorizationCodeGrantFilter.class)
|
||||
.addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository)
|
||||
.addConstructorArgValue(this.authenticationManager)
|
||||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository);
|
||||
if (this.authenticationFilterSecurityContextRepositoryRef != null) {
|
||||
authorizationCodeGrantFilterBldr.addPropertyValue("securityContextRepository",
|
||||
this.authenticationFilterSecurityContextRepositoryRef);
|
||||
}
|
||||
this.authorizationCodeGrantFilter = authorizationCodeGrantFilterBldr.getBeanDefinition();
|
||||
.addPropertyValue("authorizationRequestRepository", authorizationRequestRepository).getBeanDefinition();
|
||||
|
||||
BeanMetadataElement accessTokenResponseClient = getAccessTokenResponseClient(authorizationCodeGrantElt);
|
||||
this.authorizationCodeAuthenticationProvider = BeanDefinitionBuilder
|
||||
|
||||
-323
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.security.config.Elements;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
|
||||
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* SAML 2.0 Login {@link BeanDefinitionParser}
|
||||
*
|
||||
* @author Marcus da Coregio
|
||||
* @since 5.7
|
||||
*/
|
||||
final class Saml2LoginBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String DEFAULT_LOGIN_URI = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL;
|
||||
|
||||
private static final String DEFAULT_AUTHENTICATION_REQUEST_PROCESSING_URL = "/saml2/authenticate/{registrationId}";
|
||||
|
||||
private static final String ATT_LOGIN_PROCESSING_URL = "login-processing-url";
|
||||
|
||||
private static final String ATT_LOGIN_PAGE = "login-page";
|
||||
|
||||
private static final String ELT_RELYING_PARTY_REGISTRATION = "relying-party-registration";
|
||||
|
||||
private static final String ELT_REGISTRATION_ID = "registration-id";
|
||||
|
||||
private static final String ATT_AUTHENTICATION_FAILURE_HANDLER_REF = "authentication-failure-handler-ref";
|
||||
|
||||
private static final String ATT_AUTHENTICATION_SUCCESS_HANDLER_REF = "authentication-success-handler-ref";
|
||||
|
||||
private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";
|
||||
|
||||
private final List<BeanDefinition> csrfIgnoreRequestMatchers;
|
||||
|
||||
private final BeanReference portMapper;
|
||||
|
||||
private final BeanReference portResolver;
|
||||
|
||||
private final BeanReference requestCache;
|
||||
|
||||
private final boolean allowSessionCreation;
|
||||
|
||||
private final BeanReference authenticationManager;
|
||||
|
||||
private final BeanReference authenticationFilterSecurityContextRepositoryRef;
|
||||
|
||||
private final List<BeanReference> authenticationProviders;
|
||||
|
||||
private final Map<BeanDefinition, BeanMetadataElement> entryPoints;
|
||||
|
||||
private String loginProcessingUrl = Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI;
|
||||
|
||||
private BeanDefinition saml2WebSsoAuthenticationRequestFilter;
|
||||
|
||||
private BeanDefinition saml2AuthenticationUrlToProviderName;
|
||||
|
||||
Saml2LoginBeanDefinitionParser(List<BeanDefinition> csrfIgnoreRequestMatchers, BeanReference portMapper,
|
||||
BeanReference portResolver, BeanReference requestCache, boolean allowSessionCreation,
|
||||
BeanReference authenticationManager, BeanReference authenticationFilterSecurityContextRepositoryRef,
|
||||
List<BeanReference> authenticationProviders, Map<BeanDefinition, BeanMetadataElement> entryPoints) {
|
||||
this.csrfIgnoreRequestMatchers = csrfIgnoreRequestMatchers;
|
||||
this.portMapper = portMapper;
|
||||
this.portResolver = portResolver;
|
||||
this.requestCache = requestCache;
|
||||
this.allowSessionCreation = allowSessionCreation;
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.authenticationFilterSecurityContextRepositoryRef = authenticationFilterSecurityContextRepositoryRef;
|
||||
this.authenticationProviders = authenticationProviders;
|
||||
this.entryPoints = entryPoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
String loginProcessingUrl = element.getAttribute(ATT_LOGIN_PROCESSING_URL);
|
||||
if (StringUtils.hasText(loginProcessingUrl)) {
|
||||
this.loginProcessingUrl = loginProcessingUrl;
|
||||
}
|
||||
BeanDefinition saml2LoginBeanConfig = BeanDefinitionBuilder.rootBeanDefinition(Saml2LoginBeanConfig.class)
|
||||
.getBeanDefinition();
|
||||
String saml2LoginBeanConfigId = pc.getReaderContext().generateBeanName(saml2LoginBeanConfig);
|
||||
pc.registerBeanComponent(new BeanComponentDefinition(saml2LoginBeanConfig, saml2LoginBeanConfigId));
|
||||
registerDefaultCsrfOverride();
|
||||
BeanMetadataElement relyingPartyRegistrationRepository = Saml2LoginBeanDefinitionParserUtils
|
||||
.getRelyingPartyRegistrationRepository(element);
|
||||
BeanMetadataElement authenticationRequestRepository = Saml2LoginBeanDefinitionParserUtils
|
||||
.getAuthenticationRequestRepository(element);
|
||||
BeanMetadataElement authenticationRequestResolver = Saml2LoginBeanDefinitionParserUtils
|
||||
.getAuthenticationRequestResolver(element);
|
||||
if (authenticationRequestResolver == null) {
|
||||
authenticationRequestResolver = Saml2LoginBeanDefinitionParserUtils
|
||||
.createDefaultAuthenticationRequestResolver(relyingPartyRegistrationRepository);
|
||||
}
|
||||
BeanMetadataElement authenticationConverter = Saml2LoginBeanDefinitionParserUtils
|
||||
.getAuthenticationConverter(element);
|
||||
if (authenticationConverter == null) {
|
||||
if (!this.loginProcessingUrl.contains("{registrationId}")) {
|
||||
pc.getReaderContext().error("loginProcessingUrl must contain {registrationId} path variable", element);
|
||||
}
|
||||
authenticationConverter = Saml2LoginBeanDefinitionParserUtils
|
||||
.createDefaultAuthenticationConverter(relyingPartyRegistrationRepository);
|
||||
}
|
||||
// Configure the Saml2WebSsoAuthenticationFilter
|
||||
BeanDefinitionBuilder saml2WebSsoAuthenticationFilterBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(Saml2WebSsoAuthenticationFilter.class)
|
||||
.addConstructorArgValue(authenticationConverter).addConstructorArgValue(this.loginProcessingUrl)
|
||||
.addPropertyValue("authenticationRequestRepository", authenticationRequestRepository);
|
||||
resolveLoginPage(element, pc);
|
||||
resolveAuthenticationSuccessHandler(element, saml2WebSsoAuthenticationFilterBuilder);
|
||||
resolveAuthenticationFailureHandler(element, saml2WebSsoAuthenticationFilterBuilder);
|
||||
resolveAuthenticationManager(element, saml2WebSsoAuthenticationFilterBuilder);
|
||||
resolveSecurityContextRepository(element, saml2WebSsoAuthenticationFilterBuilder);
|
||||
// Configure the Saml2WebSsoAuthenticationRequestFilter
|
||||
this.saml2WebSsoAuthenticationRequestFilter = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(Saml2WebSsoAuthenticationRequestFilter.class)
|
||||
.addConstructorArgValue(authenticationRequestResolver)
|
||||
.addPropertyValue("authenticationRequestRepository", authenticationRequestRepository)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition saml2AuthenticationProvider = Saml2LoginBeanDefinitionParserUtils.createAuthenticationProvider();
|
||||
this.authenticationProviders.add(
|
||||
new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(saml2AuthenticationProvider)));
|
||||
this.saml2AuthenticationUrlToProviderName = BeanDefinitionBuilder.rootBeanDefinition(Map.class)
|
||||
.setFactoryMethodOnBean("getAuthenticationUrlToProviderName", saml2LoginBeanConfigId)
|
||||
.getBeanDefinition();
|
||||
return saml2WebSsoAuthenticationFilterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private void resolveAuthenticationManager(Element element,
|
||||
BeanDefinitionBuilder saml2WebSsoAuthenticationFilterBuilder) {
|
||||
String authenticationManagerRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF);
|
||||
if (StringUtils.hasText(authenticationManagerRef)) {
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyReference("authenticationManager",
|
||||
authenticationManagerRef);
|
||||
}
|
||||
else {
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyValue("authenticationManager",
|
||||
this.authenticationManager);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveSecurityContextRepository(Element element,
|
||||
BeanDefinitionBuilder saml2WebSsoAuthenticationFilterBuilder) {
|
||||
if (this.authenticationFilterSecurityContextRepositoryRef != null) {
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyValue("securityContextRepository",
|
||||
this.authenticationFilterSecurityContextRepositoryRef);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveLoginPage(Element element, ParserContext parserContext) {
|
||||
String loginPage = element.getAttribute(ATT_LOGIN_PAGE);
|
||||
Object source = parserContext.extractSource(element);
|
||||
BeanDefinition saml2LoginAuthenticationEntryPoint = null;
|
||||
if (StringUtils.hasText(loginPage)) {
|
||||
WebConfigUtils.validateHttpRedirect(loginPage, parserContext, source);
|
||||
saml2LoginAuthenticationEntryPoint = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class).addConstructorArgValue(loginPage)
|
||||
.addPropertyValue("portMapper", this.portMapper).addPropertyValue("portResolver", this.portResolver)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
else {
|
||||
Map<String, String> identityProviderUrlMap = getIdentityProviderUrlMap(element);
|
||||
if (identityProviderUrlMap.size() == 1) {
|
||||
String loginUrl = identityProviderUrlMap.entrySet().iterator().next().getKey();
|
||||
saml2LoginAuthenticationEntryPoint = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class).addConstructorArgValue(loginUrl)
|
||||
.addPropertyValue("portMapper", this.portMapper)
|
||||
.addPropertyValue("portResolver", this.portResolver).getBeanDefinition();
|
||||
}
|
||||
}
|
||||
if (saml2LoginAuthenticationEntryPoint != null) {
|
||||
BeanDefinitionBuilder requestMatcherBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AntPathRequestMatcher.class);
|
||||
requestMatcherBuilder.addConstructorArgValue(this.loginProcessingUrl);
|
||||
BeanDefinition requestMatcher = requestMatcherBuilder.getBeanDefinition();
|
||||
this.entryPoints.put(requestMatcher, saml2LoginAuthenticationEntryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveAuthenticationFailureHandler(Element element,
|
||||
BeanDefinitionBuilder saml2WebSsoAuthenticationFilterBuilder) {
|
||||
String authenticationFailureHandlerRef = element.getAttribute(ATT_AUTHENTICATION_FAILURE_HANDLER_REF);
|
||||
if (StringUtils.hasText(authenticationFailureHandlerRef)) {
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyReference("authenticationFailureHandler",
|
||||
authenticationFailureHandlerRef);
|
||||
}
|
||||
else {
|
||||
BeanDefinitionBuilder failureHandlerBuilder = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler");
|
||||
failureHandlerBuilder.addConstructorArgValue(
|
||||
DEFAULT_LOGIN_URI + "?" + DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME);
|
||||
failureHandlerBuilder.addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyValue("authenticationFailureHandler",
|
||||
failureHandlerBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveAuthenticationSuccessHandler(Element element,
|
||||
BeanDefinitionBuilder saml2WebSsoAuthenticationFilterBuilder) {
|
||||
String authenticationSuccessHandlerRef = element.getAttribute(ATT_AUTHENTICATION_SUCCESS_HANDLER_REF);
|
||||
if (StringUtils.hasText(authenticationSuccessHandlerRef)) {
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyReference("authenticationSuccessHandler",
|
||||
authenticationSuccessHandlerRef);
|
||||
}
|
||||
else {
|
||||
BeanDefinitionBuilder successHandlerBuilder = BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler")
|
||||
.addPropertyValue("requestCache", this.requestCache);
|
||||
saml2WebSsoAuthenticationFilterBuilder.addPropertyValue("authenticationSuccessHandler",
|
||||
successHandlerBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
private void registerDefaultCsrfOverride() {
|
||||
BeanDefinitionBuilder requestMatcherBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AntPathRequestMatcher.class);
|
||||
requestMatcherBuilder.addConstructorArgValue(this.loginProcessingUrl);
|
||||
BeanDefinition requestMatcher = requestMatcherBuilder.getBeanDefinition();
|
||||
this.csrfIgnoreRequestMatchers.add(requestMatcher);
|
||||
}
|
||||
|
||||
private Map<String, String> getIdentityProviderUrlMap(Element element) {
|
||||
Map<String, String> idps = new LinkedHashMap<>();
|
||||
Element relyingPartyRegistrationsElt = DomUtils.getChildElementByTagName(
|
||||
element.getOwnerDocument().getDocumentElement(), Elements.RELYING_PARTY_REGISTRATIONS);
|
||||
String authenticationRequestProcessingUrl = DEFAULT_AUTHENTICATION_REQUEST_PROCESSING_URL;
|
||||
if (relyingPartyRegistrationsElt != null) {
|
||||
List<Element> relyingPartyRegList = DomUtils.getChildElementsByTagName(relyingPartyRegistrationsElt,
|
||||
ELT_RELYING_PARTY_REGISTRATION);
|
||||
for (Element relyingPartyReg : relyingPartyRegList) {
|
||||
String registrationId = relyingPartyReg.getAttribute(ELT_REGISTRATION_ID);
|
||||
idps.put(authenticationRequestProcessingUrl.replace("{registrationId}", registrationId),
|
||||
registrationId);
|
||||
}
|
||||
}
|
||||
return idps;
|
||||
}
|
||||
|
||||
BeanDefinition getSaml2WebSsoAuthenticationRequestFilter() {
|
||||
return this.saml2WebSsoAuthenticationRequestFilter;
|
||||
}
|
||||
|
||||
BeanDefinition getSaml2AuthenticationUrlToProviderName() {
|
||||
return this.saml2AuthenticationUrlToProviderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper bean class to provide configuration from applicationContext
|
||||
*/
|
||||
public static class Saml2LoginBeanConfig implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@SuppressWarnings({ "unchecked", "unused" })
|
||||
Map<String, String> getAuthenticationUrlToProviderName() {
|
||||
Iterable<RelyingPartyRegistration> relyingPartyRegistrations = null;
|
||||
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository = this.context
|
||||
.getBean(RelyingPartyRegistrationRepository.class);
|
||||
ResolvableType type = ResolvableType.forInstance(relyingPartyRegistrationRepository).as(Iterable.class);
|
||||
if (type != ResolvableType.NONE
|
||||
&& RelyingPartyRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
|
||||
relyingPartyRegistrations = (Iterable<RelyingPartyRegistration>) relyingPartyRegistrationRepository;
|
||||
}
|
||||
if (relyingPartyRegistrations == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
String authenticationRequestProcessingUrl = DEFAULT_AUTHENTICATION_REQUEST_PROCESSING_URL;
|
||||
Map<String, String> saml2AuthenticationUrlToProviderName = new HashMap<>();
|
||||
relyingPartyRegistrations.forEach((registration) -> saml2AuthenticationUrlToProviderName.put(
|
||||
authenticationRequestProcessingUrl.replace("{registrationId}", registration.getRegistrationId()),
|
||||
registration.getRegistrationId()));
|
||||
return saml2AuthenticationUrlToProviderName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
|
||||
import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository;
|
||||
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Marcus da Coregio
|
||||
* @since 5.7
|
||||
*/
|
||||
final class Saml2LoginBeanDefinitionParserUtils {
|
||||
|
||||
private static final String ATT_RELYING_PARTY_REGISTRATION_REPOSITORY_REF = "relying-party-registration-repository-ref";
|
||||
|
||||
private static final String ATT_AUTHENTICATION_REQUEST_REPOSITORY_REF = "authentication-request-repository-ref";
|
||||
|
||||
private static final String ATT_AUTHENTICATION_REQUEST_RESOLVER_REF = "authentication-request-resolver-ref";
|
||||
|
||||
private static final String ATT_AUTHENTICATION_CONVERTER = "authentication-converter-ref";
|
||||
|
||||
private Saml2LoginBeanDefinitionParserUtils() {
|
||||
}
|
||||
|
||||
static BeanMetadataElement getRelyingPartyRegistrationRepository(Element element) {
|
||||
String relyingPartyRegistrationRepositoryRef = element
|
||||
.getAttribute(ATT_RELYING_PARTY_REGISTRATION_REPOSITORY_REF);
|
||||
if (StringUtils.hasText(relyingPartyRegistrationRepositoryRef)) {
|
||||
return new RuntimeBeanReference(relyingPartyRegistrationRepositoryRef);
|
||||
}
|
||||
return new RuntimeBeanReference(RelyingPartyRegistrationRepository.class);
|
||||
}
|
||||
|
||||
static BeanMetadataElement getAuthenticationRequestRepository(Element element) {
|
||||
String authenticationRequestRepositoryRef = element.getAttribute(ATT_AUTHENTICATION_REQUEST_REPOSITORY_REF);
|
||||
if (StringUtils.hasText(authenticationRequestRepositoryRef)) {
|
||||
return new RuntimeBeanReference(authenticationRequestRepositoryRef);
|
||||
}
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(HttpSessionSaml2AuthenticationRequestRepository.class)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanMetadataElement getAuthenticationRequestResolver(Element element) {
|
||||
String authenticationRequestContextResolver = element.getAttribute(ATT_AUTHENTICATION_REQUEST_RESOLVER_REF);
|
||||
if (StringUtils.hasText(authenticationRequestContextResolver)) {
|
||||
return new RuntimeBeanReference(authenticationRequestContextResolver);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static BeanMetadataElement createDefaultAuthenticationRequestResolver(
|
||||
BeanMetadataElement relyingPartyRegistrationRepository) {
|
||||
BeanMetadataElement defaultRelyingPartyRegistrationResolver = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DefaultRelyingPartyRegistrationResolver.class)
|
||||
.addConstructorArgValue(relyingPartyRegistrationRepository).getBeanDefinition();
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver")
|
||||
.addConstructorArgValue(defaultRelyingPartyRegistrationResolver).getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanDefinition createAuthenticationProvider() {
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider")
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanMetadataElement getAuthenticationConverter(Element element) {
|
||||
String authenticationConverter = element.getAttribute(ATT_AUTHENTICATION_CONVERTER);
|
||||
if (StringUtils.hasText(authenticationConverter)) {
|
||||
return new RuntimeBeanReference(authenticationConverter);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static BeanDefinition createDefaultAuthenticationConverter(BeanMetadataElement relyingPartyRegistrationRepository) {
|
||||
AbstractBeanDefinition resolver = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DefaultRelyingPartyRegistrationResolver.class)
|
||||
.addConstructorArgValue(relyingPartyRegistrationRepository).getBeanDefinition();
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(Saml2AuthenticationTokenConverter.class)
|
||||
.addConstructorArgValue(resolver).getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
-236
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestFilter;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseFilter;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2RelyingPartyInitiatedLogoutSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* SAML 2.0 Single Logout {@link BeanDefinitionParser}
|
||||
*
|
||||
* @author Marcus da Coregio
|
||||
* @since 5.7
|
||||
*/
|
||||
final class Saml2LogoutBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String ATT_LOGOUT_REQUEST_URL = "logout-request-url";
|
||||
|
||||
private static final String ATT_LOGOUT_RESPONSE_URL = "logout-response-url";
|
||||
|
||||
private static final String ATT_LOGOUT_URL = "logout-url";
|
||||
|
||||
private List<BeanMetadataElement> logoutHandlers;
|
||||
|
||||
private String logoutUrl = "/logout";
|
||||
|
||||
private String logoutRequestUrl = "/logout/saml2/slo";
|
||||
|
||||
private String logoutResponseUrl = "/logout/saml2/slo";
|
||||
|
||||
private BeanMetadataElement logoutSuccessHandler;
|
||||
|
||||
private BeanDefinition logoutRequestFilter;
|
||||
|
||||
private BeanDefinition logoutResponseFilter;
|
||||
|
||||
private BeanDefinition logoutFilter;
|
||||
|
||||
Saml2LogoutBeanDefinitionParser(ManagedList<BeanMetadataElement> logoutHandlers,
|
||||
BeanMetadataElement logoutSuccessHandler) {
|
||||
this.logoutHandlers = logoutHandlers;
|
||||
this.logoutSuccessHandler = logoutSuccessHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||
String logoutUrl = element.getAttribute(ATT_LOGOUT_URL);
|
||||
if (StringUtils.hasText(logoutUrl)) {
|
||||
this.logoutUrl = logoutUrl;
|
||||
}
|
||||
String logoutRequestUrl = element.getAttribute(ATT_LOGOUT_REQUEST_URL);
|
||||
if (StringUtils.hasText(logoutRequestUrl)) {
|
||||
this.logoutRequestUrl = logoutRequestUrl;
|
||||
}
|
||||
String logoutResponseUrl = element.getAttribute(ATT_LOGOUT_RESPONSE_URL);
|
||||
if (StringUtils.hasText(logoutResponseUrl)) {
|
||||
this.logoutResponseUrl = logoutResponseUrl;
|
||||
}
|
||||
WebConfigUtils.validateHttpRedirect(this.logoutUrl, pc, element);
|
||||
WebConfigUtils.validateHttpRedirect(this.logoutRequestUrl, pc, element);
|
||||
WebConfigUtils.validateHttpRedirect(this.logoutResponseUrl, pc, element);
|
||||
if (CollectionUtils.isEmpty(this.logoutHandlers)) {
|
||||
this.logoutHandlers = createDefaultLogoutHandlers();
|
||||
}
|
||||
if (this.logoutSuccessHandler == null) {
|
||||
this.logoutSuccessHandler = createDefaultLogoutSuccessHandler();
|
||||
}
|
||||
BeanMetadataElement relyingPartyRegistrationRepository = Saml2LogoutBeanDefinitionParserUtils
|
||||
.getRelyingPartyRegistrationRepository(element);
|
||||
BeanMetadataElement registrations = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(DefaultRelyingPartyRegistrationResolver.class)
|
||||
.addConstructorArgValue(relyingPartyRegistrationRepository).getBeanDefinition();
|
||||
BeanMetadataElement logoutResponseResolver = Saml2LogoutBeanDefinitionParserUtils
|
||||
.getLogoutResponseResolver(element, registrations);
|
||||
BeanMetadataElement logoutRequestValidator = Saml2LogoutBeanDefinitionParserUtils
|
||||
.getLogoutRequestValidator(element);
|
||||
BeanMetadataElement logoutRequestMatcher = createSaml2LogoutRequestMatcher();
|
||||
this.logoutRequestFilter = BeanDefinitionBuilder.rootBeanDefinition(Saml2LogoutRequestFilter.class)
|
||||
.addConstructorArgValue(registrations).addConstructorArgValue(logoutRequestValidator)
|
||||
.addConstructorArgValue(logoutResponseResolver).addConstructorArgValue(this.logoutHandlers)
|
||||
.addPropertyValue("logoutRequestMatcher", logoutRequestMatcher).getBeanDefinition();
|
||||
BeanMetadataElement logoutResponseValidator = Saml2LogoutBeanDefinitionParserUtils
|
||||
.getLogoutResponseValidator(element);
|
||||
BeanMetadataElement logoutRequestRepository = Saml2LogoutBeanDefinitionParserUtils
|
||||
.getLogoutRequestRepository(element);
|
||||
BeanMetadataElement logoutResponseMatcher = createSaml2LogoutResponseMatcher();
|
||||
this.logoutResponseFilter = BeanDefinitionBuilder.rootBeanDefinition(Saml2LogoutResponseFilter.class)
|
||||
.addConstructorArgValue(registrations).addConstructorArgValue(logoutResponseValidator)
|
||||
.addConstructorArgValue(this.logoutSuccessHandler)
|
||||
.addPropertyValue("logoutRequestMatcher", logoutResponseMatcher)
|
||||
.addPropertyValue("logoutRequestRepository", logoutRequestRepository).getBeanDefinition();
|
||||
BeanMetadataElement logoutRequestResolver = Saml2LogoutBeanDefinitionParserUtils
|
||||
.getLogoutRequestResolver(element, registrations);
|
||||
BeanMetadataElement saml2LogoutRequestSuccessHandler = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(Saml2RelyingPartyInitiatedLogoutSuccessHandler.class)
|
||||
.addConstructorArgValue(logoutRequestResolver).getBeanDefinition();
|
||||
this.logoutFilter = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class)
|
||||
.addConstructorArgValue(saml2LogoutRequestSuccessHandler).addConstructorArgValue(this.logoutHandlers)
|
||||
.addPropertyValue("logoutRequestMatcher", createLogoutRequestMatcher()).getBeanDefinition();
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<BeanMetadataElement> createDefaultLogoutHandlers() {
|
||||
List<BeanMetadataElement> handlers = new ManagedList<>();
|
||||
handlers.add(BeanDefinitionBuilder.rootBeanDefinition(SecurityContextLogoutHandler.class).getBeanDefinition());
|
||||
handlers.add(BeanDefinitionBuilder.rootBeanDefinition(LogoutSuccessEventPublishingLogoutHandler.class)
|
||||
.getBeanDefinition());
|
||||
return handlers;
|
||||
}
|
||||
|
||||
private static BeanMetadataElement createDefaultLogoutSuccessHandler() {
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(SimpleUrlLogoutSuccessHandler.class)
|
||||
.addPropertyValue("defaultTargetUrl", "/login?logout").getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement createLogoutRequestMatcher() {
|
||||
BeanMetadataElement logoutMatcher = BeanDefinitionBuilder.rootBeanDefinition(AntPathRequestMatcher.class)
|
||||
.addConstructorArgValue(this.logoutUrl).addConstructorArgValue("POST").getBeanDefinition();
|
||||
BeanMetadataElement saml2Matcher = BeanDefinitionBuilder.rootBeanDefinition(Saml2RequestMatcher.class)
|
||||
.getBeanDefinition();
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(AndRequestMatcher.class)
|
||||
.addConstructorArgValue(toManagedList(logoutMatcher, saml2Matcher)).getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement createSaml2LogoutRequestMatcher() {
|
||||
BeanMetadataElement logoutRequestMatcher = BeanDefinitionBuilder.rootBeanDefinition(AntPathRequestMatcher.class)
|
||||
.addConstructorArgValue(this.logoutRequestUrl).getBeanDefinition();
|
||||
BeanMetadataElement saml2RequestMatcher = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ParameterRequestMatcher.class).addConstructorArgValue("SAMLRequest")
|
||||
.getBeanDefinition();
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(AndRequestMatcher.class)
|
||||
.addConstructorArgValue(toManagedList(logoutRequestMatcher, saml2RequestMatcher)).getBeanDefinition();
|
||||
}
|
||||
|
||||
private BeanMetadataElement createSaml2LogoutResponseMatcher() {
|
||||
BeanMetadataElement logoutResponseMatcher = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AntPathRequestMatcher.class).addConstructorArgValue(this.logoutResponseUrl)
|
||||
.getBeanDefinition();
|
||||
BeanMetadataElement saml2ResponseMatcher = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ParameterRequestMatcher.class).addConstructorArgValue("SAMLResponse")
|
||||
.getBeanDefinition();
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(AndRequestMatcher.class)
|
||||
.addConstructorArgValue(toManagedList(logoutResponseMatcher, saml2ResponseMatcher)).getBeanDefinition();
|
||||
}
|
||||
|
||||
private static List<BeanMetadataElement> toManagedList(BeanMetadataElement... elements) {
|
||||
List<BeanMetadataElement> managedList = new ManagedList<>();
|
||||
managedList.addAll(Arrays.asList(elements));
|
||||
return managedList;
|
||||
}
|
||||
|
||||
BeanDefinition getLogoutRequestFilter() {
|
||||
return this.logoutRequestFilter;
|
||||
}
|
||||
|
||||
BeanDefinition getLogoutResponseFilter() {
|
||||
return this.logoutResponseFilter;
|
||||
}
|
||||
|
||||
BeanDefinition getLogoutFilter() {
|
||||
return this.logoutFilter;
|
||||
}
|
||||
|
||||
private static class ParameterRequestMatcher implements RequestMatcher {
|
||||
|
||||
Predicate<String> test = Objects::nonNull;
|
||||
|
||||
String name;
|
||||
|
||||
ParameterRequestMatcher(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return this.test.test(request.getParameter(this.name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Saml2RequestMatcher implements RequestMatcher {
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication == null) {
|
||||
return false;
|
||||
}
|
||||
return authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutRequestValidator;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutResponseValidator;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
|
||||
import org.springframework.security.saml2.provider.service.web.authentication.logout.HttpSessionLogoutRequestRepository;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Marcus da Coregio
|
||||
* @since 5.7
|
||||
*/
|
||||
final class Saml2LogoutBeanDefinitionParserUtils {
|
||||
|
||||
private static final String ATT_RELYING_PARTY_REGISTRATION_REPOSITORY_REF = "relying-party-registration-repository-ref";
|
||||
|
||||
private static final String ATT_LOGOUT_REQUEST_VALIDATOR_REF = "logout-request-validator-ref";
|
||||
|
||||
private static final String ATT_LOGOUT_REQUEST_REPOSITORY_REF = "logout-request-repository-ref";
|
||||
|
||||
private static final String ATT_LOGOUT_REQUEST_RESOLVER_REF = "logout-request-resolver-ref";
|
||||
|
||||
private static final String ATT_LOGOUT_RESPONSE_RESOLVER_REF = "logout-response-resolver-ref";
|
||||
|
||||
private static final String ATT_LOGOUT_RESPONSE_VALIDATOR_REF = "logout-response-validator-ref";
|
||||
|
||||
private Saml2LogoutBeanDefinitionParserUtils() {
|
||||
}
|
||||
|
||||
static BeanMetadataElement getRelyingPartyRegistrationRepository(Element element) {
|
||||
String relyingPartyRegistrationRepositoryRef = element
|
||||
.getAttribute(ATT_RELYING_PARTY_REGISTRATION_REPOSITORY_REF);
|
||||
if (StringUtils.hasText(relyingPartyRegistrationRepositoryRef)) {
|
||||
return new RuntimeBeanReference(relyingPartyRegistrationRepositoryRef);
|
||||
}
|
||||
return new RuntimeBeanReference(RelyingPartyRegistrationRepository.class);
|
||||
}
|
||||
|
||||
static BeanMetadataElement getLogoutResponseResolver(Element element, BeanMetadataElement registrations) {
|
||||
String logoutResponseResolver = element.getAttribute(ATT_LOGOUT_RESPONSE_RESOLVER_REF);
|
||||
if (StringUtils.hasText(logoutResponseResolver)) {
|
||||
return new RuntimeBeanReference(logoutResponseResolver);
|
||||
}
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutResponseResolver")
|
||||
.addConstructorArgValue(registrations).getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanMetadataElement getLogoutRequestValidator(Element element) {
|
||||
String logoutRequestValidator = element.getAttribute(ATT_LOGOUT_REQUEST_VALIDATOR_REF);
|
||||
if (StringUtils.hasText(logoutRequestValidator)) {
|
||||
return new RuntimeBeanReference(logoutRequestValidator);
|
||||
}
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(OpenSamlLogoutRequestValidator.class).getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanMetadataElement getLogoutResponseValidator(Element element) {
|
||||
String logoutResponseValidator = element.getAttribute(ATT_LOGOUT_RESPONSE_VALIDATOR_REF);
|
||||
if (StringUtils.hasText(logoutResponseValidator)) {
|
||||
return new RuntimeBeanReference(logoutResponseValidator);
|
||||
}
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(OpenSamlLogoutResponseValidator.class).getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanMetadataElement getLogoutRequestRepository(Element element) {
|
||||
String logoutRequestRepository = element.getAttribute(ATT_LOGOUT_REQUEST_REPOSITORY_REF);
|
||||
if (StringUtils.hasText(logoutRequestRepository)) {
|
||||
return new RuntimeBeanReference(logoutRequestRepository);
|
||||
}
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(HttpSessionLogoutRequestRepository.class).getBeanDefinition();
|
||||
}
|
||||
|
||||
static BeanMetadataElement getLogoutRequestResolver(Element element, BeanMetadataElement registrations) {
|
||||
String logoutRequestResolver = element.getAttribute(ATT_LOGOUT_REQUEST_RESOLVER_REF);
|
||||
if (StringUtils.hasText(logoutRequestResolver)) {
|
||||
return new RuntimeBeanReference(logoutRequestResolver);
|
||||
}
|
||||
return BeanDefinitionBuilder.rootBeanDefinition(
|
||||
"org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSaml4LogoutRequestResolver")
|
||||
.addConstructorArgValue(registrations).getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -29,10 +29,6 @@ enum SecurityFilters {
|
||||
|
||||
FIRST(Integer.MIN_VALUE),
|
||||
|
||||
DISABLE_ENCODE_URL_FILTER,
|
||||
|
||||
FORCE_EAGER_SESSION_FILTER,
|
||||
|
||||
CHANNEL_FILTER,
|
||||
|
||||
SECURITY_CONTEXT_FILTER,
|
||||
@@ -45,20 +41,12 @@ enum SecurityFilters {
|
||||
|
||||
CORS_FILTER,
|
||||
|
||||
SAML2_LOGOUT_REQUEST_FILTER,
|
||||
|
||||
SAML2_LOGOUT_RESPONSE_FILTER,
|
||||
|
||||
CSRF_FILTER,
|
||||
|
||||
SAML2_LOGOUT_FILTER,
|
||||
|
||||
LOGOUT_FILTER,
|
||||
|
||||
OAUTH2_AUTHORIZATION_REQUEST_FILTER,
|
||||
|
||||
SAML2_AUTHENTICATION_REQUEST_FILTER,
|
||||
|
||||
X509_FILTER,
|
||||
|
||||
PRE_AUTH_FILTER,
|
||||
@@ -67,8 +55,6 @@ enum SecurityFilters {
|
||||
|
||||
OAUTH2_LOGIN_FILTER,
|
||||
|
||||
SAML2_AUTHENTICATION_FILTER,
|
||||
|
||||
FORM_LOGIN_FILTER,
|
||||
|
||||
OPENID_FILTER,
|
||||
|
||||
-183
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.ldap.authentication.AbstractLdapAuthenticator;
|
||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
|
||||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||
|
||||
/**
|
||||
* Creates an {@link AuthenticationManager} that can perform LDAP authentication.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.7
|
||||
*/
|
||||
public abstract class AbstractLdapAuthenticationManagerFactory<T extends AbstractLdapAuthenticator> {
|
||||
|
||||
AbstractLdapAuthenticationManagerFactory(BaseLdapPathContextSource contextSource) {
|
||||
this.contextSource = contextSource;
|
||||
}
|
||||
|
||||
private BaseLdapPathContextSource contextSource;
|
||||
|
||||
private String[] userDnPatterns;
|
||||
|
||||
private LdapAuthoritiesPopulator ldapAuthoritiesPopulator;
|
||||
|
||||
private GrantedAuthoritiesMapper authoritiesMapper;
|
||||
|
||||
private UserDetailsContextMapper userDetailsContextMapper;
|
||||
|
||||
private String userSearchFilter;
|
||||
|
||||
private String userSearchBase = "";
|
||||
|
||||
/**
|
||||
* Sets the {@link BaseLdapPathContextSource} used to perform LDAP authentication.
|
||||
* @param contextSource the {@link BaseLdapPathContextSource} used to perform LDAP
|
||||
* authentication
|
||||
*/
|
||||
public void setContextSource(BaseLdapPathContextSource contextSource) {
|
||||
this.contextSource = contextSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link BaseLdapPathContextSource} used to perform LDAP authentication.
|
||||
* @return the {@link BaseLdapPathContextSource} used to perform LDAP authentication
|
||||
*/
|
||||
protected final BaseLdapPathContextSource getContextSource() {
|
||||
return this.contextSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link LdapAuthoritiesPopulator} used to obtain a list of granted
|
||||
* authorities for an LDAP user.
|
||||
* @param ldapAuthoritiesPopulator the {@link LdapAuthoritiesPopulator} to use
|
||||
*/
|
||||
public void setLdapAuthoritiesPopulator(LdapAuthoritiesPopulator ldapAuthoritiesPopulator) {
|
||||
this.ldapAuthoritiesPopulator = ldapAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link GrantedAuthoritiesMapper} used for converting the authorities
|
||||
* loaded from storage to a new set of authorities which will be associated to the
|
||||
* {@link UsernamePasswordAuthenticationToken}.
|
||||
* @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the
|
||||
* user's authorities
|
||||
*/
|
||||
public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
|
||||
this.authoritiesMapper = authoritiesMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom strategy to be used for creating the {@link UserDetails} which will
|
||||
* be stored as the principal in the {@link Authentication}.
|
||||
* @param userDetailsContextMapper the strategy instance
|
||||
*/
|
||||
public void setUserDetailsContextMapper(UserDetailsContextMapper userDetailsContextMapper) {
|
||||
this.userDetailsContextMapper = userDetailsContextMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* If your users are at a fixed location in the directory (i.e. you can work out the
|
||||
* DN directly from the username without doing a directory search), you can use this
|
||||
* attribute to map directly to the DN. It maps directly to the userDnPatterns
|
||||
* property of AbstractLdapAuthenticator. The value is a specific pattern used to
|
||||
* build the user's DN, for example "uid={0},ou=people". The key "{0}" must be present
|
||||
* and will be substituted with the username.
|
||||
* @param userDnPatterns the LDAP patterns for finding the usernames
|
||||
*/
|
||||
public void setUserDnPatterns(String... userDnPatterns) {
|
||||
this.userDnPatterns = userDnPatterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* The LDAP filter used to search for users (optional). For example "(uid={0})". The
|
||||
* substituted parameter is the user's login name.
|
||||
* @param userSearchFilter the LDAP filter used to search for users
|
||||
*/
|
||||
public void setUserSearchFilter(String userSearchFilter) {
|
||||
this.userSearchFilter = userSearchFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search base for user searches. Defaults to "". Only used with
|
||||
* {@link #setUserSearchFilter(String)}.
|
||||
* @param userSearchBase search base for user searches
|
||||
*/
|
||||
public void setUserSearchBase(String userSearchBase) {
|
||||
this.userSearchBase = userSearchBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured {@link AuthenticationManager} that can be used to perform
|
||||
* LDAP authentication.
|
||||
* @return the configured {@link AuthenticationManager}
|
||||
*/
|
||||
public final AuthenticationManager createAuthenticationManager() {
|
||||
LdapAuthenticationProvider ldapAuthenticationProvider = getProvider();
|
||||
return new ProviderManager(ldapAuthenticationProvider);
|
||||
}
|
||||
|
||||
private LdapAuthenticationProvider getProvider() {
|
||||
AbstractLdapAuthenticator authenticator = getAuthenticator();
|
||||
LdapAuthenticationProvider provider;
|
||||
if (this.ldapAuthoritiesPopulator != null) {
|
||||
provider = new LdapAuthenticationProvider(authenticator, this.ldapAuthoritiesPopulator);
|
||||
}
|
||||
else {
|
||||
provider = new LdapAuthenticationProvider(authenticator);
|
||||
}
|
||||
if (this.authoritiesMapper != null) {
|
||||
provider.setAuthoritiesMapper(this.authoritiesMapper);
|
||||
}
|
||||
if (this.userDetailsContextMapper != null) {
|
||||
provider.setUserDetailsContextMapper(this.userDetailsContextMapper);
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
|
||||
private AbstractLdapAuthenticator getAuthenticator() {
|
||||
AbstractLdapAuthenticator authenticator = createDefaultLdapAuthenticator();
|
||||
if (this.userSearchFilter != null) {
|
||||
authenticator.setUserSearch(
|
||||
new FilterBasedLdapUserSearch(this.userSearchBase, this.userSearchFilter, this.contextSource));
|
||||
}
|
||||
if (this.userDnPatterns != null && this.userDnPatterns.length > 0) {
|
||||
authenticator.setUserDnPatterns(this.userDnPatterns);
|
||||
}
|
||||
authenticator.afterPropertiesSet();
|
||||
return authenticator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to supply the default {@link AbstractLdapAuthenticator}.
|
||||
* @return the {@link AbstractLdapAuthenticator} that will be configured for LDAP
|
||||
* authentication
|
||||
*/
|
||||
protected abstract T createDefaultLdapAuthenticator();
|
||||
|
||||
}
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.server.EmbeddedLdapServerContainer;
|
||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Creates a {@link DefaultSpringSecurityContextSource} used to perform LDAP
|
||||
* authentication and starts and in-memory LDAP server.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.7
|
||||
*/
|
||||
public class EmbeddedLdapServerContextSourceFactoryBean
|
||||
implements FactoryBean<DefaultSpringSecurityContextSource>, DisposableBean, ApplicationContextAware {
|
||||
|
||||
private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
|
||||
|
||||
private static final int DEFAULT_PORT = 33389;
|
||||
|
||||
private static final int RANDOM_PORT = 0;
|
||||
|
||||
private Integer port;
|
||||
|
||||
private String ldif = "classpath*:*.ldif";
|
||||
|
||||
private String root = "dc=springframework,dc=org";
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
private String managerDn;
|
||||
|
||||
private String managerPassword;
|
||||
|
||||
private EmbeddedLdapServerContainer container;
|
||||
|
||||
/**
|
||||
* Create an EmbeddedLdapServerContextSourceFactoryBean that will use an embedded LDAP
|
||||
* server to perform LDAP authentication. This requires a dependency on
|
||||
* `com.unboundid:unboundid-ldapsdk`.
|
||||
* @return the EmbeddedLdapServerContextSourceFactoryBean
|
||||
*/
|
||||
public static EmbeddedLdapServerContextSourceFactoryBean fromEmbeddedLdapServer() {
|
||||
return new EmbeddedLdapServerContextSourceFactoryBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies an LDIF to load at startup for an embedded LDAP server. The default is
|
||||
* "classpath*:*.ldif".
|
||||
* @param ldif the ldif to load at startup for an embedded LDAP server.
|
||||
*/
|
||||
public void setLdif(String ldif) {
|
||||
this.ldif = ldif;
|
||||
}
|
||||
|
||||
/**
|
||||
* The port to connect to LDAP to (the default is 33389 or random available port if
|
||||
* unavailable). Supplying 0 as the port indicates that a random available port should
|
||||
* be selected.
|
||||
* @param port the port to connect to
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional root suffix for the embedded LDAP server. Default is
|
||||
* "dc=springframework,dc=org".
|
||||
* @param root root suffix for the embedded LDAP server
|
||||
*/
|
||||
public void setRoot(String root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Username (DN) of the "manager" user identity (i.e. "uid=admin,ou=system") which
|
||||
* will be used to authenticate to an LDAP server. If omitted, anonymous access will
|
||||
* be used.
|
||||
* @param managerDn the username (DN) of the "manager" user identity used to
|
||||
* authenticate to a LDAP server.
|
||||
*/
|
||||
public void setManagerDn(String managerDn) {
|
||||
this.managerDn = managerDn;
|
||||
}
|
||||
|
||||
/**
|
||||
* The password for the manager DN. This is required if the
|
||||
* {@link #setManagerDn(String)} is specified.
|
||||
* @param managerPassword password for the manager DN
|
||||
*/
|
||||
public void setManagerPassword(String managerPassword) {
|
||||
this.managerPassword = managerPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultSpringSecurityContextSource getObject() throws Exception {
|
||||
if (!ClassUtils.isPresent(UNBOUNDID_CLASSNAME, getClass().getClassLoader())) {
|
||||
throw new IllegalStateException("Embedded LDAP server is not provided");
|
||||
}
|
||||
this.container = getContainer();
|
||||
this.port = this.container.getPort();
|
||||
DefaultSpringSecurityContextSource contextSourceFromProviderUrl = new DefaultSpringSecurityContextSource(
|
||||
"ldap://127.0.0.1:" + this.port + "/" + this.root);
|
||||
if (this.managerDn != null) {
|
||||
contextSourceFromProviderUrl.setUserDn(this.managerDn);
|
||||
if (this.managerPassword == null) {
|
||||
throw new IllegalStateException("managerPassword is required if managerDn is supplied");
|
||||
}
|
||||
contextSourceFromProviderUrl.setPassword(this.managerPassword);
|
||||
}
|
||||
contextSourceFromProviderUrl.afterPropertiesSet();
|
||||
return contextSourceFromProviderUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return DefaultSpringSecurityContextSource.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (this.container instanceof Lifecycle) {
|
||||
((Lifecycle) this.container).stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
private EmbeddedLdapServerContainer getContainer() {
|
||||
if (!ClassUtils.isPresent(UNBOUNDID_CLASSNAME, getClass().getClassLoader())) {
|
||||
throw new IllegalStateException("Embedded LDAP server is not provided");
|
||||
}
|
||||
UnboundIdContainer unboundIdContainer = new UnboundIdContainer(this.root, this.ldif);
|
||||
unboundIdContainer.setApplicationContext(this.context);
|
||||
unboundIdContainer.setPort(getEmbeddedServerPort());
|
||||
unboundIdContainer.afterPropertiesSet();
|
||||
return unboundIdContainer;
|
||||
}
|
||||
|
||||
private int getEmbeddedServerPort() {
|
||||
if (this.port == null) {
|
||||
this.port = getDefaultEmbeddedServerPort();
|
||||
}
|
||||
return this.port;
|
||||
}
|
||||
|
||||
private int getDefaultEmbeddedServerPort() {
|
||||
try (ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT)) {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return RANDOM_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.ldap.authentication.BindAuthenticator;
|
||||
|
||||
/**
|
||||
* Creates an {@link AuthenticationManager} that can perform LDAP authentication using
|
||||
* bind authentication.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.7
|
||||
*/
|
||||
public class LdapBindAuthenticationManagerFactory extends AbstractLdapAuthenticationManagerFactory<BindAuthenticator> {
|
||||
|
||||
public LdapBindAuthenticationManagerFactory(BaseLdapPathContextSource contextSource) {
|
||||
super(contextSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BindAuthenticator createDefaultLdapAuthenticator() {
|
||||
return new BindAuthenticator(getContextSource());
|
||||
}
|
||||
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.ldap;
|
||||
|
||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Creates an {@link AuthenticationManager} that can perform LDAP authentication using
|
||||
* password comparison.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.7
|
||||
*/
|
||||
public class LdapPasswordComparisonAuthenticationManagerFactory
|
||||
extends AbstractLdapAuthenticationManagerFactory<PasswordComparisonAuthenticator> {
|
||||
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
private String passwordAttribute;
|
||||
|
||||
public LdapPasswordComparisonAuthenticationManagerFactory(BaseLdapPathContextSource contextSource,
|
||||
PasswordEncoder passwordEncoder) {
|
||||
super(contextSource);
|
||||
setPasswordEncoder(passwordEncoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link PasswordEncoder} to be used when authenticating with password
|
||||
* comparison.
|
||||
* @param passwordEncoder the {@link PasswordEncoder} to use
|
||||
*/
|
||||
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
|
||||
Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* The attribute in the directory which contains the user password. Only used when
|
||||
* authenticating with password comparison. Defaults to "userPassword".
|
||||
* @param passwordAttribute the attribute in the directory which contains the user
|
||||
* password
|
||||
*/
|
||||
public void setPasswordAttribute(String passwordAttribute) {
|
||||
this.passwordAttribute = passwordAttribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PasswordComparisonAuthenticator createDefaultLdapAuthenticator() {
|
||||
PasswordComparisonAuthenticator ldapAuthenticator = new PasswordComparisonAuthenticator(getContextSource());
|
||||
if (this.passwordAttribute != null) {
|
||||
ldapAuthenticator.setPasswordAttributeName(this.passwordAttribute);
|
||||
}
|
||||
ldapAuthenticator.setPasswordEncoder(this.passwordEncoder);
|
||||
return ldapAuthenticator;
|
||||
}
|
||||
|
||||
}
|
||||
-376
@@ -1,376 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.saml2;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.security.converter.RsaKeyConverters;
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations;
|
||||
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* @author Marcus da Coregio
|
||||
* @since 5.7
|
||||
*/
|
||||
public final class RelyingPartyRegistrationsBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String ELT_RELYING_PARTY_REGISTRATION = "relying-party-registration";
|
||||
|
||||
private static final String ELT_SIGNING_CREDENTIAL = "signing-credential";
|
||||
|
||||
private static final String ELT_DECRYPTION_CREDENTIAL = "decryption-credential";
|
||||
|
||||
private static final String ELT_ASSERTING_PARTY = "asserting-party";
|
||||
|
||||
private static final String ELT_VERIFICATION_CREDENTIAL = "verification-credential";
|
||||
|
||||
private static final String ELT_ENCRYPTION_CREDENTIAL = "encryption-credential";
|
||||
|
||||
private static final String ATT_REGISTRATION_ID = "registration-id";
|
||||
|
||||
private static final String ATT_ASSERTING_PARTY_ID = "asserting-party-id";
|
||||
|
||||
private static final String ATT_ENTITY_ID = "entity-id";
|
||||
|
||||
private static final String ATT_METADATA_LOCATION = "metadata-location";
|
||||
|
||||
private static final String ATT_ASSERTION_CONSUMER_SERVICE_LOCATION = "assertion-consumer-service-location";
|
||||
|
||||
private static final String ATT_ASSERTION_CONSUMER_SERVICE_BINDING = "assertion-consumer-service-binding";
|
||||
|
||||
private static final String ATT_PRIVATE_KEY_LOCATION = "private-key-location";
|
||||
|
||||
private static final String ATT_CERTIFICATE_LOCATION = "certificate-location";
|
||||
|
||||
private static final String ATT_WANT_AUTHN_REQUESTS_SIGNED = "want-authn-requests-signed";
|
||||
|
||||
private static final String ATT_SINGLE_SIGN_ON_SERVICE_LOCATION = "single-sign-on-service-location";
|
||||
|
||||
private static final String ATT_SINGLE_SIGN_ON_SERVICE_BINDING = "single-sign-on-service-binding";
|
||||
|
||||
private static final String ATT_SIGNING_ALGORITHMS = "signing-algorithms";
|
||||
|
||||
private static final String ATT_SINGLE_LOGOUT_SERVICE_LOCATION = "single-logout-service-location";
|
||||
|
||||
private static final String ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION = "single-logout-service-response-location";
|
||||
|
||||
private static final String ATT_SINGLE_LOGOUT_SERVICE_BINDING = "single-logout-service-binding";
|
||||
|
||||
private static final ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
|
||||
parserContext.extractSource(element));
|
||||
parserContext.pushContainingComponent(compositeDef);
|
||||
Map<String, Map<String, Object>> assertingParties = getAssertingParties(element);
|
||||
List<RelyingPartyRegistration> relyingPartyRegistrations = getRelyingPartyRegistrations(element,
|
||||
assertingParties, parserContext);
|
||||
BeanDefinition relyingPartyRegistrationRepositoryBean = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(InMemoryRelyingPartyRegistrationRepository.class)
|
||||
.addConstructorArgValue(relyingPartyRegistrations).getBeanDefinition();
|
||||
String relyingPartyRegistrationRepositoryId = parserContext.getReaderContext()
|
||||
.generateBeanName(relyingPartyRegistrationRepositoryBean);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(relyingPartyRegistrationRepositoryBean,
|
||||
relyingPartyRegistrationRepositoryId));
|
||||
parserContext.popAndRegisterContainingComponent();
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Map<String, Map<String, Object>> getAssertingParties(Element element) {
|
||||
List<Element> assertingPartyElts = DomUtils.getChildElementsByTagName(element, ELT_ASSERTING_PARTY);
|
||||
Map<String, Map<String, Object>> providers = new HashMap<>();
|
||||
for (Element assertingPartyElt : assertingPartyElts) {
|
||||
Map<String, Object> assertingParty = new HashMap<>();
|
||||
String assertingPartyId = assertingPartyElt.getAttribute(ATT_ASSERTING_PARTY_ID);
|
||||
String entityId = assertingPartyElt.getAttribute(ATT_ENTITY_ID);
|
||||
String wantAuthnRequestsSigned = assertingPartyElt.getAttribute(ATT_WANT_AUTHN_REQUESTS_SIGNED);
|
||||
String singleSignOnServiceLocation = assertingPartyElt.getAttribute(ATT_SINGLE_SIGN_ON_SERVICE_LOCATION);
|
||||
String singleSignOnServiceBinding = assertingPartyElt.getAttribute(ATT_SINGLE_SIGN_ON_SERVICE_BINDING);
|
||||
String signingAlgorithms = assertingPartyElt.getAttribute(ATT_SIGNING_ALGORITHMS);
|
||||
String singleLogoutServiceLocation = assertingPartyElt.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_LOCATION);
|
||||
String singleLogoutServiceResponseLocation = assertingPartyElt
|
||||
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION);
|
||||
String singleLogoutServiceBinding = assertingPartyElt.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_BINDING);
|
||||
assertingParty.put(ATT_ASSERTING_PARTY_ID, assertingPartyId);
|
||||
assertingParty.put(ATT_ENTITY_ID, entityId);
|
||||
assertingParty.put(ATT_WANT_AUTHN_REQUESTS_SIGNED, wantAuthnRequestsSigned);
|
||||
assertingParty.put(ATT_SINGLE_SIGN_ON_SERVICE_LOCATION, singleSignOnServiceLocation);
|
||||
assertingParty.put(ATT_SINGLE_SIGN_ON_SERVICE_BINDING, singleSignOnServiceBinding);
|
||||
assertingParty.put(ATT_SIGNING_ALGORITHMS, signingAlgorithms);
|
||||
assertingParty.put(ATT_SINGLE_LOGOUT_SERVICE_LOCATION, singleLogoutServiceLocation);
|
||||
assertingParty.put(ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION, singleLogoutServiceResponseLocation);
|
||||
assertingParty.put(ATT_SINGLE_LOGOUT_SERVICE_BINDING, singleLogoutServiceBinding);
|
||||
addVerificationCredentials(assertingPartyElt, assertingParty);
|
||||
addEncryptionCredentials(assertingPartyElt, assertingParty);
|
||||
providers.put(assertingPartyId, assertingParty);
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
private static void addVerificationCredentials(Map<String, Object> assertingParty,
|
||||
RelyingPartyRegistration.AssertingPartyDetails.Builder builder) {
|
||||
List<String> verificationCertificateLocations = (List<String>) assertingParty.get(ELT_VERIFICATION_CREDENTIAL);
|
||||
List<Saml2X509Credential> verificationCredentials = new ArrayList<>();
|
||||
for (String certificateLocation : verificationCertificateLocations) {
|
||||
verificationCredentials.add(getSaml2VerificationCredential(certificateLocation));
|
||||
}
|
||||
builder.verificationX509Credentials((credentials) -> credentials.addAll(verificationCredentials));
|
||||
}
|
||||
|
||||
private static void addEncryptionCredentials(Map<String, Object> assertingParty,
|
||||
RelyingPartyRegistration.AssertingPartyDetails.Builder builder) {
|
||||
List<String> encryptionCertificateLocations = (List<String>) assertingParty.get(ELT_ENCRYPTION_CREDENTIAL);
|
||||
List<Saml2X509Credential> encryptionCredentials = new ArrayList<>();
|
||||
for (String certificateLocation : encryptionCertificateLocations) {
|
||||
encryptionCredentials.add(getSaml2EncryptionCredential(certificateLocation));
|
||||
}
|
||||
builder.encryptionX509Credentials((credentials) -> credentials.addAll(encryptionCredentials));
|
||||
}
|
||||
|
||||
private static void addVerificationCredentials(Element assertingPartyElt, Map<String, Object> assertingParty) {
|
||||
List<String> verificationCertificateLocations = new ArrayList<>();
|
||||
List<Element> verificationCredentialElts = DomUtils.getChildElementsByTagName(assertingPartyElt,
|
||||
ELT_VERIFICATION_CREDENTIAL);
|
||||
for (Element verificationCredentialElt : verificationCredentialElts) {
|
||||
String certificateLocation = verificationCredentialElt.getAttribute(ATT_CERTIFICATE_LOCATION);
|
||||
verificationCertificateLocations.add(certificateLocation);
|
||||
}
|
||||
assertingParty.put(ELT_VERIFICATION_CREDENTIAL, verificationCertificateLocations);
|
||||
}
|
||||
|
||||
private static void addEncryptionCredentials(Element assertingPartyElt, Map<String, Object> assertingParty) {
|
||||
List<String> encryptionCertificateLocations = new ArrayList<>();
|
||||
List<Element> encryptionCredentialElts = DomUtils.getChildElementsByTagName(assertingPartyElt,
|
||||
ELT_VERIFICATION_CREDENTIAL);
|
||||
for (Element encryptionCredentialElt : encryptionCredentialElts) {
|
||||
String certificateLocation = encryptionCredentialElt.getAttribute(ATT_CERTIFICATE_LOCATION);
|
||||
encryptionCertificateLocations.add(certificateLocation);
|
||||
}
|
||||
assertingParty.put(ELT_ENCRYPTION_CREDENTIAL, encryptionCertificateLocations);
|
||||
}
|
||||
|
||||
private List<RelyingPartyRegistration> getRelyingPartyRegistrations(Element element,
|
||||
Map<String, Map<String, Object>> assertingParties, ParserContext parserContext) {
|
||||
List<Element> relyingPartyRegistrationElts = DomUtils.getChildElementsByTagName(element,
|
||||
ELT_RELYING_PARTY_REGISTRATION);
|
||||
List<RelyingPartyRegistration> relyingPartyRegistrations = new ArrayList<>();
|
||||
for (Element relyingPartyRegistrationElt : relyingPartyRegistrationElts) {
|
||||
RelyingPartyRegistration.Builder builder = getBuilderFromMetadataLocationIfPossible(
|
||||
relyingPartyRegistrationElt, assertingParties, parserContext);
|
||||
addSigningCredentials(relyingPartyRegistrationElt, builder);
|
||||
addDecryptionCredentials(relyingPartyRegistrationElt, builder);
|
||||
relyingPartyRegistrations.add(builder.build());
|
||||
}
|
||||
return relyingPartyRegistrations;
|
||||
}
|
||||
|
||||
private static RelyingPartyRegistration.Builder getBuilderFromMetadataLocationIfPossible(
|
||||
Element relyingPartyRegistrationElt, Map<String, Map<String, Object>> assertingParties,
|
||||
ParserContext parserContext) {
|
||||
String registrationId = relyingPartyRegistrationElt.getAttribute(ATT_REGISTRATION_ID);
|
||||
String metadataLocation = relyingPartyRegistrationElt.getAttribute(ATT_METADATA_LOCATION);
|
||||
String singleLogoutServiceLocation = relyingPartyRegistrationElt
|
||||
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_LOCATION);
|
||||
String singleLogoutServiceResponseLocation = relyingPartyRegistrationElt
|
||||
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION);
|
||||
Saml2MessageBinding singleLogoutServiceBinding = getSingleLogoutServiceBinding(relyingPartyRegistrationElt);
|
||||
if (StringUtils.hasText(metadataLocation)) {
|
||||
return RelyingPartyRegistrations.fromMetadataLocation(metadataLocation).registrationId(registrationId)
|
||||
.singleLogoutServiceLocation(singleLogoutServiceLocation)
|
||||
.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation)
|
||||
.singleLogoutServiceBinding(singleLogoutServiceBinding);
|
||||
}
|
||||
String entityId = relyingPartyRegistrationElt.getAttribute(ATT_ENTITY_ID);
|
||||
String assertionConsumerServiceLocation = relyingPartyRegistrationElt
|
||||
.getAttribute(ATT_ASSERTION_CONSUMER_SERVICE_LOCATION);
|
||||
Saml2MessageBinding assertionConsumerServiceBinding = getAssertionConsumerServiceBinding(
|
||||
relyingPartyRegistrationElt);
|
||||
return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(entityId)
|
||||
.assertionConsumerServiceLocation(assertionConsumerServiceLocation)
|
||||
.assertionConsumerServiceBinding(assertionConsumerServiceBinding)
|
||||
.singleLogoutServiceLocation(singleLogoutServiceLocation)
|
||||
.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation)
|
||||
.singleLogoutServiceBinding(singleLogoutServiceBinding)
|
||||
.assertingPartyDetails((builder) -> buildAssertingParty(relyingPartyRegistrationElt, assertingParties,
|
||||
builder, parserContext));
|
||||
}
|
||||
|
||||
private static void buildAssertingParty(Element relyingPartyElt, Map<String, Map<String, Object>> assertingParties,
|
||||
RelyingPartyRegistration.AssertingPartyDetails.Builder builder, ParserContext parserContext) {
|
||||
String assertingPartyId = relyingPartyElt.getAttribute(ATT_ASSERTING_PARTY_ID);
|
||||
if (!assertingParties.containsKey(assertingPartyId)) {
|
||||
Object source = parserContext.extractSource(relyingPartyElt);
|
||||
parserContext.getReaderContext()
|
||||
.error(String.format("Could not find asserting party with id %s", assertingPartyId), source);
|
||||
}
|
||||
Map<String, Object> assertingParty = assertingParties.get(assertingPartyId);
|
||||
String entityId = getAsString(assertingParty, ATT_ENTITY_ID);
|
||||
String wantAuthnRequestsSigned = getAsString(assertingParty, ATT_WANT_AUTHN_REQUESTS_SIGNED);
|
||||
String singleSignOnServiceLocation = getAsString(assertingParty, ATT_SINGLE_SIGN_ON_SERVICE_LOCATION);
|
||||
String singleSignOnServiceBinding = getAsString(assertingParty, ATT_SINGLE_SIGN_ON_SERVICE_BINDING);
|
||||
Saml2MessageBinding saml2MessageBinding = StringUtils.hasText(singleSignOnServiceBinding)
|
||||
? Saml2MessageBinding.valueOf(singleSignOnServiceBinding) : Saml2MessageBinding.REDIRECT;
|
||||
String singleLogoutServiceLocation = getAsString(assertingParty, ATT_SINGLE_LOGOUT_SERVICE_LOCATION);
|
||||
String singleLogoutServiceResponseLocation = getAsString(assertingParty,
|
||||
ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION);
|
||||
String singleLogoutServiceBinding = getAsString(assertingParty, ATT_SINGLE_LOGOUT_SERVICE_BINDING);
|
||||
Saml2MessageBinding saml2LogoutMessageBinding = StringUtils.hasText(singleLogoutServiceBinding)
|
||||
? Saml2MessageBinding.valueOf(singleLogoutServiceBinding) : Saml2MessageBinding.REDIRECT;
|
||||
builder.entityId(entityId).wantAuthnRequestsSigned(Boolean.parseBoolean(wantAuthnRequestsSigned))
|
||||
.singleSignOnServiceLocation(singleSignOnServiceLocation)
|
||||
.singleSignOnServiceBinding(saml2MessageBinding)
|
||||
.singleLogoutServiceLocation(singleLogoutServiceLocation)
|
||||
.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation)
|
||||
.singleLogoutServiceBinding(saml2LogoutMessageBinding);
|
||||
addSigningAlgorithms(assertingParty, builder);
|
||||
addVerificationCredentials(assertingParty, builder);
|
||||
addEncryptionCredentials(assertingParty, builder);
|
||||
}
|
||||
|
||||
private static void addSigningAlgorithms(Map<String, Object> assertingParty,
|
||||
RelyingPartyRegistration.AssertingPartyDetails.Builder builder) {
|
||||
String signingAlgorithmsAttr = getAsString(assertingParty, ATT_SIGNING_ALGORITHMS);
|
||||
if (StringUtils.hasText(signingAlgorithmsAttr)) {
|
||||
List<String> signingAlgorithms = Arrays.asList(signingAlgorithmsAttr.split(","));
|
||||
builder.signingAlgorithms((s) -> s.addAll(signingAlgorithms));
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSigningCredentials(Element relyingPartyRegistrationElt,
|
||||
RelyingPartyRegistration.Builder builder) {
|
||||
List<Element> credentialElts = DomUtils.getChildElementsByTagName(relyingPartyRegistrationElt,
|
||||
ELT_SIGNING_CREDENTIAL);
|
||||
for (Element credentialElt : credentialElts) {
|
||||
String privateKeyLocation = credentialElt.getAttribute(ATT_PRIVATE_KEY_LOCATION);
|
||||
String certificateLocation = credentialElt.getAttribute(ATT_CERTIFICATE_LOCATION);
|
||||
builder.signingX509Credentials(
|
||||
(c) -> c.add(getSaml2SigningCredential(privateKeyLocation, certificateLocation)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void addDecryptionCredentials(Element relyingPartyRegistrationElt,
|
||||
RelyingPartyRegistration.Builder builder) {
|
||||
List<Element> credentialElts = DomUtils.getChildElementsByTagName(relyingPartyRegistrationElt,
|
||||
ELT_DECRYPTION_CREDENTIAL);
|
||||
for (Element credentialElt : credentialElts) {
|
||||
String privateKeyLocation = credentialElt.getAttribute(ATT_PRIVATE_KEY_LOCATION);
|
||||
String certificateLocation = credentialElt.getAttribute(ATT_CERTIFICATE_LOCATION);
|
||||
Saml2X509Credential credential = getSaml2DecryptionCredential(privateKeyLocation, certificateLocation);
|
||||
builder.decryptionX509Credentials((c) -> c.add(credential));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getAsString(Map<String, Object> assertingParty, String key) {
|
||||
return (String) assertingParty.get(key);
|
||||
}
|
||||
|
||||
private static Saml2MessageBinding getAssertionConsumerServiceBinding(Element relyingPartyRegistrationElt) {
|
||||
String assertionConsumerServiceBinding = relyingPartyRegistrationElt
|
||||
.getAttribute(ATT_ASSERTION_CONSUMER_SERVICE_BINDING);
|
||||
if (StringUtils.hasText(assertionConsumerServiceBinding)) {
|
||||
return Saml2MessageBinding.valueOf(assertionConsumerServiceBinding);
|
||||
}
|
||||
return Saml2MessageBinding.REDIRECT;
|
||||
}
|
||||
|
||||
private static Saml2MessageBinding getSingleLogoutServiceBinding(Element relyingPartyRegistrationElt) {
|
||||
String singleLogoutServiceBinding = relyingPartyRegistrationElt.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_BINDING);
|
||||
if (StringUtils.hasText(singleLogoutServiceBinding)) {
|
||||
return Saml2MessageBinding.valueOf(singleLogoutServiceBinding);
|
||||
}
|
||||
return Saml2MessageBinding.POST;
|
||||
}
|
||||
|
||||
private static Saml2X509Credential getSaml2VerificationCredential(String certificateLocation) {
|
||||
return getSaml2Credential(certificateLocation, Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
|
||||
}
|
||||
|
||||
private static Saml2X509Credential getSaml2EncryptionCredential(String certificateLocation) {
|
||||
return getSaml2Credential(certificateLocation, Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
|
||||
}
|
||||
|
||||
private static Saml2X509Credential getSaml2SigningCredential(String privateKeyLocation,
|
||||
String certificateLocation) {
|
||||
return getSaml2Credential(privateKeyLocation, certificateLocation,
|
||||
Saml2X509Credential.Saml2X509CredentialType.SIGNING);
|
||||
}
|
||||
|
||||
private static Saml2X509Credential getSaml2DecryptionCredential(String privateKeyLocation,
|
||||
String certificateLocation) {
|
||||
return getSaml2Credential(privateKeyLocation, certificateLocation,
|
||||
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
|
||||
}
|
||||
|
||||
private static Saml2X509Credential getSaml2Credential(String privateKeyLocation, String certificateLocation,
|
||||
Saml2X509Credential.Saml2X509CredentialType credentialType) {
|
||||
RSAPrivateKey privateKey = readPrivateKey(privateKeyLocation);
|
||||
X509Certificate certificate = readCertificate(certificateLocation);
|
||||
return new Saml2X509Credential(privateKey, certificate, credentialType);
|
||||
}
|
||||
|
||||
private static Saml2X509Credential getSaml2Credential(String certificateLocation,
|
||||
Saml2X509Credential.Saml2X509CredentialType credentialType) {
|
||||
X509Certificate certificate = readCertificate(certificateLocation);
|
||||
return new Saml2X509Credential(certificate, credentialType);
|
||||
}
|
||||
|
||||
private static RSAPrivateKey readPrivateKey(String privateKeyLocation) {
|
||||
Resource privateKey = resourceLoader.getResource(privateKeyLocation);
|
||||
try (InputStream inputStream = privateKey.getInputStream()) {
|
||||
return RsaKeyConverters.pkcs8().convert(inputStream);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static X509Certificate readCertificate(String certificateLocation) {
|
||||
Resource certificate = resourceLoader.getResource(certificateLocation);
|
||||
try (InputStream inputStream = certificate.getInputStream()) {
|
||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(inputStream);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-198
@@ -133,7 +133,6 @@ import org.springframework.security.web.server.authorization.AuthorizationContex
|
||||
import org.springframework.security.web.server.authorization.AuthorizationWebFilter;
|
||||
import org.springframework.security.web.server.authorization.DelegatingReactiveAuthorizationManager;
|
||||
import org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter;
|
||||
import org.springframework.security.web.server.authorization.IpAddressReactiveAuthorizationManager;
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||
import org.springframework.security.web.server.authorization.ServerWebExchangeDelegatingServerAccessDeniedHandler;
|
||||
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
|
||||
@@ -149,12 +148,6 @@ import org.springframework.security.web.server.header.CacheControlServerHttpHead
|
||||
import org.springframework.security.web.server.header.CompositeServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.ContentSecurityPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy;
|
||||
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy;
|
||||
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy;
|
||||
import org.springframework.security.web.server.header.FeaturePolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.HttpHeaderWriterWebFilter;
|
||||
import org.springframework.security.web.server.header.PermissionsPolicyServerHttpHeadersWriter;
|
||||
@@ -1689,18 +1682,6 @@ public class ServerHttpSecurity {
|
||||
return access(AuthenticatedReactiveAuthorizationManager.authenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Require a specific IP address or range using an IP/Netmask (e.g.
|
||||
* 192.168.1.0/24).
|
||||
* @param ipAddress the address or range of addresses from which the request
|
||||
* must come.
|
||||
* @return the {@link AuthorizeExchangeSpec} to configure
|
||||
* @since 5.7
|
||||
*/
|
||||
public AuthorizeExchangeSpec hasIpAddress(String ipAddress) {
|
||||
return access(IpAddressReactiveAuthorizationManager.hasIpAddress(ipAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugging in a custom authorization strategy
|
||||
* @param manager the authorization manager to use
|
||||
@@ -2386,17 +2367,10 @@ public class ServerHttpSecurity {
|
||||
|
||||
private ReferrerPolicyServerHttpHeadersWriter referrerPolicy = new ReferrerPolicyServerHttpHeadersWriter();
|
||||
|
||||
private CrossOriginOpenerPolicyServerHttpHeadersWriter crossOriginOpenerPolicy = new CrossOriginOpenerPolicyServerHttpHeadersWriter();
|
||||
|
||||
private CrossOriginEmbedderPolicyServerHttpHeadersWriter crossOriginEmbedderPolicy = new CrossOriginEmbedderPolicyServerHttpHeadersWriter();
|
||||
|
||||
private CrossOriginResourcePolicyServerHttpHeadersWriter crossOriginResourcePolicy = new CrossOriginResourcePolicyServerHttpHeadersWriter();
|
||||
|
||||
private HeaderSpec() {
|
||||
this.writers = new ArrayList<>(Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts,
|
||||
this.frameOptions, this.xss, this.featurePolicy, this.permissionsPolicy, this.contentSecurityPolicy,
|
||||
this.referrerPolicy, this.crossOriginOpenerPolicy, this.crossOriginEmbedderPolicy,
|
||||
this.crossOriginResourcePolicy));
|
||||
this.referrerPolicy));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2608,84 +2582,6 @@ public class ServerHttpSecurity {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||
* Cross-Origin-Opener-Policy</a> header.
|
||||
* @return the {@link CrossOriginOpenerPolicySpec} to configure
|
||||
* @since 5.7
|
||||
* @see CrossOriginOpenerPolicyServerHttpHeadersWriter
|
||||
*/
|
||||
public CrossOriginOpenerPolicySpec crossOriginOpenerPolicy() {
|
||||
return new CrossOriginOpenerPolicySpec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||
* Cross-Origin-Opener-Policy</a> header.
|
||||
* @return the {@link HeaderSpec} to customize
|
||||
* @since 5.7
|
||||
* @see CrossOriginOpenerPolicyServerHttpHeadersWriter
|
||||
*/
|
||||
public HeaderSpec crossOriginOpenerPolicy(
|
||||
Customizer<CrossOriginOpenerPolicySpec> crossOriginOpenerPolicyCustomizer) {
|
||||
crossOriginOpenerPolicyCustomizer.customize(new CrossOriginOpenerPolicySpec());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||
* Cross-Origin-Embedder-Policy</a> header.
|
||||
* @return the {@link CrossOriginEmbedderPolicySpec} to configure
|
||||
* @since 5.7
|
||||
* @see CrossOriginEmbedderPolicyServerHttpHeadersWriter
|
||||
*/
|
||||
public CrossOriginEmbedderPolicySpec crossOriginEmbedderPolicy() {
|
||||
return new CrossOriginEmbedderPolicySpec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||
* Cross-Origin-Embedder-Policy</a> header.
|
||||
* @return the {@link HeaderSpec} to customize
|
||||
* @since 5.7
|
||||
* @see CrossOriginEmbedderPolicyServerHttpHeadersWriter
|
||||
*/
|
||||
public HeaderSpec crossOriginEmbedderPolicy(
|
||||
Customizer<CrossOriginEmbedderPolicySpec> crossOriginEmbedderPolicyCustomizer) {
|
||||
crossOriginEmbedderPolicyCustomizer.customize(new CrossOriginEmbedderPolicySpec());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||
* Cross-Origin-Resource-Policy</a> header.
|
||||
* @return the {@link CrossOriginResourcePolicySpec} to configure
|
||||
* @since 5.7
|
||||
* @see CrossOriginResourcePolicyServerHttpHeadersWriter
|
||||
*/
|
||||
public CrossOriginResourcePolicySpec crossOriginResourcePolicy() {
|
||||
return new CrossOriginResourcePolicySpec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href=
|
||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||
* Cross-Origin-Resource-Policy</a> header.
|
||||
* @return the {@link HeaderSpec} to customize
|
||||
* @since 5.7
|
||||
* @see CrossOriginResourcePolicyServerHttpHeadersWriter
|
||||
*/
|
||||
public HeaderSpec crossOriginResourcePolicy(
|
||||
Customizer<CrossOriginResourcePolicySpec> crossOriginResourcePolicyCustomizer) {
|
||||
crossOriginResourcePolicyCustomizer.customize(new CrossOriginResourcePolicySpec());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures cache control headers
|
||||
*
|
||||
@@ -3001,99 +2897,6 @@ public class ServerHttpSecurity {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Cross-Origin-Opener-Policy header
|
||||
*
|
||||
* @since 5.7
|
||||
*/
|
||||
public final class CrossOriginOpenerPolicySpec {
|
||||
|
||||
private CrossOriginOpenerPolicySpec() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value to be used in the `Cross-Origin-Opener-Policy` header
|
||||
* @param openerPolicy a opener policy
|
||||
* @return the {@link CrossOriginOpenerPolicySpec} to continue configuring
|
||||
*/
|
||||
public CrossOriginOpenerPolicySpec policy(CrossOriginOpenerPolicy openerPolicy) {
|
||||
HeaderSpec.this.crossOriginOpenerPolicy.setPolicy(openerPolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows method chaining to continue configuring the
|
||||
* {@link ServerHttpSecurity}.
|
||||
* @return the {@link HeaderSpec} to continue configuring
|
||||
*/
|
||||
public HeaderSpec and() {
|
||||
return HeaderSpec.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Cross-Origin-Embedder-Policy header
|
||||
*
|
||||
* @since 5.7
|
||||
*/
|
||||
public final class CrossOriginEmbedderPolicySpec {
|
||||
|
||||
private CrossOriginEmbedderPolicySpec() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value to be used in the `Cross-Origin-Embedder-Policy` header
|
||||
* @param embedderPolicy a opener policy
|
||||
* @return the {@link CrossOriginEmbedderPolicySpec} to continue configuring
|
||||
*/
|
||||
public CrossOriginEmbedderPolicySpec policy(CrossOriginEmbedderPolicy embedderPolicy) {
|
||||
HeaderSpec.this.crossOriginEmbedderPolicy.setPolicy(embedderPolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows method chaining to continue configuring the
|
||||
* {@link ServerHttpSecurity}.
|
||||
* @return the {@link HeaderSpec} to continue configuring
|
||||
*/
|
||||
public HeaderSpec and() {
|
||||
return HeaderSpec.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Cross-Origin-Resource-Policy header
|
||||
*
|
||||
* @since 5.7
|
||||
*/
|
||||
public final class CrossOriginResourcePolicySpec {
|
||||
|
||||
private CrossOriginResourcePolicySpec() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value to be used in the `Cross-Origin-Resource-Policy` header
|
||||
* @param resourcePolicy a opener policy
|
||||
* @return the {@link CrossOriginResourcePolicySpec} to continue configuring
|
||||
*/
|
||||
public CrossOriginResourcePolicySpec policy(CrossOriginResourcePolicy resourcePolicy) {
|
||||
HeaderSpec.this.crossOriginResourcePolicy.setPolicy(resourcePolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows method chaining to continue configuring the
|
||||
* {@link ServerHttpSecurity}.
|
||||
* @return the {@link HeaderSpec} to continue configuring
|
||||
*/
|
||||
public HeaderSpec and() {
|
||||
return HeaderSpec.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -22,7 +22,6 @@ import org.springframework.security.authorization.AuthorizationDecision
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.server.authorization.AuthorizationContext
|
||||
import org.springframework.security.web.server.authorization.IpAddressReactiveAuthorizationManager
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
@@ -109,13 +108,6 @@ class AuthorizeExchangeDsl {
|
||||
fun hasAnyAuthority(vararg authorities: String): ReactiveAuthorizationManager<AuthorizationContext> =
|
||||
AuthorityReactiveAuthorizationManager.hasAnyAuthority<AuthorizationContext>(*authorities)
|
||||
|
||||
/**
|
||||
* Require a specific IP or range of IP addresses.
|
||||
* @since 5.7
|
||||
*/
|
||||
fun hasIpAddress(ipAddress: String): ReactiveAuthorizationManager<AuthorizationContext> =
|
||||
IpAddressReactiveAuthorizationManager.hasIpAddress(ipAddress)
|
||||
|
||||
/**
|
||||
* Require an authenticated user.
|
||||
*/
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.web.server
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Embedder-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.7
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
@ServerSecurityMarker
|
||||
class ServerCrossOriginEmbedderPolicyDsl {
|
||||
|
||||
var policy: CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy? = null
|
||||
|
||||
internal fun get(): (ServerHttpSecurity.HeaderSpec.CrossOriginEmbedderPolicySpec) -> Unit {
|
||||
return { crossOriginEmbedderPolicy ->
|
||||
policy?.also {
|
||||
crossOriginEmbedderPolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.web.server
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Opener-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.7
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
@ServerSecurityMarker
|
||||
class ServerCrossOriginOpenerPolicyDsl {
|
||||
|
||||
var policy: CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy? = null
|
||||
|
||||
internal fun get(): (ServerHttpSecurity.HeaderSpec.CrossOriginOpenerPolicySpec) -> Unit {
|
||||
return { crossOriginOpenerPolicy ->
|
||||
policy?.also {
|
||||
crossOriginOpenerPolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.web.server
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Resource-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.7
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
@ServerSecurityMarker
|
||||
class ServerCrossOriginResourcePolicyDsl {
|
||||
|
||||
var policy: CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy? = null
|
||||
|
||||
internal fun get(): (ServerHttpSecurity.HeaderSpec.CrossOriginResourcePolicySpec) -> Unit {
|
||||
return { crossOriginResourcePolicy ->
|
||||
policy?.also {
|
||||
crossOriginResourcePolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-51
@@ -16,12 +16,7 @@
|
||||
|
||||
package org.springframework.security.config.web.server
|
||||
|
||||
import org.springframework.security.web.server.header.CacheControlServerHttpHeadersWriter
|
||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter
|
||||
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter
|
||||
import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter
|
||||
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter
|
||||
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter
|
||||
import org.springframework.security.web.server.header.*
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [ServerHttpSecurity] headers using idiomatic Kotlin code.
|
||||
@@ -40,9 +35,6 @@ class ServerHeadersDsl {
|
||||
private var referrerPolicy: ((ServerHttpSecurity.HeaderSpec.ReferrerPolicySpec) -> Unit)? = null
|
||||
private var featurePolicyDirectives: String? = null
|
||||
private var permissionsPolicy: ((ServerHttpSecurity.HeaderSpec.PermissionsPolicySpec) -> Unit)? = null
|
||||
private var crossOriginOpenerPolicy: ((ServerHttpSecurity.HeaderSpec.CrossOriginOpenerPolicySpec) -> Unit)? = null
|
||||
private var crossOriginEmbedderPolicy: ((ServerHttpSecurity.HeaderSpec.CrossOriginEmbedderPolicySpec) -> Unit)? = null
|
||||
private var crossOriginResourcePolicy: ((ServerHttpSecurity.HeaderSpec.CrossOriginResourcePolicySpec) -> Unit)? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
@@ -165,39 +157,6 @@ class ServerHeadersDsl {
|
||||
this.permissionsPolicy = ServerPermissionsPolicyDsl().apply(permissionsPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||
* Cross-Origin-Opener-Policy</a> header.
|
||||
*
|
||||
* @since 5.7
|
||||
* @param crossOriginOpenerPolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun crossOriginOpenerPolicy(crossOriginOpenerPolicyConfig: ServerCrossOriginOpenerPolicyDsl.() -> Unit) {
|
||||
this.crossOriginOpenerPolicy = ServerCrossOriginOpenerPolicyDsl().apply(crossOriginOpenerPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||
* Cross-Origin-Embedder-Policy</a> header.
|
||||
*
|
||||
* @since 5.7
|
||||
* @param crossOriginEmbedderPolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun crossOriginEmbedderPolicy(crossOriginEmbedderPolicyConfig: ServerCrossOriginEmbedderPolicyDsl.() -> Unit) {
|
||||
this.crossOriginEmbedderPolicy = ServerCrossOriginEmbedderPolicyDsl().apply(crossOriginEmbedderPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||
* Cross-Origin-Resource-Policy</a> header.
|
||||
*
|
||||
* @since 5.7
|
||||
* @param crossOriginResourcePolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun crossOriginResourcePolicy(crossOriginResourcePolicyConfig: ServerCrossOriginResourcePolicyDsl.() -> Unit) {
|
||||
this.crossOriginResourcePolicy = ServerCrossOriginResourcePolicyDsl().apply(crossOriginResourcePolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables HTTP response headers.
|
||||
*/
|
||||
@@ -235,15 +194,6 @@ class ServerHeadersDsl {
|
||||
referrerPolicy?.also {
|
||||
headers.referrerPolicy(referrerPolicy)
|
||||
}
|
||||
crossOriginOpenerPolicy?.also {
|
||||
headers.crossOriginOpenerPolicy(crossOriginOpenerPolicy)
|
||||
}
|
||||
crossOriginEmbedderPolicy?.also {
|
||||
headers.crossOriginEmbedderPolicy(crossOriginEmbedderPolicy)
|
||||
}
|
||||
crossOriginResourcePolicy?.also {
|
||||
headers.crossOriginResourcePolicy(crossOriginResourcePolicy)
|
||||
}
|
||||
if (disabled) {
|
||||
headers.disable()
|
||||
}
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
|
||||
@@ -38,25 +36,14 @@ abstract class AbstractRequestMatcherDsl {
|
||||
protected data class MatcherAuthorizationRule(val matcher: RequestMatcher,
|
||||
override val rule: String) : AuthorizationRule(rule)
|
||||
|
||||
protected data class MatcherAuthorizationManagerRule(val matcher: RequestMatcher,
|
||||
override val rule: AuthorizationManager<RequestAuthorizationContext>) : AuthorizationManagerRule(rule)
|
||||
|
||||
protected data class PatternAuthorizationRule(val pattern: String,
|
||||
val patternType: PatternType,
|
||||
val servletPath: String? = null,
|
||||
val httpMethod: HttpMethod? = null,
|
||||
override val rule: String) : AuthorizationRule(rule)
|
||||
|
||||
protected data class PatternAuthorizationManagerRule(val pattern: String,
|
||||
val patternType: PatternType,
|
||||
val servletPath: String? = null,
|
||||
val httpMethod: HttpMethod? = null,
|
||||
override val rule: AuthorizationManager<RequestAuthorizationContext>) : AuthorizationManagerRule(rule)
|
||||
|
||||
protected abstract class AuthorizationRule(open val rule: String)
|
||||
|
||||
protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager<RequestAuthorizationContext>)
|
||||
|
||||
protected enum class PatternType {
|
||||
ANT, MVC
|
||||
}
|
||||
|
||||
-260
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.web.servlet
|
||||
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.security.authorization.AuthenticatedAuthorizationManager
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager
|
||||
import org.springframework.security.authorization.AuthorizationDecision
|
||||
import org.springframework.security.authorization.AuthorizationManager
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.access.intercept.AuthorizationFilter
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.util.ClassUtils
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] request authorization using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Yuriy Savchenko
|
||||
* @since 5.7
|
||||
* @property shouldFilterAllDispatcherTypes whether the [AuthorizationFilter] should filter all dispatcher types
|
||||
*/
|
||||
class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
var shouldFilterAllDispatcherTypes: Boolean? = null
|
||||
|
||||
private val authorizationRules = mutableListOf<AuthorizationManagerRule>()
|
||||
|
||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
||||
private val MVC_PRESENT = ClassUtils.isPresent(
|
||||
HANDLER_MAPPING_INTROSPECTOR,
|
||||
AuthorizeHttpRequestsDsl::class.java.classLoader)
|
||||
private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule.
|
||||
*
|
||||
* @param matches the [RequestMatcher] to match incoming requests against
|
||||
* @param access the [AuthorizationManager] to secure the matching request
|
||||
* (i.e. created via hasAuthority("ROLE_USER"))
|
||||
*/
|
||||
fun authorize(matches: RequestMatcher = AnyRequestMatcher.INSTANCE,
|
||||
access: AuthorizationManager<RequestAuthorizationContext>) {
|
||||
authorizationRules.add(MatcherAuthorizationManagerRule(matches, access))
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param access the [AuthorizationManager] to secure the matching request
|
||||
* (i.e. created via hasAuthority("ROLE_USER"))
|
||||
*/
|
||||
fun authorize(pattern: String,
|
||||
access: AuthorizationManager<RequestAuthorizationContext>) {
|
||||
authorizationRules.add(
|
||||
PatternAuthorizationManagerRule(
|
||||
pattern = pattern,
|
||||
patternType = PATTERN_TYPE,
|
||||
rule = access
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param method the HTTP method to match the income requests against.
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param access the [AuthorizationManager] to secure the matching request
|
||||
* (i.e. created via hasAuthority("ROLE_USER"))
|
||||
*/
|
||||
fun authorize(method: HttpMethod,
|
||||
pattern: String,
|
||||
access: AuthorizationManager<RequestAuthorizationContext>) {
|
||||
authorizationRules.add(
|
||||
PatternAuthorizationManagerRule(
|
||||
pattern = pattern,
|
||||
patternType = PATTERN_TYPE,
|
||||
httpMethod = method,
|
||||
rule = access
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param servletPath the servlet path to match incoming requests against. This
|
||||
* only applies when using an MVC pattern matcher.
|
||||
* @param access the [AuthorizationManager] to secure the matching request
|
||||
* (i.e. created via hasAuthority("ROLE_USER"))
|
||||
*/
|
||||
fun authorize(pattern: String,
|
||||
servletPath: String,
|
||||
access: AuthorizationManager<RequestAuthorizationContext>) {
|
||||
authorizationRules.add(
|
||||
PatternAuthorizationManagerRule(
|
||||
pattern = pattern,
|
||||
patternType = PATTERN_TYPE,
|
||||
servletPath = servletPath,
|
||||
rule = access
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param method the HTTP method to match the income requests against.
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param servletPath the servlet path to match incoming requests against. This
|
||||
* only applies when using an MVC pattern matcher.
|
||||
* @param access the [AuthorizationManager] to secure the matching request
|
||||
* (i.e. created via hasAuthority("ROLE_USER"))
|
||||
*/
|
||||
fun authorize(method: HttpMethod,
|
||||
pattern: String,
|
||||
servletPath: String,
|
||||
access: AuthorizationManager<RequestAuthorizationContext>) {
|
||||
authorizationRules.add(
|
||||
PatternAuthorizationManagerRule(
|
||||
pattern = pattern,
|
||||
patternType = PATTERN_TYPE,
|
||||
servletPath = servletPath,
|
||||
httpMethod = method,
|
||||
rule = access
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs require a particular authority.
|
||||
*
|
||||
* @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the [AuthorizationManager] with the provided authority
|
||||
*/
|
||||
fun hasAuthority(authority: String): AuthorizationManager<RequestAuthorizationContext> {
|
||||
return AuthorityAuthorizationManager.hasAuthority(authority)
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs require any of the provided authorities.
|
||||
*
|
||||
* @param authorities the authorities to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the [AuthorizationManager] with the provided authorities
|
||||
*/
|
||||
fun hasAnyAuthority(vararg authorities: String): AuthorizationManager<RequestAuthorizationContext> {
|
||||
return AuthorityAuthorizationManager.hasAnyAuthority(*authorities)
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs require a particular role.
|
||||
*
|
||||
* @param role the role to require (i.e. USER, ADMIN, etc).
|
||||
* @return the [AuthorizationManager] with the provided role
|
||||
*/
|
||||
fun hasRole(role: String): AuthorizationManager<RequestAuthorizationContext> {
|
||||
return AuthorityAuthorizationManager.hasRole(role)
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs require any of the provided roles.
|
||||
*
|
||||
* @param roles the roles to require (i.e. USER, ADMIN, etc).
|
||||
* @return the [AuthorizationManager] with the provided roles
|
||||
*/
|
||||
fun hasAnyRole(vararg roles: String): AuthorizationManager<RequestAuthorizationContext> {
|
||||
return AuthorityAuthorizationManager.hasAnyRole(*roles)
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by anyone.
|
||||
*/
|
||||
val permitAll: AuthorizationManager<RequestAuthorizationContext> =
|
||||
AuthorizationManager { _: Supplier<Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
|
||||
|
||||
/**
|
||||
* Specify that URLs are not allowed by anyone.
|
||||
*/
|
||||
val denyAll: AuthorizationManager<RequestAuthorizationContext> =
|
||||
AuthorizationManager { _: Supplier<Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by any authenticated user.
|
||||
*/
|
||||
val authenticated: AuthorizationManager<RequestAuthorizationContext> =
|
||||
AuthenticatedAuthorizationManager.authenticated()
|
||||
|
||||
internal fun get(): (AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry) -> Unit {
|
||||
return { requests ->
|
||||
authorizationRules.forEach { rule ->
|
||||
when (rule) {
|
||||
is MatcherAuthorizationManagerRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
||||
is PatternAuthorizationManagerRule -> {
|
||||
when (rule.patternType) {
|
||||
PatternType.ANT -> requests.antMatchers(rule.httpMethod, rule.pattern).access(rule.rule)
|
||||
PatternType.MVC -> requests.mvcMatchers(rule.httpMethod, rule.pattern)
|
||||
.apply { if (rule.servletPath != null) servletPath(rule.servletPath) }
|
||||
.access(rule.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
shouldFilterAllDispatcherTypes?.also { shouldFilter ->
|
||||
requests.shouldFilterAllDispatcherTypes(shouldFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -54,7 +54,7 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
@@ -75,7 +75,7 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
@@ -98,7 +98,7 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
@@ -122,7 +122,7 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not on the classpath, it will use an ant matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
@@ -154,7 +154,7 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
fun hasAuthority(authority: String) = "hasAuthority('$authority')"
|
||||
|
||||
/**
|
||||
* Specify that URLs require any number of authorities.
|
||||
* Specify that URLs requires any of a number authorities.
|
||||
*
|
||||
* @param authorities the authorities to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the SpEL expression "hasAnyAuthority" with the given authorities as a
|
||||
@@ -175,7 +175,7 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
fun hasRole(role: String) = "hasRole('$role')"
|
||||
|
||||
/**
|
||||
* Specify that URLs require any number of roles.
|
||||
* Specify that URLs requires any of a number roles.
|
||||
*
|
||||
* @param roles the roles to require (i.e. USER, ADMIN, etc).
|
||||
* @return the SpEL expression "hasAnyRole" with the given roles as a
|
||||
|
||||
@@ -42,9 +42,6 @@ class HeadersDsl {
|
||||
private var referrerPolicy: ((HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit)? = null
|
||||
private var featurePolicyDirectives: String? = null
|
||||
private var permissionsPolicy: ((HeadersConfigurer<HttpSecurity>.PermissionsPolicyConfig) -> Unit)? = null
|
||||
private var crossOriginOpenerPolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginOpenerPolicyConfig) -> Unit)? = null
|
||||
private var crossOriginEmbedderPolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginEmbedderPolicyConfig) -> Unit)? = null
|
||||
private var crossOriginResourcePolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginResourcePolicyConfig) -> Unit)? = null
|
||||
private var disabled = false
|
||||
private var headerWriters = mutableListOf<HeaderWriter>()
|
||||
|
||||
@@ -184,54 +181,6 @@ class HeadersDsl {
|
||||
this.permissionsPolicy = PermissionsPolicyDsl().apply(permissionsPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||
* Cross-Origin-Opener-Policy</a> header.
|
||||
*
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the Cross-Origin-Opener-Policy
|
||||
* header in the response using the supplied policy.
|
||||
* <p>
|
||||
*
|
||||
* @since 5.7
|
||||
* @param crossOriginOpenerPolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun crossOriginOpenerPolicy(crossOriginOpenerPolicyConfig: CrossOriginOpenerPolicyDsl.() -> Unit) {
|
||||
this.crossOriginOpenerPolicy = CrossOriginOpenerPolicyDsl().apply(crossOriginOpenerPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||
* Cross-Origin-Embedder-Policy</a> header.
|
||||
*
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the Cross-Origin-Embedder-Policy
|
||||
* header in the response using the supplied policy.
|
||||
* <p>
|
||||
*
|
||||
* @since 5.7
|
||||
* @param crossOriginEmbedderPolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun crossOriginEmbedderPolicy(crossOriginEmbedderPolicyConfig: CrossOriginEmbedderPolicyDsl.() -> Unit) {
|
||||
this.crossOriginEmbedderPolicy = CrossOriginEmbedderPolicyDsl().apply(crossOriginEmbedderPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||
* Cross-Origin-Resource-Policy</a> header.
|
||||
*
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the Cross-Origin-Resource-Policy
|
||||
* header in the response using the supplied policy.
|
||||
* <p>
|
||||
*
|
||||
* @since 5.7
|
||||
* @param crossOriginResourcePolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun crossOriginResourcePolicy(crossOriginResourcePolicyConfig: CrossOriginResourcePolicyDsl.() -> Unit) {
|
||||
this.crossOriginResourcePolicy = CrossOriginResourcePolicyDsl().apply(crossOriginResourcePolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a [HeaderWriter] instance.
|
||||
*
|
||||
@@ -289,15 +238,6 @@ class HeadersDsl {
|
||||
permissionsPolicy?.also {
|
||||
headers.permissionsPolicy(permissionsPolicy)
|
||||
}
|
||||
crossOriginOpenerPolicy?.also {
|
||||
headers.crossOriginOpenerPolicy(crossOriginOpenerPolicy)
|
||||
}
|
||||
crossOriginEmbedderPolicy?.also {
|
||||
headers.crossOriginEmbedderPolicy(crossOriginEmbedderPolicy)
|
||||
}
|
||||
crossOriginResourcePolicy?.also {
|
||||
headers.crossOriginResourcePolicy(crossOriginResourcePolicy)
|
||||
}
|
||||
headerWriters.forEach { headerWriter ->
|
||||
headers.addHeaderWriter(headerWriter)
|
||||
}
|
||||
|
||||
+6
-70
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -38,8 +38,8 @@ import javax.servlet.http.HttpServletRequest
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* authorizeRequests {
|
||||
* authorize("/public", permitAll)
|
||||
* authorize(anyRequest, authenticated)
|
||||
* request("/public", permitAll)
|
||||
* request(anyRequest, authenticated)
|
||||
* }
|
||||
* formLogin {
|
||||
* loginPage = "/log-in"
|
||||
@@ -50,7 +50,6 @@ import javax.servlet.http.HttpServletRequest
|
||||
* ```
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @author Norbert Nowak
|
||||
* @since 5.3
|
||||
* @param httpConfiguration the configurations to apply to [HttpSecurity]
|
||||
*/
|
||||
@@ -102,10 +101,7 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
||||
fun securityMatcher(vararg pattern: String) {
|
||||
val mvcPresent = ClassUtils.isPresent(
|
||||
HANDLER_MAPPING_INTROSPECTOR,
|
||||
AuthorizeRequestsDsl::class.java.classLoader) ||
|
||||
ClassUtils.isPresent(
|
||||
HANDLER_MAPPING_INTROSPECTOR,
|
||||
AuthorizeHttpRequestsDsl::class.java.classLoader)
|
||||
AuthorizeRequestsDsl::class.java.classLoader)
|
||||
this.http.requestMatchers {
|
||||
if (mvcPresent) {
|
||||
it.mvcMatchers(*pattern)
|
||||
@@ -185,8 +181,8 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* authorizeRequests {
|
||||
* authorize("/public", permitAll)
|
||||
* authorize(anyRequest, authenticated)
|
||||
* request("/public", permitAll)
|
||||
* request(anyRequest, authenticated)
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
@@ -202,38 +198,6 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
||||
this.http.authorizeRequests(authorizeRequestsCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows restricting access based upon the [HttpServletRequest]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig {
|
||||
*
|
||||
* @Bean
|
||||
* fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
* http {
|
||||
* authorizeHttpRequests {
|
||||
* authorize("/public", permitAll)
|
||||
* authorize(anyRequest, authenticated)
|
||||
* }
|
||||
* }
|
||||
* return http.build()
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param authorizeHttpRequestsConfiguration custom configuration that specifies
|
||||
* access for requests
|
||||
* @see [AuthorizeHttpRequestsDsl]
|
||||
* @since 5.7
|
||||
*/
|
||||
fun authorizeHttpRequests(authorizeHttpRequestsConfiguration: AuthorizeHttpRequestsDsl.() -> Unit) {
|
||||
val authorizeHttpRequestsCustomizer = AuthorizeHttpRequestsDsl().apply(authorizeHttpRequestsConfiguration).get()
|
||||
this.http.authorizeHttpRequests(authorizeHttpRequestsCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables HTTP basic authentication.
|
||||
*
|
||||
@@ -906,32 +870,4 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
||||
init()
|
||||
authenticationManager?.also { this.http.authenticationManager(authenticationManager) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables security context configuration.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* securityContext {
|
||||
* securityContextRepository = SECURITY_CONTEXT_REPOSITORY
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @author Norbert Nowak
|
||||
* @since 5.7
|
||||
* @param securityContextConfiguration configuration to be applied to Security Context
|
||||
* @see [SecurityContextDsl]
|
||||
*/
|
||||
fun securityContext(securityContextConfiguration: SecurityContextDsl.() -> Unit) {
|
||||
val securityContextCustomizer = SecurityContextDsl().apply(securityContextConfiguration).get()
|
||||
this.http.securityContext(securityContextCustomizer)
|
||||
}
|
||||
}
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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
|
||||
*
|
||||
* https://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.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer
|
||||
import org.springframework.security.web.context.SecurityContextRepository
|
||||
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] security context using idiomatic Kotlin code.
|
||||
*
|
||||
* @property securityContextRepository the [SecurityContextRepository] used for persisting [org.springframework.security.core.context.SecurityContext] between requests
|
||||
* @author Norbert Nowak
|
||||
* @since 5.7
|
||||
*/
|
||||
@SecurityMarker
|
||||
class SecurityContextDsl {
|
||||
|
||||
var securityContextRepository: SecurityContextRepository? = null
|
||||
var requireExplicitSave: Boolean? = null
|
||||
|
||||
internal fun get(): (SecurityContextConfigurer<HttpSecurity>) -> Unit {
|
||||
return { securityContext ->
|
||||
securityContextRepository?.also { securityContext.securityContextRepository(it) }
|
||||
requireExplicitSave?.also { securityContext.requireExplicitSave(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
import org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Embedder-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.7
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
@HeadersSecurityMarker
|
||||
class CrossOriginEmbedderPolicyDsl {
|
||||
|
||||
var policy: CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy? = null
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.CrossOriginEmbedderPolicyConfig) -> Unit {
|
||||
return { crossOriginEmbedderPolicy ->
|
||||
policy?.also {
|
||||
crossOriginEmbedderPolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Opener-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.7
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
@HeadersSecurityMarker
|
||||
class CrossOriginOpenerPolicyDsl {
|
||||
|
||||
var policy: CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy? = null
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.CrossOriginOpenerPolicyConfig) -> Unit {
|
||||
return { crossOriginOpenerPolicy ->
|
||||
policy?.also {
|
||||
crossOriginOpenerPolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Resource-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.7
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
@HeadersSecurityMarker
|
||||
class CrossOriginResourcePolicyDsl {
|
||||
|
||||
var policy: CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy? = null
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.CrossOriginResourcePolicyConfig) -> Unit {
|
||||
return { crossOriginResourcePolicy ->
|
||||
policy?.also {
|
||||
crossOriginResourcePolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.7.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-5.7.xsd=org/springframework/security/config/spring-security-5.7.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.6.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-5.6.xsd=org/springframework/security/config/spring-security-5.6.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-5.5.xsd=org/springframework/security/config/spring-security-5.5.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-5.4.xsd=org/springframework/security/config/spring-security-5.4.xsd
|
||||
@@ -18,8 +17,7 @@ http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/spri
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
||||
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
||||
https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.7.xsd
|
||||
https\://www.springframework.org/schema/security/spring-security-5.7.xsd=org/springframework/security/config/spring-security-5.7.xsd
|
||||
https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.6.xsd
|
||||
https\://www.springframework.org/schema/security/spring-security-5.6.xsd=org/springframework/security/config/spring-security-5.6.xsd
|
||||
https\://www.springframework.org/schema/security/spring-security-5.5.xsd=org/springframework/security/config/spring-security-5.5.xsd
|
||||
https\://www.springframework.org/schema/security/spring-security-5.4.xsd=org/springframework/security/config/spring-security-5.4.xsd
|
||||
|
||||
-1321
File diff suppressed because it is too large
Load Diff
-3764
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
|
||||
<xsl:variable name="elts-to-inline">
|
||||
<xsl:text>,access-denied-handler,anonymous,session-management,concurrency-control,after-invocation-provider,authentication-provider,ldap-authentication-provider,user,port-mapping,openid-login,saml2-login,saml2-logout,expression-handler,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,add-headers,</xsl:text>
|
||||
<xsl:text>,access-denied-handler,anonymous,session-management,concurrency-control,after-invocation-provider,authentication-provider,ldap-authentication-provider,user,port-mapping,openid-login,expression-handler,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,add-headers,</xsl:text>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:template match="xs:element">
|
||||
|
||||
+5
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -93,8 +93,8 @@ public class AuthenticationManagerBuilderTests {
|
||||
given(opp.postProcess(any())).willAnswer((a) -> a.getArgument(0));
|
||||
AuthenticationManager am = new AuthenticationManagerBuilder(opp).authenticationEventPublisher(aep)
|
||||
.inMemoryAuthentication().and().build();
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
|
||||
() -> am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password")));
|
||||
assertThatExceptionOfType(AuthenticationException.class)
|
||||
.isThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")));
|
||||
verify(aep).publishAuthenticationFailure(any(), any());
|
||||
}
|
||||
|
||||
@@ -103,8 +103,7 @@ public class AuthenticationManagerBuilderTests {
|
||||
this.spring.register(PasswordEncoderGlobalConfig.class).autowire();
|
||||
AuthenticationManager manager = this.spring.getContext().getBean(AuthenticationConfiguration.class)
|
||||
.getAuthenticationManager();
|
||||
Authentication auth = manager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
Authentication auth = manager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
assertThat(auth.getName()).isEqualTo("user");
|
||||
assertThat(auth.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("ROLE_USER");
|
||||
}
|
||||
@@ -114,8 +113,7 @@ public class AuthenticationManagerBuilderTests {
|
||||
this.spring.register(PasswordEncoderGlobalConfig.class).autowire();
|
||||
AuthenticationManager manager = this.spring.getContext().getBean(AuthenticationConfiguration.class)
|
||||
.getAuthenticationManager();
|
||||
Authentication auth = manager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
Authentication auth = manager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
assertThat(auth.getName()).isEqualTo("user");
|
||||
assertThat(auth.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("ROLE_USER");
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -47,8 +47,7 @@ public class AuthenticationConfigurationPublishTests {
|
||||
// gh-4940
|
||||
@Test
|
||||
public void authenticationEventPublisherBeanUsedByDefault() {
|
||||
this.authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
assertThat(this.listener.getEvents()).hasSize(1);
|
||||
}
|
||||
|
||||
|
||||
+16
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -129,8 +129,7 @@ public class AuthenticationConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void getAuthenticationWhenGlobalAuthenticationConfigurerAdapterThenAuthenticates() throws Exception {
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("user",
|
||||
"password");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
|
||||
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class,
|
||||
UserGlobalAuthenticationConfigurerAdapter.class).autowire();
|
||||
AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class)
|
||||
@@ -140,8 +139,7 @@ public class AuthenticationConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void getAuthenticationWhenAuthenticationManagerBeanThenAuthenticates() throws Exception {
|
||||
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated("user",
|
||||
"password");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
|
||||
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class,
|
||||
AuthenticationManagerBeanConfig.class).autowire();
|
||||
AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class)
|
||||
@@ -167,9 +165,9 @@ public class AuthenticationConfigurationTests {
|
||||
config.setGlobalAuthenticationConfigurers(Arrays.asList(new ConfiguresInMemoryConfigurerAdapter(),
|
||||
new BootGlobalAuthenticationConfigurerAdapter()));
|
||||
AuthenticationManager authenticationManager = config.getAuthenticationManager();
|
||||
authenticationManager.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(() -> authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("boot", "password")));
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
|
||||
() -> authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -178,7 +176,7 @@ public class AuthenticationConfigurationTests {
|
||||
AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class);
|
||||
config.setGlobalAuthenticationConfigurers(Arrays.asList(new BootGlobalAuthenticationConfigurerAdapter()));
|
||||
AuthenticationManager authenticationManager = config.getAuthenticationManager();
|
||||
authenticationManager.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("boot", "password"));
|
||||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password"));
|
||||
}
|
||||
|
||||
// gh-2531
|
||||
@@ -208,9 +206,9 @@ public class AuthenticationConfigurationTests {
|
||||
AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class)
|
||||
.getAuthenticationManager();
|
||||
given(uds.loadUserByUsername("user")).willReturn(PasswordEncodedUser.user(), PasswordEncodedUser.user());
|
||||
am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
|
||||
() -> am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "invalid")));
|
||||
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
assertThatExceptionOfType(AuthenticationException.class)
|
||||
.isThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -223,9 +221,9 @@ public class AuthenticationConfigurationTests {
|
||||
.getAuthenticationManager();
|
||||
given(uds.loadUserByUsername("user")).willReturn(User.withUserDetails(user).build(),
|
||||
User.withUserDetails(user).build());
|
||||
am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
|
||||
() -> am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "invalid")));
|
||||
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
assertThatExceptionOfType(AuthenticationException.class)
|
||||
.isThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -239,7 +237,7 @@ public class AuthenticationConfigurationTests {
|
||||
given(manager.loadUserByUsername("user")).willReturn(User.withUserDetails(user).build(),
|
||||
User.withUserDetails(user).build());
|
||||
given(manager.updatePassword(any(), any())).willReturn(user);
|
||||
am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
verify(manager).updatePassword(eq(user), startsWith("{bcrypt}"));
|
||||
}
|
||||
|
||||
@@ -252,7 +250,7 @@ public class AuthenticationConfigurationTests {
|
||||
.getAuthenticationManager();
|
||||
given(ap.supports(any())).willReturn(true);
|
||||
given(ap.authenticate(any())).willReturn(TestAuthentication.authenticatedUser());
|
||||
am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
}
|
||||
|
||||
// gh-3091
|
||||
@@ -264,7 +262,7 @@ public class AuthenticationConfigurationTests {
|
||||
.getAuthenticationManager();
|
||||
given(ap.supports(any())).willReturn(true);
|
||||
given(ap.authenticate(any())).willReturn(TestAuthentication.authenticatedUser());
|
||||
am.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("user", "password"));
|
||||
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -75,21 +75,21 @@ public class Issue50Tests {
|
||||
@Test
|
||||
public void authenticateWhenMissingUserThenUsernameNotFoundException() {
|
||||
assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> this.authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("test", "password")));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("test", "password")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenInvalidPasswordThenBadCredentialsException() {
|
||||
this.userRepo.save(User.withUsernameAndPassword("test", "password"));
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("test", "invalid")));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("test", "invalid")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenValidUserThenAuthenticates() {
|
||||
this.userRepo.save(User.withUsernameAndPassword("test", "password"));
|
||||
Authentication result = this.authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("test", "password"));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("test", "password"));
|
||||
assertThat(result.getName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class Issue50Tests {
|
||||
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("test", null, "ROLE_USER"));
|
||||
this.userRepo.save(User.withUsernameAndPassword("denied", "password"));
|
||||
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> this.authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("test", "password")));
|
||||
.authenticate(new UsernamePasswordAuthenticationToken("test", "password")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -106,8 +106,8 @@ public class GlobalMethodSecurityConfigurationTests {
|
||||
@Test
|
||||
public void methodSecurityAuthenticationManagerPublishesEvent() {
|
||||
this.spring.register(InMemoryAuthWithGlobalMethodSecurityConfig.class).autowire();
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(() -> this.authenticationManager
|
||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("foo", "bar")));
|
||||
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
|
||||
() -> this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("foo", "bar")));
|
||||
assertThat(this.events.getEvents()).extracting(Object::getClass)
|
||||
.containsOnly((Class) AuthenticationFailureBadCredentialsEvent.class);
|
||||
}
|
||||
|
||||
+1
-41
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -20,7 +20,6 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
@@ -33,7 +32,6 @@ import org.springframework.aop.support.JdkRegexpMethodPointcut;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.annotation.AnnotationConfigurationException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
@@ -45,11 +43,9 @@ import org.springframework.security.access.annotation.Jsr250BusinessServiceImpl;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationEventPublisher;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.authorization.method.AuthorizationInterceptorsOrder;
|
||||
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
||||
import org.springframework.security.authorization.method.MethodInvocationResult;
|
||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
@@ -62,9 +58,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link PrePostMethodSecurityConfiguration}.
|
||||
@@ -357,27 +350,6 @@ public class PrePostMethodSecurityConfigurationTests {
|
||||
.isThrownBy(() -> this.businessService.repeatedAnnotations());
|
||||
}
|
||||
|
||||
@WithMockUser
|
||||
@Test
|
||||
public void preAuthorizeWhenAuthorizationEventPublisherThenUses() {
|
||||
this.spring.register(MethodSecurityServiceConfig.class, AuthorizationEventPublisherConfig.class).autowire();
|
||||
assertThatExceptionOfType(AccessDeniedException.class)
|
||||
.isThrownBy(() -> this.methodSecurityService.preAuthorize());
|
||||
AuthorizationEventPublisher publisher = this.spring.getContext().getBean(AuthorizationEventPublisher.class);
|
||||
verify(publisher).publishAuthorizationEvent(any(Supplier.class), any(MethodInvocation.class),
|
||||
any(AuthorizationDecision.class));
|
||||
}
|
||||
|
||||
@WithMockUser
|
||||
@Test
|
||||
public void postAuthorizeWhenAuthorizationEventPublisherThenUses() {
|
||||
this.spring.register(MethodSecurityServiceConfig.class, AuthorizationEventPublisherConfig.class).autowire();
|
||||
this.methodSecurityService.postAnnotation("grant");
|
||||
AuthorizationEventPublisher publisher = this.spring.getContext().getBean(AuthorizationEventPublisher.class);
|
||||
verify(publisher).publishAuthorizationEvent(any(Supplier.class), any(MethodInvocationResult.class),
|
||||
any(AuthorizationDecision.class));
|
||||
}
|
||||
|
||||
// gh-10305
|
||||
@WithMockUser
|
||||
@Test
|
||||
@@ -512,16 +484,4 @@ public class PrePostMethodSecurityConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AuthorizationEventPublisherConfig {
|
||||
|
||||
private final AuthorizationEventPublisher publisher = mock(AuthorizationEventPublisher.class);
|
||||
|
||||
@Bean
|
||||
AuthorizationEventPublisher authorizationEventPublisher() {
|
||||
return this.publisher;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class FilterOrderRegistrationTests {
|
||||
|
||||
@Test
|
||||
public void putWhenPredefinedFilterThenDoesNotOverride() {
|
||||
int position = 300;
|
||||
int position = 100;
|
||||
Integer predefinedFilterOrderBefore = this.filterOrderRegistration.getOrder(ChannelProcessingFilter.class);
|
||||
this.filterOrderRegistration.put(MyFilter.class, position);
|
||||
Integer myFilterOrder = this.filterOrderRegistration.getOrder(MyFilter.class);
|
||||
|
||||
-24
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.security.config.annotation.web.builders;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -27,7 +24,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -36,7 +32,6 @@ import org.springframework.security.config.annotation.authentication.builders.Au
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
@@ -97,15 +92,6 @@ public class WebSecurityTests {
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestRejectedHandlerInvoked() throws ServletException, IOException {
|
||||
loadConfig(RequestRejectedHandlerConfig.class);
|
||||
this.request.setServletPath("/spring");
|
||||
this.request.setRequestURI("/spring/\u0019path");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoringMvcMatcherServletPath() throws Exception {
|
||||
loadConfig(MvcMatcherServletPathConfig.class, LegacyMvcMatchingConfig.class);
|
||||
@@ -237,14 +223,4 @@ public class WebSecurityTests {
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class RequestRejectedHandlerConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.requestRejectedHandler(new HttpStatusRequestRejectedHandler(HttpStatus.BAD_REQUEST.value()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -65,7 +65,7 @@ public class AuthenticationPrincipalArgumentResolverTests {
|
||||
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(
|
||||
UsernamePasswordAuthenticationToken.authenticated(user, user.getPassword(), user.getAuthorities()));
|
||||
new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()));
|
||||
SecurityContextHolder.setContext(context);
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
// @formatter:off
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user