Compare commits
201 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89c815032c | |||
| ff055cf07a | |||
| b08a06aa76 | |||
| 465d80c162 | |||
| 4992e8ce62 | |||
| c772daab92 | |||
| 45a4a89960 | |||
| b43c7e927f | |||
| 50d23622d0 | |||
| 2c2603ba0f | |||
| f7f53ea2b7 | |||
| e0f8c711d8 | |||
| e0843aabb1 | |||
| 26bb60c567 | |||
| c44230ba24 | |||
| 8d2fb6858f | |||
| 7756247c3a | |||
| 3387149a0f | |||
| 8b74bf9742 | |||
| 40abf87ae6 | |||
| 1c014eb512 | |||
| 8c69699458 | |||
| fc10d5fc29 | |||
| c79ebf4edf | |||
| a8d6c1d21f | |||
| 7c7f9380c7 | |||
| 888715bbb2 | |||
| 13feb87171 | |||
| faf9fb7337 | |||
| f33d7253b6 | |||
| db74e9d128 | |||
| 4559d269e0 | |||
| 627809d2dc | |||
| 4b1d7e9479 | |||
| d9980a4dfe | |||
| 8eb7e589eb | |||
| 0d7dce9d71 | |||
| da09788be9 | |||
| ead587c597 | |||
| 02459919cc | |||
| 57d212ddca | |||
| 539b17f6da | |||
| 37e1ad27fe | |||
| 043fdd6f03 | |||
| 3234e05085 | |||
| f957e3c051 | |||
| d66ad22652 | |||
| 7a860e1568 | |||
| 0d3c3c676d | |||
| 0f64d4c091 | |||
| 56a6133b20 | |||
| aaf20e7b61 | |||
| 148756076c | |||
| 6f321a27c4 | |||
| 539443b4be | |||
| 28424f8ae5 | |||
| a7d21f1b34 | |||
| d3a024786b | |||
| 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 |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"index_name": "security-docs",
|
||||
"start_urls": [
|
||||
"https://docs.spring.io/spring-security/reference/"
|
||||
],
|
||||
"selectors": {
|
||||
"lvl0": {
|
||||
"selector": "//nav[@class='crumbs']//li[@class='crumb'][last()-1]",
|
||||
"type": "xpath",
|
||||
"global": true,
|
||||
"default_value": "Home"
|
||||
},
|
||||
"lvl1": ".doc h1",
|
||||
"lvl2": ".doc h2",
|
||||
"lvl3": ".doc h3",
|
||||
"lvl4": ".doc h4",
|
||||
"text": ".doc p, .doc td.content, .doc th.tableblock"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
HOST="$1"
|
||||
HOST_PATH="$2"
|
||||
SSH_PRIVATE_KEY="$3"
|
||||
SSH_KNOWN_HOST="$4"
|
||||
|
||||
|
||||
if [ "$#" -ne 4 ]; then
|
||||
echo -e "not enough arguments USAGE:\n\n$0 \$HOST \$HOST_PATH \$SSH_PRIVATE_KEY \$SSH_KNOWN_HOSTS \n\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use a non-default path to avoid overriding when testing locally
|
||||
SSH_PRIVATE_KEY_PATH=~/.ssh/github-actions-docs
|
||||
install -m 600 -D /dev/null "$SSH_PRIVATE_KEY_PATH"
|
||||
echo "$SSH_PRIVATE_KEY" > "$SSH_PRIVATE_KEY_PATH"
|
||||
echo "$SSH_KNOWN_HOST" > ~/.ssh/known_hosts
|
||||
rsync --delete -avze "ssh -i $SSH_PRIVATE_KEY_PATH" docs/build/site/ "$HOST:$HOST_PATH"
|
||||
rm -f "$SSH_PRIVATE_KEY_PATH"
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
###
|
||||
# Docs
|
||||
# config.json https://docsearch.algolia.com/docs/config-file
|
||||
# Run the crawler https://docsearch.algolia.com/docs/run-your-own/#run-the-crawl-from-the-docker-image
|
||||
|
||||
### USAGE
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo -e "not enough arguments USAGE:\n\n$0 \$ALGOLIA_APPLICATION_ID \$ALGOLIA_API_KEY \$CONFIG_FILE\n\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Script Parameters
|
||||
APPLICATION_ID=$1
|
||||
API_KEY=$2
|
||||
CONFIG_FILE=$3
|
||||
|
||||
#### Script
|
||||
script_dir=$(dirname $0)
|
||||
docker run -e "APPLICATION_ID=$APPLICATION_ID" -e "API_KEY=$API_KEY" -e "CONFIG=$(cat $CONFIG_FILE | jq -r tostring)" algolia/docsearch-scraper
|
||||
@@ -1,20 +0,0 @@
|
||||
name: Update Algolia Index
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 10 * * *' # Once per day at 10am UTC
|
||||
workflow_dispatch: # Manual trigger
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: Update Algolia Index
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v2
|
||||
- name: Update Index
|
||||
run: ${GITHUB_WORKSPACE}/.github/actions/algolia-docsearch-scraper.sh "${{ secrets.ALGOLIA_APPLICATION_ID }}" "${{ secrets.ALGOLIA_WRITE_API_KEY }}" "${GITHUB_WORKSPACE}/.github/actions/algolia-config.json"
|
||||
@@ -1,33 +0,0 @@
|
||||
name: Backport Bot
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
push:
|
||||
branches:
|
||||
- '*.x'
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
- name: Download BackportBot
|
||||
run: wget https://github.com/spring-io/backport-bot/releases/download/latest/backport-bot-0.0.1-SNAPSHOT.jar
|
||||
- name: Backport
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_EVENT: ${{ toJSON(github.event) }}
|
||||
run: java -jar backport-bot-0.0.1-SNAPSHOT.jar --github.accessToken="$GITHUB_TOKEN" --github.event_name "$GITHUB_EVENT_NAME" --github.event "$GITHUB_EVENT"
|
||||
@@ -98,13 +98,15 @@ jobs:
|
||||
- name: Check samples project
|
||||
env:
|
||||
LOCAL_REPOSITORY_PATH: ${{ github.workspace }}/build/publications/repos
|
||||
SAMPLES_INIT_SCRIPT: ${{ github.workspace }}/build/includeRepo/spring-security-ci.gradle
|
||||
SAMPLES_DIR: ../spring-security-samples
|
||||
VERSION: ${{ needs.prerequisites.outputs.project_version }}
|
||||
run: |
|
||||
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
|
||||
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
|
||||
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
|
||||
./gradlew publishMavenJavaPublicationToLocalRepository
|
||||
./gradlew checkSamples -PsamplesInitScript="$SAMPLES_INIT_SCRIPT" -PlocalRepositoryPath="$LOCAL_REPOSITORY_PATH" --stacktrace
|
||||
./gradlew cloneSamples -PcloneOutputDirectory="$SAMPLES_DIR"
|
||||
./gradlew --project-dir "$SAMPLES_DIR" --init-script spring-security-ci.gradle -PlocalRepositoryPath="$LOCAL_REPOSITORY_PATH" -PspringSecurityVersion="$VERSION" :runAllTests
|
||||
check_tangles:
|
||||
name: Check for Package Tangles
|
||||
needs: [ prerequisites ]
|
||||
@@ -269,7 +271,6 @@ jobs:
|
||||
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
|
||||
echo "Updating $REPO@$VERSION to next snapshot version."
|
||||
./gradlew :updateToSnapshotVersion
|
||||
./gradlew :spring-security-docs:antoraUpdateVersion
|
||||
git commit -am "Next development version"
|
||||
git push
|
||||
perform_post_release:
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Build & Deploy Reference
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: request-build-reference
|
||||
schedule:
|
||||
- cron: '0 10 * * *' # Once per day at 10am UTC
|
||||
workflow_dispatch: # Manual trigger
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up gradle
|
||||
uses: spring-io/spring-gradle-build-action@v1
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
- name: Cleanup Gradle Cache
|
||||
# Remove some files from the Gradle cache, so they aren't cached by GitHub Actions.
|
||||
# Restoring these files from a GitHub Actions cache might cause problems for future builds.
|
||||
run: |
|
||||
rm -f /home/runner/.gradle/caches/modules-2/modules-2.lock
|
||||
rm -f /home/runner/.gradle/caches/modules-2/gc.properties
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew :spring-security-docs:antora --stacktrace
|
||||
- name: Deploy
|
||||
run: ${GITHUB_WORKSPACE}/.github/actions/algolia-deploy.sh "${{ secrets.DOCS_USERNAME }}@${{ secrets.DOCS_HOST }}" "/opt/www/domains/spring.io/docs/htdocs/spring-security/reference/" "${{ secrets.DOCS_SSH_KEY }}" "${{ secrets.DOCS_SSH_HOST_KEY }}"
|
||||
@@ -64,7 +64,6 @@ jobs:
|
||||
git config user.name 'github-actions[bot]'
|
||||
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
./gradlew :updateProjectVersion
|
||||
./gradlew :spring-security-docs:antoraUpdateVersion
|
||||
updatedVersion=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}')
|
||||
git commit -am "Release $updatedVersion"
|
||||
git tag $updatedVersion
|
||||
|
||||
+9
-2
@@ -43,9 +43,12 @@ If you're considering anything more than correcting a typo or fixing a minor bug
|
||||
|
||||
If you have not previously done so, please fill out and submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement].
|
||||
|
||||
= Create your branch from main
|
||||
= Create your branch from oldest maintenance branch
|
||||
|
||||
Create your topic branch to be submitted as a pull request from main. The Spring team will consider your pull request for backporting on a case-by-case basis; you don't need to worry about submitting anything for backporting.
|
||||
Create your topic branch to be submitted as a pull request from the oldest impacted and supported maintenance branch.
|
||||
You can find the supported versions by looking at the https://github.com/spring-projects/spring-security/milestones[milestones page].
|
||||
Switch to a branch named `<major>.<minor>.x` from the smallest milestone in the format of `<major>.<minor>.<patch>(-<prerelease>)`.
|
||||
The spring team will ensure the code gets merged forward into additional branches.
|
||||
|
||||
= Use short branch names
|
||||
|
||||
@@ -133,6 +136,10 @@ Search the codebase to find related unit tests and add additional `@Test` method
|
||||
|
||||
Update the https://www.relaxng.org[RELAX NG] schema `spring-security-x.y.rnc` instead of `spring-security-x.y.xsd` if you contribute changes to supported XML configuration. The XML schema file can be generated the following Gradle task:
|
||||
|
||||
----
|
||||
./gradlew :spring-security-config:rncToXsd
|
||||
----
|
||||
|
||||
Changes to the XML schema will be overwritten by the Gradle build task.
|
||||
|
||||
= Squash commits
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+10
-14
@@ -1,13 +1,16 @@
|
||||
import io.spring.gradle.IncludeRepoTask
|
||||
|
||||
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/' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +18,6 @@ apply plugin: 'io.spring.nohttp'
|
||||
apply plugin: 'locks'
|
||||
apply plugin: 's101'
|
||||
apply plugin: 'io.spring.convention.root'
|
||||
apply plugin: 'io.spring.convention.include-check-remote'
|
||||
apply plugin: 'org.jetbrains.kotlin.jvm'
|
||||
apply plugin: 'org.springframework.security.update-dependencies'
|
||||
apply plugin: 'org.springframework.security.update-version'
|
||||
@@ -102,9 +104,9 @@ updateDependenciesSettings {
|
||||
dependencyExcludes {
|
||||
majorVersionBump()
|
||||
minorVersionBump()
|
||||
alphaBetaVersions()
|
||||
releaseCandidatesVersions()
|
||||
milestoneVersions()
|
||||
alphaBetaVersions()
|
||||
snapshotVersions()
|
||||
addRule { components ->
|
||||
components.withModule("commons-codec:commons-codec") { selection ->
|
||||
@@ -200,16 +202,10 @@ nohttp {
|
||||
|
||||
}
|
||||
|
||||
tasks.register('checkSamples') {
|
||||
includeCheckRemote {
|
||||
repository = 'spring-projects/spring-security-samples'
|
||||
ref = samplesBranch
|
||||
if (project.hasProperty("samplesInitScript")) {
|
||||
initScripts = [samplesInitScript]
|
||||
projectProperties = ["localRepositoryPath": localRepositoryPath, "springSecurityVersion": project.version]
|
||||
}
|
||||
}
|
||||
dependsOn checkRemote
|
||||
tasks.register('cloneSamples', IncludeRepoTask) {
|
||||
repository = 'spring-projects/spring-security-samples'
|
||||
ref = samplesBranch
|
||||
outputDirectory = project.hasProperty("cloneOutputDirectory") ? project.file("$cloneOutputDirectory") : project.file("build/samples")
|
||||
}
|
||||
|
||||
s101 {
|
||||
|
||||
@@ -87,7 +87,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.24'
|
||||
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'
|
||||
|
||||
@@ -54,7 +54,7 @@ abstract class IncludeRepoTask extends DefaultTask {
|
||||
* Directory where the project template should be copied.
|
||||
*/
|
||||
@OutputDirectory
|
||||
final File outputDirectory = project.file("$project.buildDir/$name")
|
||||
File outputDirectory = project.file("$project.buildDir/$name")
|
||||
|
||||
@TaskAction
|
||||
void checkoutAndCopy() {
|
||||
|
||||
@@ -1,80 +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 io.spring.gradle.convention
|
||||
|
||||
import io.spring.gradle.IncludeRepoTask
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.GradleBuild
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
|
||||
/**
|
||||
* Adds a set of tasks that make easy to clone a remote repository and perform some task
|
||||
*
|
||||
* @author Marcus Da Coregio
|
||||
*/
|
||||
class IncludeCheckRemotePlugin implements Plugin<Project> {
|
||||
@Override
|
||||
void apply(Project project) {
|
||||
IncludeCheckRemoteExtension extension = project.extensions.create('includeCheckRemote', IncludeCheckRemoteExtension)
|
||||
TaskProvider<IncludeRepoTask> includeRepoTask = project.tasks.register('includeRepo', IncludeRepoTask) { IncludeRepoTask it ->
|
||||
it.repository = extension.repository
|
||||
it.ref = extension.ref
|
||||
}
|
||||
project.tasks.register('checkRemote', GradleBuild) {
|
||||
it.dependsOn 'includeRepo'
|
||||
it.dir = includeRepoTask.get().outputDirectory
|
||||
it.tasks = extension.getTasks()
|
||||
extension.getInitScripts().forEach {script ->
|
||||
it.startParameter.addInitScript(new File(script))
|
||||
}
|
||||
extension.getProjectProperties().entrySet().forEach { entry ->
|
||||
it.startParameter.projectProperties.put(entry.getKey(), entry.getValue())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class IncludeCheckRemoteExtension {
|
||||
|
||||
/**
|
||||
* Git repository to clone
|
||||
*/
|
||||
String repository;
|
||||
|
||||
/**
|
||||
* Git ref to checkout
|
||||
*/
|
||||
String ref
|
||||
|
||||
/**
|
||||
* Task to run in the repository
|
||||
*/
|
||||
List<String> tasks = ['check']
|
||||
|
||||
/**
|
||||
* Init scripts for the build
|
||||
*/
|
||||
List<String> initScripts = []
|
||||
|
||||
/**
|
||||
* Map of properties for the build
|
||||
*/
|
||||
Map<String, String> projectProperties = [:]
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
implementation-class=io.spring.gradle.convention.IncludeCheckRemotePlugin
|
||||
@@ -1,148 +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 io.spring.gradle.convention;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.spring.gradle.IncludeRepoTask;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.GradleBuild;
|
||||
import org.gradle.testfixtures.ProjectBuilder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class IncludeCheckRemotePluginTest {
|
||||
|
||||
Project rootProject;
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() throws Exception {
|
||||
if (rootProject != null) {
|
||||
FileUtils.deleteDirectory(rootProject.getProjectDir());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenExtensionPropertiesNoTasksThenCreateCheckRemoteTaskWithDefaultTask() {
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
|
||||
(includeCheckRemoteExtension) -> {
|
||||
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
|
||||
includeCheckRemoteExtension.setProperty("ref", "main");
|
||||
});
|
||||
|
||||
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
|
||||
assertThat(checkRemote.getTasks()).containsExactly("check");
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenExtensionPropertiesTasksThenCreateCheckRemoteWithProvidedTasks() {
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
|
||||
(includeCheckRemoteExtension) -> {
|
||||
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
|
||||
includeCheckRemoteExtension.setProperty("ref", "main");
|
||||
includeCheckRemoteExtension.setProperty("tasks", Arrays.asList("clean", "build", "test"));
|
||||
});
|
||||
|
||||
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
|
||||
assertThat(checkRemote.getTasks()).containsExactly("clean", "build", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenExtensionPropertiesInitScriptsThenCreateCheckRemoteWithProvidedTasks() {
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
|
||||
(includeCheckRemoteExtension) -> {
|
||||
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
|
||||
includeCheckRemoteExtension.setProperty("ref", "main");
|
||||
includeCheckRemoteExtension.setProperty("initScripts", Arrays.asList("spring-security-ci.gradle"));
|
||||
});
|
||||
|
||||
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
|
||||
assertThat(checkRemote.getStartParameter().getAllInitScripts()).extracting(File::getName).containsExactly("spring-security-ci.gradle");
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenExtensionPropertiesBuildPropertiesThenCreateCheckRemoteWithProvidedTasks() {
|
||||
Map<String, String> projectProperties = new HashMap<>();
|
||||
projectProperties.put("localRepositoryPath", "~/local/repository");
|
||||
projectProperties.put("anotherProperty", "some_value");
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
|
||||
(includeCheckRemoteExtension) -> {
|
||||
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
|
||||
includeCheckRemoteExtension.setProperty("ref", "main");
|
||||
includeCheckRemoteExtension.setProperty("projectProperties", projectProperties);
|
||||
});
|
||||
|
||||
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
|
||||
assertThat(checkRemote.getStartParameter().getProjectProperties()).containsEntry("localRepositoryPath", "~/local/repository")
|
||||
.containsEntry("anotherProperty", "some_value");
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenExtensionPropertiesThenRegisterIncludeRepoTaskWithExtensionProperties() {
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
|
||||
(includeCheckRemoteExtension) -> {
|
||||
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
|
||||
includeCheckRemoteExtension.setProperty("ref", "main");
|
||||
});
|
||||
|
||||
IncludeRepoTask includeRepo = (IncludeRepoTask) this.rootProject.getTasks().named("includeRepo").get();
|
||||
assertThat(includeRepo).isNotNull();
|
||||
assertThat(includeRepo.getRepository().get()).isEqualTo("my-project/my-repository");
|
||||
assertThat(includeRepo.getRef().get()).isEqualTo("main");
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenRegisterTasksThenCheckRemoteDirSameAsIncludeRepoOutputDir() {
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
|
||||
(includeCheckRemoteExtension) -> {
|
||||
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
|
||||
includeCheckRemoteExtension.setProperty("ref", "main");
|
||||
});
|
||||
IncludeRepoTask includeRepo = (IncludeRepoTask) this.rootProject.getTasks().named("includeRepo").get();
|
||||
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
|
||||
assertThat(checkRemote.getDir()).isEqualTo(includeRepo.getOutputDirectory());
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenNoExtensionPropertiesThenRegisterTasks() {
|
||||
this.rootProject = ProjectBuilder.builder().build();
|
||||
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
|
||||
IncludeRepoTask includeRepo = (IncludeRepoTask) this.rootProject.getTasks().named("includeRepo").get();
|
||||
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
|
||||
assertThat(includeRepo).isNotNull();
|
||||
assertThat(checkRemote).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -4,6 +4,7 @@ import java.nio.charset.Charset;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
@@ -636,7 +637,7 @@ public class GitHubMilestoneApiTests {
|
||||
" \"state\":\"open\",\n" +
|
||||
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
|
||||
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
|
||||
" \"due_on\":\"" + Instant.now().toString() + "\",\n" +
|
||||
" \"due_on\":\"" + LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toString() + "\",\n" +
|
||||
" \"closed_at\":null\n" +
|
||||
" }\n" +
|
||||
"]";
|
||||
|
||||
+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'
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs {
|
||||
.ldif("classpath:users.xldif") // ldap-server@ldif
|
||||
.managerDn("uid=admin,ou=system") // ldap-server@manager-dn
|
||||
.managerPassword("secret") // ldap-server@manager-password
|
||||
.port(33399) // ldap-server@port
|
||||
.port(0) // ldap-server@port
|
||||
.root("dc=springframework,dc=org"); // ldap-server@root
|
||||
// .url("ldap://localhost:33389/dc-springframework,dc=org") this overrides root and port and is used for external
|
||||
// @formatter:on
|
||||
|
||||
-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.*");
|
||||
}
|
||||
|
||||
+10
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* 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.
|
||||
@@ -39,6 +39,7 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||
@@ -79,8 +80,7 @@ public class AuthenticationConfiguration {
|
||||
public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor,
|
||||
ApplicationContext context) {
|
||||
LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
|
||||
AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context,
|
||||
AuthenticationEventPublisher.class);
|
||||
AuthenticationEventPublisher authenticationEventPublisher = getAuthenticationEventPublisher(context);
|
||||
DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
objectPostProcessor, defaultPasswordEncoder);
|
||||
if (authenticationEventPublisher != null) {
|
||||
@@ -142,6 +142,13 @@ public class AuthenticationConfiguration {
|
||||
this.objectPostProcessor = objectPostProcessor;
|
||||
}
|
||||
|
||||
private AuthenticationEventPublisher getAuthenticationEventPublisher(ApplicationContext context) {
|
||||
if (context.getBeanNamesForType(AuthenticationEventPublisher.class).length > 0) {
|
||||
return context.getBean(AuthenticationEventPublisher.class);
|
||||
}
|
||||
return this.objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T lazyBean(Class<T> interfaceName) {
|
||||
LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource();
|
||||
|
||||
+11
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -39,19 +39,10 @@ import org.springframework.security.config.annotation.web.servlet.configuration.
|
||||
* @EnableGlobalAuthentication
|
||||
* public class MyGlobalAuthenticationConfiguration {
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* UserDetails admin = User.withDefaultPasswordEncoder()
|
||||
* .username("admin")
|
||||
* .password("password")
|
||||
* .roles("ADMIN", "USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user, admin);
|
||||
* @Autowired
|
||||
* public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
* auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
* .and().withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
@@ -63,24 +54,15 @@ import org.springframework.security.config.annotation.web.servlet.configuration.
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class MyWebSecurityConfiguration {
|
||||
* public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* UserDetails admin = User.withDefaultPasswordEncoder()
|
||||
* .username("admin")
|
||||
* .password("password")
|
||||
* .roles("ADMIN", "USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user, admin);
|
||||
* @Autowired
|
||||
* public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
* auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
* .and().withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* }
|
||||
*
|
||||
* // Possibly more bean methods ...
|
||||
* // Possibly overridden methods ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
|
||||
+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>
|
||||
|
||||
+7
-4
@@ -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.
|
||||
@@ -23,16 +23,19 @@ import org.springframework.security.config.annotation.SecurityBuilder;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
/**
|
||||
* Allows customization to the {@link WebSecurity}. In most instances users will use
|
||||
* {@link EnableWebSecurity} and create a {@link Configuration} that exposes a
|
||||
* {@link SecurityFilterChain} bean. This will automatically be applied to the
|
||||
* {@link WebSecurity} by the {@link EnableWebSecurity} annotation.
|
||||
* {@link EnableWebSecurity} and either create a {@link Configuration} that extends
|
||||
* {@link WebSecurityConfigurerAdapter} or expose a {@link SecurityFilterChain} bean. Both
|
||||
* will automatically be applied to the {@link WebSecurity} by the
|
||||
* {@link EnableWebSecurity} annotation.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @see WebSecurityConfigurerAdapter
|
||||
* @see SecurityFilterChain
|
||||
*/
|
||||
public interface WebSecurityConfigurer<T extends SecurityBuilder<Filter>> extends SecurityConfigurer<Filter, T> {
|
||||
|
||||
-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());
|
||||
|
||||
+406
-779
File diff suppressed because it is too large
Load Diff
+8
-18
@@ -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.
|
||||
@@ -42,6 +42,7 @@ import org.springframework.security.config.annotation.web.AbstractRequestMatcher
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
@@ -76,7 +77,8 @@ import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
*
|
||||
* <p>
|
||||
* Customizations to the {@link WebSecurity} can be made by creating a
|
||||
* {@link WebSecurityConfigurer} or exposing a {@link WebSecurityCustomizer} bean.
|
||||
* {@link WebSecurityConfigurer}, overriding {@link WebSecurityConfigurerAdapter} or
|
||||
* exposing a {@link WebSecurityCustomizer} bean.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
@@ -198,7 +200,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
||||
*
|
||||
* <p>
|
||||
* Typically this method is invoked automatically within the framework from
|
||||
* {@link WebSecurityConfiguration#springSecurityFilterChain()}
|
||||
* {@link WebSecurityConfigurerAdapter#init(WebSecurity)}
|
||||
* </p>
|
||||
* @param securityFilterChainBuilder the builder to use to create the
|
||||
* {@link SecurityFilterChain} instances
|
||||
@@ -256,7 +258,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
||||
|
||||
/**
|
||||
* Sets the {@link FilterSecurityInterceptor}. This is typically invoked by
|
||||
* {@link WebSecurityConfiguration#springSecurityFilterChain()}.
|
||||
* {@link WebSecurityConfigurerAdapter}.
|
||||
* @param securityInterceptor the {@link FilterSecurityInterceptor} to use
|
||||
* @return the {@link WebSecurity} for further customizations
|
||||
* @deprecated Use {@link #privilegeEvaluator(WebInvocationPrivilegeEvaluator)}
|
||||
@@ -278,24 +280,12 @@ 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(),
|
||||
() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
|
||||
+ "Typically this is done by exposing a SecurityFilterChain bean. "
|
||||
+ "Typically this is done by exposing a SecurityFilterChain bean "
|
||||
+ "or by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
|
||||
+ "More advanced users can invoke " + WebSecurity.class.getSimpleName()
|
||||
+ ".addSecurityFilterChainBuilder directly");
|
||||
int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
|
||||
|
||||
+17
-25
@@ -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.
|
||||
@@ -26,56 +26,48 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
/**
|
||||
* Add this annotation to an {@code @Configuration} class to have the Spring Security
|
||||
* configuration defined in any {@link WebSecurityConfigurer} or more likely by exposing a
|
||||
* {@link SecurityFilterChain} bean:
|
||||
* configuration defined in any {@link WebSecurityConfigurer} or more likely by extending
|
||||
* the {@link WebSecurityConfigurerAdapter} base class and overriding individual methods:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class MyWebSecurityConfiguration {
|
||||
* public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Bean
|
||||
* public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
* return (web) -> web.ignoring()
|
||||
* @Override
|
||||
* public void configure(WebSecurity web) throws Exception {
|
||||
* web.ignoring()
|
||||
* // Spring Security should completely ignore URLs starting with /resources/
|
||||
* .antMatchers("/resources/**");
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) throws Exception {
|
||||
* http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
|
||||
* .hasRole("USER").and()
|
||||
* // Possibly more configuration ...
|
||||
* .formLogin() // enable form based log in
|
||||
* // set permitAll for all URLs associated with Form Login
|
||||
* .permitAll();
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("user")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* UserDetails admin = User.withDefaultPasswordEncoder()
|
||||
* .username("admin")
|
||||
* .password("password")
|
||||
* .roles("ADMIN", "USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user, admin);
|
||||
* @Override
|
||||
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* // enable in memory based authentication with a user named "user" and "admin"
|
||||
* .inMemoryAuthentication().withUser("user").password("password").roles("USER")
|
||||
* .and().withUser("admin").password("password").roles("USER", "ADMIN");
|
||||
* }
|
||||
*
|
||||
* // Possibly more bean methods ...
|
||||
* // Possibly more overridden methods ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see WebSecurityConfigurer
|
||||
* @see WebSecurityConfigurerAdapter
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
|
||||
+7
-10
@@ -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,13 @@ 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.AuthenticationEventPublisher;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.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;
|
||||
|
||||
@@ -85,6 +84,7 @@ class HttpSecurityConfiguration {
|
||||
AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||
this.objectPostProcessor, passwordEncoder);
|
||||
authenticationBuilder.parentAuthenticationManager(authenticationManager());
|
||||
authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher());
|
||||
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
|
||||
// @formatter:off
|
||||
http
|
||||
@@ -100,7 +100,6 @@ class HttpSecurityConfiguration {
|
||||
.apply(new DefaultLoginPageConfigurer<>());
|
||||
http.logout(withDefaults());
|
||||
// @formatter:on
|
||||
applyDefaultConfigurers(http);
|
||||
return http;
|
||||
}
|
||||
|
||||
@@ -109,13 +108,11 @@ 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 AuthenticationEventPublisher getAuthenticationEventPublisher() {
|
||||
if (this.context.getBeanNamesForType(AuthenticationEventPublisher.class).length > 0) {
|
||||
return this.context.getBean(AuthenticationEventPublisher.class);
|
||||
}
|
||||
return this.objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
|
||||
}
|
||||
|
||||
private Map<Class<?>, Object> createSharedObjects() {
|
||||
|
||||
+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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-8
@@ -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.
|
||||
@@ -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;
|
||||
@@ -54,9 +55,10 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
|
||||
* based security for Spring Security. It then exports the necessary beans. Customizations
|
||||
* can be made to {@link WebSecurity} by implementing {@link WebSecurityConfigurer} and
|
||||
* exposing it as a {@link Configuration} or exposing a {@link WebSecurityCustomizer}
|
||||
* bean. This configuration is imported when using {@link EnableWebSecurity}.
|
||||
* can be made to {@link WebSecurity} by extending {@link WebSecurityConfigurerAdapter}
|
||||
* and exposing it as a {@link Configuration} or implementing
|
||||
* {@link WebSecurityConfigurer} and exposing it as a {@link Configuration}. This
|
||||
* configuration is imported when using {@link EnableWebSecurity}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Keesun Baik
|
||||
@@ -141,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;
|
||||
@@ -188,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);
|
||||
|
||||
+6
-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.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.http.MediaType;
|
||||
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.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.openid.OpenIDLoginConfigurer;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -306,14 +294,14 @@ public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecur
|
||||
/**
|
||||
* <p>
|
||||
* Specifies the URL to send users to if login is required. If used with
|
||||
* {@link EnableWebSecurity} a default login page will be generated when this
|
||||
* attribute is not specified.
|
||||
* {@link WebSecurityConfigurerAdapter} a default login page will be generated when
|
||||
* this attribute is not specified.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If a URL is specified or this is not being used in conjunction with
|
||||
* {@link EnableWebSecurity}, users are required to process the specified URL to
|
||||
* generate a login page.
|
||||
* {@link WebSecurityConfigurerAdapter}, users are required to process the specified
|
||||
* URL to generate a login page.
|
||||
* </p>
|
||||
*/
|
||||
protected T loginPage(String loginPage) {
|
||||
|
||||
+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();
|
||||
|
||||
+4
-4
@@ -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.
|
||||
@@ -22,7 +22,7 @@ import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
|
||||
@@ -30,7 +30,7 @@ import org.springframework.security.web.csrf.CsrfToken;
|
||||
|
||||
/**
|
||||
* Adds a Filter that will generate a login page if one is not specified otherwise when
|
||||
* using {@link EnableWebSecurity}.
|
||||
* using {@link WebSecurityConfigurerAdapter}.
|
||||
*
|
||||
* <p>
|
||||
* By default an
|
||||
@@ -64,7 +64,7 @@ import org.springframework.security.web.csrf.CsrfToken;
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @see EnableWebSecurity
|
||||
* @see WebSecurityConfigurerAdapter
|
||||
*/
|
||||
public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
extends AbstractHttpConfigurer<DefaultLoginPageConfigurer<H>, H> {
|
||||
|
||||
+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
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
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.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler;
|
||||
@@ -84,15 +84,15 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
/**
|
||||
* <p>
|
||||
* Specifies the URL to send users to if login is required. If used with
|
||||
* {@link EnableWebSecurity} a default login page will be generated when this
|
||||
* attribute is not specified.
|
||||
* {@link WebSecurityConfigurerAdapter} a default login page will be generated when
|
||||
* this attribute is not specified.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If a URL is specified or this is not being used in conjunction with
|
||||
* {@link EnableWebSecurity}, users are required to process the specified URL to
|
||||
* generate a login page. In general, the login page should create a form that submits
|
||||
* a request with the following requirements to work with
|
||||
* {@link WebSecurityConfigurerAdapter}, users are required to process the specified
|
||||
* URL to generate a login page. In general, the login page should create a form that
|
||||
* submits a request with the following requirements to work with
|
||||
* {@link UsernamePasswordAuthenticationFilter}:
|
||||
* </p>
|
||||
*
|
||||
|
||||
+3
-230
@@ -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.
|
||||
@@ -26,14 +26,11 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.security.config.Customizer;
|
||||
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.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
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;
|
||||
@@ -50,7 +47,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* <p>
|
||||
* Adds the Security HTTP headers to the response. Security HTTP headers is activated by
|
||||
* default when using {@link EnableWebSecurity}'s default constructor.
|
||||
* default when using {@link WebSecurityConfigurerAdapter}'s default constructor.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-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,12 +18,12 @@ 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;
|
||||
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.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
@@ -148,10 +148,11 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
/**
|
||||
* Specifies the {@link UserDetailsService} used to look up the {@link UserDetails}
|
||||
* when a remember me token is valid. 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)}.
|
||||
* 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)}.
|
||||
* Alternatively, one can populate {@link #rememberMeServices(RememberMeServices)}.
|
||||
* @param userDetailsService the {@link UserDetailsService} to configure
|
||||
* @return the {@link RememberMeConfigurer} for further customization
|
||||
* @see AbstractRememberMeServices
|
||||
@@ -394,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()
|
||||
@@ -431,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) {
|
||||
|
||||
+4
-26
@@ -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,8 +18,6 @@ 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;
|
||||
@@ -142,7 +140,8 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
/**
|
||||
* Specifies the {@link AuthenticationUserDetailsService} to use. If not specified,
|
||||
* then the {@link UserDetailsService} bean will be used by default.
|
||||
* the shared {@link UserDetailsService} will be used to create a
|
||||
* {@link UserDetailsByNameServiceWrapper}.
|
||||
* @param authenticationUserDetailsService the
|
||||
* {@link AuthenticationUserDetailsService} to use
|
||||
* @return the {@link X509Configurer} for further customizations
|
||||
@@ -201,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;
|
||||
|
||||
+18
-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.
|
||||
@@ -31,7 +31,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.Customizer;
|
||||
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.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer;
|
||||
@@ -61,29 +61,29 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
* <h2>Example Configuration</h2>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class OpenIDLoginConfig {
|
||||
* public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Bean
|
||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) {
|
||||
* http
|
||||
* .authorizeRequests()
|
||||
* .antMatchers("/**").hasRole("USER")
|
||||
* .and()
|
||||
* .openidLogin()
|
||||
* .permitAll();
|
||||
* return http.build();
|
||||
* }
|
||||
*
|
||||
* @Bean
|
||||
* public UserDetailsService userDetailsService() {
|
||||
* UserDetails user = User.withDefaultPasswordEncoder()
|
||||
* .username("https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
|
||||
* .password("password")
|
||||
* .roles("USER")
|
||||
* .build();
|
||||
* return new InMemoryUserDetailsManager(user);
|
||||
* @Override
|
||||
* protected void configure(AuthenticationManagerBuilder auth)(
|
||||
* AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
|
||||
* .password("password")
|
||||
* .roles("USER");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
@@ -229,14 +229,14 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
/**
|
||||
* <p>
|
||||
* Specifies the URL to send users to if login is required. If used with
|
||||
* {@link EnableWebSecurity} a default login page will be generated when this
|
||||
* attribute is not specified.
|
||||
* {@link WebSecurityConfigurerAdapter} a default login page will be generated when
|
||||
* this attribute is not specified.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If a URL is specified or this is not being used in conjunction with
|
||||
* {@link EnableWebSecurity}, users are required to process the specified URL to
|
||||
* generate a login page.
|
||||
* {@link WebSecurityConfigurerAdapter}, users are required to process the specified
|
||||
* URL to generate a login page.
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
|
||||
+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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user