Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ffe73b4920 | |||
| f0ffda89e0 | |||
| 746c6e124e | |||
| 123a2d79cf | |||
| 0c3e483432 | |||
| b804da974d | |||
| b9bb5e0b52 | |||
| 4fd8e1d596 | |||
| c59fb0cd35 | |||
| 50aba3aaf3 | |||
| 6cbbf6c561 | |||
| 10cb6f7003 | |||
| 252c69460e | |||
| 3131642aae | |||
| 552d8d1d29 | |||
| f240f29433 | |||
| 06caf327c1 | |||
| 4cc6687916 | |||
| 108dc5996b | |||
| 8c3453dfd2 | |||
| ce963c744c | |||
| 1efacf1ad8 | |||
| 71a10cef0b | |||
| 784e6efcf5 | |||
| 1caefd748b | |||
| b427587d27 | |||
| 832635c9e8 | |||
| e45258a8bc | |||
| fa7c6ea583 | |||
| 3841e0f6b3 | |||
| 50fad46df6 | |||
| e28eea208b | |||
| f646392542 | |||
| ffeda7a1b3 | |||
| c85e7a0828 | |||
| 14cf90a7b9 | |||
| 729e58b9de | |||
| 5c678bd78a | |||
| 52ca16fa4b | |||
| 31993e72ea | |||
| 0bd3aa9a02 | |||
| dc7edcaf95 | |||
| 310abcf23b | |||
| 5807da104b | |||
| 24e5f2f910 | |||
| 4f8fcea4de | |||
| 659aedbe96 | |||
| d589707385 | |||
| 4734af6856 | |||
| ac09b73725 | |||
| 075c48c0d8 | |||
| 31090f7a18 | |||
| 447e76bd06 | |||
| dfde3295cd | |||
| 32b60e0f26 | |||
| 4b65d1c763 | |||
| ce5e28e3f1 | |||
| 355f6ccc64 | |||
| 20663e2849 | |||
| 41e7af70b5 | |||
| 46a9514420 | |||
| 8432df498e | |||
| 63162eb5f1 | |||
| 5c3b8c513b | |||
| d276c943fc | |||
| 18d9dd77ec | |||
| d3c42a7a4f | |||
| e61c03f7c3 | |||
| 2c97b3376b | |||
| 9273f411c1 | |||
| d6e3ec78cd | |||
| 48c1023fd6 | |||
| 04dbdc8588 | |||
| 6ca04d9b77 | |||
| 3960bf950d | |||
| bc6ac7c8c6 | |||
| 74b93a19f6 | |||
| 6dd6e8ebb1 | |||
| edd82ba82c | |||
| cf656ce6e1 | |||
| f75e9c7138 | |||
| 7cfcfaefae | |||
| f7f5165321 | |||
| 27f91e03f9 | |||
| b7230c367e | |||
| cd72cb1f2e | |||
| a865671526 | |||
| 4f52b71be8 | |||
| 398430f672 | |||
| 03b3b852f5 | |||
| e54bb9f3f5 | |||
| 30be114a5e | |||
| 75121bf455 | |||
| aa21e62fb8 | |||
| b58187082a | |||
| bd3441caac | |||
| 8879aa83a3 | |||
| 1f39a3dd3e | |||
| 84b124d29d | |||
| fee6a9bb0e | |||
| d2ed8321b4 | |||
| dd1f097131 | |||
| 7690c284c0 | |||
| 508b3f26e3 | |||
| f2e674ff77 | |||
| 7fcbf642b8 | |||
| a32d9f04e3 | |||
| 9c449000dc | |||
| 63c99b9438 | |||
| 641d8a362b | |||
| 13f6286e04 | |||
| b77ea8d3a3 | |||
| e9a92a8e9a | |||
| ed774d3595 | |||
| eb5cc89c69 | |||
| d6f8a2e928 | |||
| 6a47b5d573 | |||
| e588a3528f | |||
| 7ea5be4b98 | |||
| 2344fe5ebb | |||
| ba18f681e5 | |||
| 3d9bc6a5cf | |||
| 1d8ea63a9e | |||
| d20c88ecef | |||
| 79815e044e | |||
| 04bba36ee5 | |||
| 5bb99b654f | |||
| 37c15f3b81 | |||
| 0b4dcc4328 | |||
| c09549970f | |||
| e7ba153d5d | |||
| 05518f3402 | |||
| ffa2c195d8 | |||
| 8901fe3d04 | |||
| e1256d1d2f | |||
| 334df75c39 | |||
| 11b601159d | |||
| c77f42e80f | |||
| 8521b7d5a6 | |||
| 7af927ead4 | |||
| 1529a2f5e3 | |||
| beb3c78333 | |||
| f17a07e4c1 | |||
| 687eb4faf6 | |||
| 00fbe052f4 | |||
| 5023cc7e4c | |||
| f4bfa609ae | |||
| 6d6552a602 | |||
| a259e49380 | |||
| d5b135ad0f | |||
| 5ca0d8027d | |||
| ac9c0a4313 | |||
| 8a3e6a8fda | |||
| 811be0a927 | |||
| 40e11752e0 | |||
| bc8d630bbc | |||
| 861c60a28f | |||
| 3cd8dc5c44 | |||
| 97342f83fd | |||
| dfe062b390 | |||
| 703a81390e | |||
| 0514ee4cc5 | |||
| 18c4c4c528 | |||
| 9fd6d54268 | |||
| 3f04f42abb | |||
| f585461427 | |||
| a155c035e1 | |||
| 6d722edab1 | |||
| e712531555 | |||
| 100c07de98 | |||
| 9095a1bffd | |||
| 279afe3e28 |
@@ -17,7 +17,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
deploy-artifacts:
|
||||
name: Deploy Artifacts
|
||||
needs: [ build]
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||
default-publish-milestones-central: true
|
||||
@@ -38,14 +38,14 @@ jobs:
|
||||
deploy-schema:
|
||||
name: Deploy Schema
|
||||
needs: [ build ]
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||
secrets: inherit
|
||||
perform-release:
|
||||
name: Perform Release
|
||||
needs: [ deploy-artifacts, deploy-schema ]
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
|
||||
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
|
||||
@@ -61,6 +61,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Notification
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
if: github.repository_owner == 'spring-projects'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: docs-build
|
||||
fetch-depth: 1
|
||||
|
||||
@@ -19,14 +19,14 @@ jobs:
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Set up Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
uses: gradle/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # v5.0.1
|
||||
- name: Upgrade Wrappers
|
||||
run: ./gradlew clean upgradeGradleWrapperAll --continue -Porg.gradle.java.installations.auto-download=false
|
||||
env:
|
||||
|
||||
@@ -30,6 +30,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Notification
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||
|
||||
@@ -11,9 +11,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Set up gradle
|
||||
uses: spring-io/spring-gradle-build-action@v2
|
||||
uses: spring-io/spring-gradle-build-action@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
@@ -24,9 +24,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Set up gradle
|
||||
uses: spring-io/spring-gradle-build-action@v2
|
||||
uses: spring-io/spring-gradle-build-action@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora
|
||||
- name: Upload Docs
|
||||
id: upload
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: docs
|
||||
path: docs/build/site
|
||||
@@ -46,6 +46,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Notification
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Dispatch
|
||||
|
||||
@@ -16,9 +16,9 @@ jobs:
|
||||
name: Update on Supported Branches
|
||||
strategy:
|
||||
matrix:
|
||||
branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
|
||||
branch: [ '6.4.x', '6.5.x', 'main' ]
|
||||
steps:
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf
|
||||
name: Update
|
||||
with:
|
||||
docs-branch: ${{ matrix.branch }}
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Update on docs-build
|
||||
steps:
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf
|
||||
name: Update
|
||||
with:
|
||||
docs-branch: 'docs-build'
|
||||
|
||||
@@ -9,7 +9,7 @@ permissions:
|
||||
jobs:
|
||||
update-scheduled-release-version:
|
||||
name: Update Scheduled Release Version
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
secrets: inherit
|
||||
send-notification:
|
||||
name: Send Notification
|
||||
@@ -18,6 +18,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Notification
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||
with:
|
||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||
+1
-1
@@ -39,7 +39,7 @@ interface EvaluationContextPostProcessor<I> {
|
||||
* that was passed in.
|
||||
* @param context the original {@link EvaluationContext}
|
||||
* @param invocation the security invocation object (i.e. Message)
|
||||
* @return the upated context.
|
||||
* @return the updated context.
|
||||
*/
|
||||
EvaluationContext postProcess(EvaluationContext context, I invocation);
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import org.springframework.security.acls.model.Acl;
|
||||
|
||||
/**
|
||||
* Strategy used by {@link AclImpl} to determine whether a principal is permitted to call
|
||||
* adminstrative methods on the <code>AclImpl</code>.
|
||||
* administrative methods on the <code>AclImpl</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
|
||||
@@ -42,7 +42,7 @@ public class GrantedAuthoritySid implements Sid {
|
||||
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
|
||||
Assert.notNull(grantedAuthority, "GrantedAuthority required");
|
||||
Assert.notNull(grantedAuthority.getAuthority(),
|
||||
"This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
|
||||
"This Sid is only compatible with GrantedAuthority that provide a non-null getAuthority()");
|
||||
this.grantedAuthority = grantedAuthority.getAuthority();
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ public class JdbcAclService implements AclService {
|
||||
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
|
||||
}
|
||||
else {
|
||||
log.debug("Find children statement has already been overridden, so not overridding the default");
|
||||
log.debug("Find children statement has already been overridden, so not overriding the default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ import org.springframework.util.Assert;
|
||||
* The default settings are for HSQLDB. If you are using a different database you will
|
||||
* probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and
|
||||
* {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The
|
||||
* other queries, SQL inserts and updates can also be customized to accomodate schema
|
||||
* other queries, SQL inserts and updates can also be customized to accommodate schema
|
||||
* variations, but must produce results consistent with those expected by the defaults.
|
||||
* <p>
|
||||
* See the appendix of the Spring Security reference manual for more information on the
|
||||
@@ -471,7 +471,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
|
||||
}
|
||||
else {
|
||||
log.debug("Insert class statement has already been overridden, so not overridding the default");
|
||||
log.debug("Insert class statement has already been overridden, so not overriding the default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ apply plugin: 'io.spring.convention.spring-module'
|
||||
apply plugin: 'io.freefair.aspectj'
|
||||
|
||||
compileAspectj {
|
||||
sourceCompatibility "17"
|
||||
targetCompatibility "17"
|
||||
sourceCompatibility = "17"
|
||||
targetCompatibility = "17"
|
||||
}
|
||||
compileTestAspectj {
|
||||
sourceCompatibility "17"
|
||||
targetCompatibility "17"
|
||||
sourceCompatibility = "17"
|
||||
targetCompatibility = "17"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
+9
-36
@@ -10,7 +10,7 @@ buildscript {
|
||||
classpath libs.com.netflix.nebula.nebula.project.plugin
|
||||
}
|
||||
repositories {
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
maven { url='https://plugins.gradle.org/m2/' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ ext.milestoneBuild = !(snapshotBuild || releaseBuild)
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url = "https://repo.spring.io/milestone" }
|
||||
}
|
||||
|
||||
springRelease {
|
||||
@@ -46,46 +46,19 @@ springRelease {
|
||||
replaceSnapshotVersionInReferenceDocUrl = true
|
||||
}
|
||||
|
||||
def toolchainVersion() {
|
||||
if (project.hasProperty('testToolchain')) {
|
||||
return project.property('testToolchain').toString().toInteger()
|
||||
}
|
||||
return 17
|
||||
}
|
||||
|
||||
subprojects {
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(toolchainVersion())
|
||||
}
|
||||
}
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
}
|
||||
}
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = "UTF-8"
|
||||
options.compilerArgs.add("-parameters")
|
||||
options.release.set(17)
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
if (!['spring-security-bom', 'spring-security-docs'].contains(project.name)) {
|
||||
apply plugin: 'io.spring.javaformat'
|
||||
apply plugin: 'checkstyle'
|
||||
|
||||
pluginManager.withPlugin("io.spring.convention.checkstyle", { plugin ->
|
||||
configure(plugin) {
|
||||
dependencies {
|
||||
checkstyle libs.io.spring.javaformat.spring.javaformat.checkstyle
|
||||
}
|
||||
checkstyle {
|
||||
toolVersion = '8.34'
|
||||
}
|
||||
pluginManager.withPlugin("io.spring.convention.checkstyle") {
|
||||
dependencies {
|
||||
checkstyle libs.io.spring.javaformat.spring.javaformat.checkstyle
|
||||
}
|
||||
})
|
||||
checkstyle {
|
||||
toolVersion = '8.34'
|
||||
}
|
||||
}
|
||||
|
||||
if (project.name.contains('sample')) {
|
||||
tasks.whenTaskAdded { task ->
|
||||
|
||||
@@ -12,7 +12,7 @@ java {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven { url 'https://repo.spring.io/snapshot' }
|
||||
maven { url = 'https://repo.spring.io/snapshot' }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
BIN
Binary file not shown.
@@ -1,5 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
Vendored
-240
@@ -1,240 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original 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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
-91
@@ -1,91 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2004-present the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -81,8 +81,8 @@ class ArtifactoryPlugin implements Plugin<Project> {
|
||||
repository {
|
||||
repoKey = isSnapshot ? snapshotRepository : isMilestone ? milestoneRepository : releaseRepository
|
||||
if(project.hasProperty('artifactoryUsername')) {
|
||||
username = artifactoryUsername
|
||||
password = artifactoryPassword
|
||||
username = project.artifactoryUsername
|
||||
password = project.artifactoryPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ public class DocsPlugin implements Plugin<Project> {
|
||||
into 'api'
|
||||
}
|
||||
into 'docs'
|
||||
duplicatesStrategy 'exclude'
|
||||
duplicatesStrategy = 'exclude'
|
||||
}
|
||||
|
||||
Task docs = project.tasks.create("docs") {
|
||||
group = 'Documentation'
|
||||
description 'An aggregator task to generate all the documentation'
|
||||
description = 'An aggregator task to generate all the documentation'
|
||||
dependsOn docsZip
|
||||
}
|
||||
project.tasks.assemble.dependsOn docs
|
||||
|
||||
@@ -90,7 +90,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
||||
project.plugins.withType(IdeaPlugin) {
|
||||
project.idea {
|
||||
module {
|
||||
testSourceDirs += project.file('src/integration-test/java')
|
||||
testSources.from(project.file('src/integration-test/java'))
|
||||
scopes.TEST.plus += [ project.configurations.integrationTestCompileClasspath ]
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
||||
project.plugins.withType(IdeaPlugin) {
|
||||
project.idea {
|
||||
module {
|
||||
testSourceDirs += project.file('src/integration-test/groovy')
|
||||
testSources.from(project.file('src/integration-test/groovy'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.gradle.api.Action;
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.javadoc.Javadoc;
|
||||
import org.slf4j.Logger;
|
||||
@@ -71,7 +71,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
api.setMaxMemory("1024m");
|
||||
api.setDestinationDir(new File(project.getBuildDir(), "api"));
|
||||
api.setDestinationDir(project.layout.getBuildDirectory().dir("api").get().getAsFile());
|
||||
|
||||
project.getPluginManager().apply("io.spring.convention.javadoc-options");
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
|
||||
public void execute(SpringModulePlugin plugin) {
|
||||
logger.info("Added sources for {}", project);
|
||||
|
||||
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
|
||||
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
|
||||
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
|
||||
|
||||
api.setSource(api.getSource().plus(mainSourceSet.getAllJava()));
|
||||
|
||||
@@ -40,7 +40,7 @@ public class SchemaZipPlugin implements Plugin<Project> {
|
||||
throw new IllegalStateException("Could not find schema file for resource name " + schemaResourceName + " in src/main/resources")
|
||||
}
|
||||
schemaZip.into (shortName) {
|
||||
duplicatesStrategy 'exclude'
|
||||
duplicatesStrategy = 'exclude'
|
||||
from xsdFile.path
|
||||
}
|
||||
versionlessXsd.getInputFiles().from(xsdFile.path)
|
||||
|
||||
@@ -35,6 +35,7 @@ class SpringModulePlugin extends AbstractSpringJavaPlugin {
|
||||
pluginManager.apply(SpringMavenPlugin.class);
|
||||
pluginManager.apply(CheckClasspathForProhibitedDependenciesPlugin.class);
|
||||
pluginManager.apply("io.spring.convention.jacoco");
|
||||
pluginManager.apply("java-toolchain");
|
||||
|
||||
def deployArtifacts = project.task("deployArtifacts")
|
||||
deployArtifacts.group = 'Deploy tasks'
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
def toolchainVersion() {
|
||||
if (project.hasProperty('testToolchain')) {
|
||||
return project.property('testToolchain').toString().toInteger()
|
||||
}
|
||||
return 17
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(toolchainVersion())
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = "UTF-8"
|
||||
options.compilerArgs.add("-parameters")
|
||||
options.release = 17
|
||||
}
|
||||
|
||||
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion = JavaLanguageVersion.of(toolchainVersion())
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(KotlinCompile).configureEach {
|
||||
compilerOptions {
|
||||
javaParameters = true
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,7 +326,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
/**
|
||||
* Use this {@code RequestMatcher} to match proxy receptor requests. Without setting
|
||||
* this matcher, {@link CasAuthenticationFilter} will not capture any proxy receptor
|
||||
* requets.
|
||||
* requests.
|
||||
* @param proxyReceptorMatcher the {@link RequestMatcher} to use
|
||||
* @since 6.5
|
||||
*/
|
||||
@@ -383,8 +383,8 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the request is elgible to process a service ticket. This method exists
|
||||
* for readability.
|
||||
* Indicates if the request is eligible to process a service ticket. This method
|
||||
* exists for readability.
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
@@ -396,7 +396,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the request is elgible to process a proxy ticket.
|
||||
* Indicates if the request is eligible to process a proxy ticket.
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@@ -419,7 +419,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the request is elgible to be processed as the proxy receptor.
|
||||
* Indicates if the request is eligible to be processed as the proxy receptor.
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -144,14 +144,14 @@ tasks.named('processResources', ProcessResources).configure {
|
||||
into 'org/springframework/security/config/'
|
||||
}
|
||||
from(rncToXsd) {
|
||||
duplicatesStrategy DuplicatesStrategy.EXCLUDE
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
into 'org/springframework/security/config/'
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('sourcesJar', Jar).configure {
|
||||
from(rncToXsd) {
|
||||
duplicatesStrategy DuplicatesStrategy.EXCLUDE
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
into 'org/springframework/security/config/'
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -177,7 +177,7 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a shared Object. Note that object heirarchies are not considered.
|
||||
* Gets a shared Object. Note that object hierarchies are not considered.
|
||||
* @param sharedType the type of the shared Object
|
||||
* @return the shared Object or null if it is not found
|
||||
*/
|
||||
@@ -360,7 +360,7 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to build the object that is being returned.
|
||||
* @return the Object to be buit or null if the implementation allows it
|
||||
* @return the Object to be built or null if the implementation allows it
|
||||
*/
|
||||
protected abstract O performBuild();
|
||||
|
||||
@@ -414,13 +414,13 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
||||
private enum BuildState {
|
||||
|
||||
/**
|
||||
* This is the state before the {@link Builder#build()} is invoked
|
||||
* This is the state before the {@link SecurityBuilder#build()} is invoked
|
||||
*/
|
||||
UNBUILT(0),
|
||||
|
||||
/**
|
||||
* The state from when {@link Builder#build()} is first invoked until all the
|
||||
* {@link SecurityConfigurer#init(SecurityBuilder)} methods have been invoked.
|
||||
* The state from when {@link SecurityBuilder#build()} is first invoked until all
|
||||
* the {@link SecurityConfigurer#init(SecurityBuilder)} methods have been invoked.
|
||||
*/
|
||||
INITIALIZING(1),
|
||||
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>>
|
||||
<C> void setSharedObject(Class<C> sharedType, C object);
|
||||
|
||||
/**
|
||||
* Gets a shared Object. Note that object heirarchies are not considered.
|
||||
* Gets a shared Object. Note that object hierarchies are not considered.
|
||||
* @param sharedType the type of the shared Object
|
||||
* @return the shared Object or null if it is not found
|
||||
*/
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ final class FilterOrderRegistration {
|
||||
/**
|
||||
* Register a {@link Filter} with its specific position. If the {@link Filter} was
|
||||
* already registered before, the position previously defined is not going to be
|
||||
* overriden
|
||||
* overridden
|
||||
* @param filter the {@link Filter} to register
|
||||
* @param position the position to associate with the {@link Filter}
|
||||
*/
|
||||
|
||||
+1
-1
@@ -305,7 +305,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the logoutSuccesUrl or null if a
|
||||
* Gets the logoutSuccessUrl or null if a
|
||||
* {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured.
|
||||
* @return the logoutSuccessUrl
|
||||
*/
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
|
||||
/**
|
||||
* This should not use RequestAttributeSecurityContextRepository since that is
|
||||
* stateless and sesison management is about state management.
|
||||
* stateless and session management is about state management.
|
||||
*/
|
||||
private SecurityContextRepository sessionManagementSecurityContextRepository = new HttpSessionSecurityContextRepository();
|
||||
|
||||
|
||||
+3
-34
@@ -16,14 +16,9 @@
|
||||
|
||||
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
import com.nimbusds.jose.proc.SecurityContext;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -45,7 +40,6 @@ import org.springframework.security.oauth2.server.authorization.token.OAuth2Toke
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for the OAuth 2.0 Configurers.
|
||||
@@ -207,41 +201,16 @@ final class OAuth2ConfigurerUtils {
|
||||
}
|
||||
|
||||
static <T> T getBean(HttpSecurity httpSecurity, Class<T> type) {
|
||||
return httpSecurity.getSharedObject(ApplicationContext.class).getBean(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T getBean(HttpSecurity httpSecurity, ResolvableType type) {
|
||||
ApplicationContext context = httpSecurity.getSharedObject(ApplicationContext.class);
|
||||
String[] names = context.getBeanNamesForType(type);
|
||||
if (names.length == 1) {
|
||||
return (T) context.getBean(names[0]);
|
||||
}
|
||||
if (names.length > 1) {
|
||||
throw new NoUniqueBeanDefinitionException(type, names);
|
||||
}
|
||||
throw new NoSuchBeanDefinitionException(type);
|
||||
return httpSecurity.getSharedObject(ApplicationContext.class).getBeanProvider(type).getObject();
|
||||
}
|
||||
|
||||
static <T> T getOptionalBean(HttpSecurity httpSecurity, Class<T> type) {
|
||||
Map<String, T> beansMap = BeanFactoryUtils
|
||||
.beansOfTypeIncludingAncestors(httpSecurity.getSharedObject(ApplicationContext.class), type);
|
||||
if (beansMap.size() > 1) {
|
||||
throw new NoUniqueBeanDefinitionException(type, beansMap.size(),
|
||||
"Expected single matching bean of type '" + type.getName() + "' but found " + beansMap.size() + ": "
|
||||
+ StringUtils.collectionToCommaDelimitedString(beansMap.keySet()));
|
||||
}
|
||||
return (!beansMap.isEmpty() ? beansMap.values().iterator().next() : null);
|
||||
return httpSecurity.getSharedObject(ApplicationContext.class).getBeanProvider(type).getIfUnique();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T getOptionalBean(HttpSecurity httpSecurity, ResolvableType type) {
|
||||
ApplicationContext context = httpSecurity.getSharedObject(ApplicationContext.class);
|
||||
String[] names = context.getBeanNamesForType(type);
|
||||
if (names.length > 1) {
|
||||
throw new NoUniqueBeanDefinitionException(type, names);
|
||||
}
|
||||
return (names.length == 1) ? (T) context.getBean(names[0]) : null;
|
||||
return (T) httpSecurity.getSharedObject(ApplicationContext.class).getBeanProvider(type).getIfUnique();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class Saml2MetadataConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
* If there is no {@code registrationId} and your
|
||||
* {@link RelyingPartyRegistrationRepository} is {code Iterable}, the metadata
|
||||
* endpoint will try and show all relying parties' metadata in a single
|
||||
* {@code <md:EntitiesDecriptor} element.
|
||||
* {@code <md:EntitiesDescriptor} element.
|
||||
*
|
||||
* <p>
|
||||
* If you need a more sophisticated lookup strategy than these, use
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ class ServerHttpSecurityConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all {@code Custmizer<ServerHttpSecurity>} Beans to
|
||||
* Applies all {@code Customizer<ServerHttpSecurity>} Beans to
|
||||
* {@link ServerHttpSecurity}.
|
||||
* @param context the {@link ApplicationContext}
|
||||
* @param http the {@link ServerHttpSecurity}
|
||||
|
||||
+3
-3
@@ -538,7 +538,7 @@ final class AuthenticationConfigBuilder {
|
||||
}
|
||||
injectAuthenticationDetailsSource(x509Elt, filterBuilder);
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
createPrauthEntryPoint(x509Elt);
|
||||
createPreauthEntryPoint(x509Elt);
|
||||
createX509Provider();
|
||||
}
|
||||
this.x509Filter = filter;
|
||||
@@ -562,7 +562,7 @@ final class AuthenticationConfigBuilder {
|
||||
this.x509ProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
|
||||
}
|
||||
|
||||
private void createPrauthEntryPoint(Element source) {
|
||||
private void createPreauthEntryPoint(Element source) {
|
||||
if (this.preAuthEntryPoint == null) {
|
||||
this.preAuthEntryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
|
||||
this.preAuthEntryPoint.setSource(this.pc.extractSource(source));
|
||||
@@ -595,7 +595,7 @@ final class AuthenticationConfigBuilder {
|
||||
adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
|
||||
filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
|
||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||
createPrauthEntryPoint(jeeElt);
|
||||
createPreauthEntryPoint(jeeElt);
|
||||
createJeeProvider();
|
||||
}
|
||||
this.jeeFilter = filter;
|
||||
|
||||
+3
-3
@@ -165,20 +165,20 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
private RootBeanDefinition getRootBeanDefinition(String mode) {
|
||||
if (isUnboundidEnabled(mode)) {
|
||||
if (isUnboundIdEnabled(mode)) {
|
||||
return new RootBeanDefinition(UNBOUNDID_CONTAINER_CLASSNAME, null, null);
|
||||
}
|
||||
throw new IllegalStateException("Embedded LDAP server is not provided");
|
||||
}
|
||||
|
||||
private String resolveBeanId(String mode) {
|
||||
if (isUnboundidEnabled(mode)) {
|
||||
if (isUnboundIdEnabled(mode)) {
|
||||
return BeanIds.EMBEDDED_UNBOUNDID;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isUnboundidEnabled(String mode) {
|
||||
private boolean isUnboundIdEnabled(String mode) {
|
||||
return "unboundid".equals(mode) || unboundIdPresent;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1340,7 +1340,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
||||
static class ServletPathConfig {
|
||||
|
||||
@Bean
|
||||
PathPatternRequestMatcherBuilderFactoryBean requesMatcherBuilder() {
|
||||
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
|
||||
PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
bean.setBasePath("/spring");
|
||||
return bean;
|
||||
|
||||
+38
@@ -45,6 +45,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -158,6 +159,8 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
|
||||
private static AuthenticationFailureHandler authenticationFailureHandler;
|
||||
|
||||
private static PasswordEncoder passwordEncoder;
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
@@ -183,6 +186,9 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
authenticationProvidersConsumer = mock(Consumer.class);
|
||||
authenticationSuccessHandler = mock(AuthenticationSuccessHandler.class);
|
||||
authenticationFailureHandler = mock(AuthenticationFailureHandler.class);
|
||||
passwordEncoder = mock(PasswordEncoder.class);
|
||||
given(passwordEncoder.matches(any(), any())).willReturn(true);
|
||||
given(passwordEncoder.upgradeEncoding(any())).willReturn(false);
|
||||
db = new EmbeddedDatabaseBuilder().generateUniqueName(true)
|
||||
.setType(EmbeddedDatabaseType.HSQL)
|
||||
.setScriptEncoding("UTF-8")
|
||||
@@ -496,6 +502,26 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
.andExpect(jsonPath("$.token_type").value(OAuth2AccessToken.TokenType.DPOP.getValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenTokenRequestWithMultiplePasswordEncodersThenPrimaryPasswordEncoderUsed() throws Exception {
|
||||
this.spring.register(AuthorizationServerConfigurationWithMultiplePasswordEncoders.class).autowire();
|
||||
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
this.registeredClientRepository.save(registeredClient);
|
||||
|
||||
this.mvc
|
||||
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI)
|
||||
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||
.param(OAuth2ParameterNames.SCOPE, "scope1 scope2")
|
||||
.header(HttpHeaders.AUTHORIZATION,
|
||||
"Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret())))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.access_token").isNotEmpty())
|
||||
.andExpect(jsonPath("$.scope").value("scope1 scope2"));
|
||||
|
||||
verify(passwordEncoder).matches(any(), any());
|
||||
}
|
||||
|
||||
private static String generateDPoPProof(String tokenEndpointUri) {
|
||||
// @formatter:off
|
||||
Map<String, Object> publicJwk = TestJwks.DEFAULT_EC_JWK
|
||||
@@ -658,4 +684,16 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class AuthorizationServerConfigurationWithMultiplePasswordEncoders extends AuthorizationServerConfiguration {
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
PasswordEncoder primaryPasswordEncoder() {
|
||||
return passwordEncoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ public interface SecurityExpressionOperations {
|
||||
boolean isAnonymous();
|
||||
|
||||
/**
|
||||
* Determines ifthe {@link #getAuthentication()} is authenticated
|
||||
* Determines if the {@link #getAuthentication()} is authenticated
|
||||
* @return true if the {@link #getAuthentication()} is authenticated, else false
|
||||
*/
|
||||
boolean isAuthenticated();
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ public class DefaultSecurityParameterNameDiscoverer extends PrioritizedParameter
|
||||
annotationClassesToUse.add(DATA_PARAM_CLASSNAME);
|
||||
}
|
||||
addDiscoverer(new AnnotationParameterNameDiscoverer(annotationClassesToUse));
|
||||
addDiscoverer(new DefaultParameterNameDiscoverer());
|
||||
addDiscoverer(DefaultParameterNameDiscoverer.getSharedInstance());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ urls:
|
||||
redirect_facility: httpd
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.18/ui-bundle.zip
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.25/ui-bundle.zip
|
||||
snapshot: true
|
||||
runtime:
|
||||
log:
|
||||
|
||||
@@ -77,7 +77,7 @@ Public Clients are supported using https://tools.ietf.org/html/rfc7636[Proof Key
|
||||
If the client is running in an untrusted environment (eg. native application or web browser-based application) and therefore incapable of maintaining the confidentiality of it's credentials, PKCE will automatically be used when the following conditions are true:
|
||||
|
||||
. `client-secret` is omitted (or empty)
|
||||
. `client-authentication-method` is set to "none" (`ClientAuthenticationMethod.NONE`)
|
||||
. `client-authentication-method` is set to `none` (`ClientAuthenticationMethod.NONE`)
|
||||
|
||||
or
|
||||
|
||||
@@ -85,7 +85,7 @@ or
|
||||
|
||||
[TIP]
|
||||
====
|
||||
If the OAuth 2.0 Provider supports PKCE for https://tools.ietf.org/html/rfc6749#section-2.1[Confidential Clients], you may (optionally) configure it using `DefaultServerOAuth2AuthorizationRequestResolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce())`.
|
||||
If the OAuth 2.0 Provider doesn't support PKCE for https://tools.ietf.org/html/rfc6749#section-2.1[Confidential Clients], you need to disable it by setting `ClientRegistration.clientSettings.requireProofKey` to `false`.
|
||||
====
|
||||
|
||||
[[oauth2-client-authorization-code-redirect-uri]]
|
||||
|
||||
@@ -68,7 +68,7 @@ The name may be used in certain scenarios, such as when displaying the name of t
|
||||
<15> `(userInfoEndpoint)authenticationMethod`: The authentication method used when sending the access token to the UserInfo Endpoint.
|
||||
The supported values are *header*, *form* and *query*.
|
||||
<16> `userNameAttributeName`: The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.
|
||||
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `authorizationGrantType` is `none`, then PKCE will be enabled by default.
|
||||
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `clientAuthenticationMethod` is `none`, then PKCE will be enabled. Defaults to `true` for `authorization_code` grant type and `false` for other grant types.
|
||||
|
||||
A `ClientRegistration` can be initially configured using discovery of an OpenID Connect Provider's https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Configuration endpoint] or an Authorization Server's https://tools.ietf.org/html/rfc8414#section-3[Metadata endpoint].
|
||||
|
||||
|
||||
@@ -414,7 +414,7 @@ If you build your project with Maven, adding the appropriate Spring Security mod
|
||||
Any that are marked as "`optional`" in the Spring Security `pom.xml` files have to be added to your own `pom.xml` file if you need them.
|
||||
|
||||
[[appendix-faq-unboundid-deps]]
|
||||
=== What dependences are needed to run an embedded UnboundID LDAP server?
|
||||
=== What dependencies are needed to run an embedded UnboundID LDAP server?
|
||||
|
||||
You need to add the following dependency to your project:
|
||||
|
||||
|
||||
@@ -137,7 +137,8 @@ fun method(authentication: Authentication?): String {
|
||||
will always return "not anonymous", even for anonymous requests.
|
||||
The reason is that Spring MVC resolves the parameter using `HttpServletRequest#getPrincipal`, which is `null` when the request is anonymous.
|
||||
|
||||
If you'd like to obtain the `Authentication` in anonymous requests, use `@CurrentSecurityContext` instead:
|
||||
If you'd like to obtain the `Authentication` in anonymous requests, use
|
||||
xref:servlet/integrations/mvc.adoc#mvc-current-security-context[`@CurrentSecurityContext`] instead:
|
||||
|
||||
.Use CurrentSecurityContext for Anonymous requests
|
||||
[tabs]
|
||||
|
||||
@@ -97,7 +97,11 @@ val authorities = authentication.authorities
|
||||
----
|
||||
======
|
||||
|
||||
// FIXME: Add links to and relevant description of HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal
|
||||
In Spring MVC, you can resolve the current principal with
|
||||
xref:servlet/integrations/mvc.adoc#mvc-authentication-principal[`@AuthenticationPrincipal`]
|
||||
and the full `SecurityContext` with
|
||||
xref:servlet/integrations/mvc.adoc#mvc-current-security-context[`@CurrentSecurityContext`].
|
||||
For Servlet API access, use `HttpServletRequest#getRemoteUser`.
|
||||
|
||||
By default, `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread, even if the `SecurityContext` is not explicitly passed around as an argument to those methods.
|
||||
Using a `ThreadLocal` in this way is quite safe if you take care to clear the thread after the present principal's request is processed.
|
||||
|
||||
@@ -12,7 +12,7 @@ OWASP places factors into the following categories:
|
||||
== `FactorGrantedAuthority`
|
||||
|
||||
At the time of authentication, Spring Security's authentication mechanisms add a javadoc:org.springframework.security.core.authority.FactorGrantedAuthority[].
|
||||
For example, when a user authenticates using a password a `FactorGrantedAuthority` with the `authority` of `FactorGrantedAuthority.PASSWORD_AUTHORITY` is automatically added to the `Authentiation`.
|
||||
For example, when a user authenticates using a password a `FactorGrantedAuthority` with the `authority` of `FactorGrantedAuthority.PASSWORD_AUTHORITY` is automatically added to the `Authentication`.
|
||||
In order to require MFA with Spring Security you must:
|
||||
|
||||
- Specify an authorization rule that requires multiple factors
|
||||
@@ -51,7 +51,7 @@ include-code::./UseAuthorizationManagerFactoryConfiguration[tag=authorizationMan
|
||||
[[selective-mfa]]
|
||||
== Selectively Requiring MFA
|
||||
|
||||
We have demonstrated how to configure an entire application to require MFA by using xref:./mfa.adoc#emfa[`@EnableMultiFactorAuthentication`]s `authorities` property.
|
||||
We have demonstrated how to configure an entire application to require MFA by using xref:./mfa.adoc#emfa[``@EnableMultiFactorAuthentication``s] `authorities` property.
|
||||
However, there are times that an application only wants parts of the application to require MFA.
|
||||
Consider the following requirements:
|
||||
|
||||
@@ -118,7 +118,7 @@ To enable the MFA rules globally, we can publish an `AuthorizationManagerFactory
|
||||
|
||||
include-code::./AdminMfaAuthorizationManagerConfiguration[tag=authorizationManagerFactory,indent=0]
|
||||
<1> Inject the custom `AuthorizationManager` as the javadoc:org.springframework.security.authorization.DefaultAuthorizationManagerFactory#setAdditionalAuthorization(org.springframework.security.authorization.AuthorizationManager)[DefaultAuthorization.additionalAuthorization].
|
||||
This instructs `DefaultAuthorizationManagerFactory` that any authorization rule should apply our custom `AuthorizationManager` along with any authorization requirements defined by the application (e.g. `hasRole("ADMIN")).
|
||||
This instructs `DefaultAuthorizationManagerFactory` that any authorization rule should apply our custom `AuthorizationManager` along with any authorization requirements defined by the application (e.g. `hasRole("ADMIN")`).
|
||||
<2> Publish `DefaultAuthorizationManagerFactory` as a Bean, so it is used globally
|
||||
|
||||
This should feel very similar to our previous example in xref:./mfa.adoc#authorization-manager-factory[].
|
||||
@@ -153,10 +153,11 @@ Next we can define an `AuthorizationManagerFactory` that uses the `RequiredAutho
|
||||
|
||||
include-code::./RequiredAuthoritiesAuthorizationManagerConfiguration[tag=authorizationManagerFactory,indent=0]
|
||||
<1> Inject the `RequiredAuthoritiesAuthorizationManager` as the javadoc:org.springframework.security.authorization.DefaultAuthorizationManagerFactory#setAdditionalAuthorization(org.springframework.security.authorization.AuthorizationManager)[DefaultAuthorization.additionalAuthorization].
|
||||
This instructs `DefaultAuthorizationManagerFactory` that any authorization rule should apply `RequiredAuthoritiesAuthorizationManager` along with any authorization requirements defined by the application (e.g. `hasRole("ADMIN")).
|
||||
This instructs `DefaultAuthorizationManagerFactory` that any authorization rule should apply `RequiredAuthoritiesAuthorizationManager` along with any authorization requirements defined by the application (e.g. `hasRole("ADMIN")`).
|
||||
<2> Publish `DefaultAuthorizationManagerFactory` as a Bean, so it is used globally
|
||||
|
||||
We can now define our authorization rules which are combined with `RequiredAuthoritiesAuthorizationManager`.
|
||||
|
||||
include-code::./RequiredAuthoritiesAuthorizationManagerConfiguration[tag=httpSecurity,indent=0]
|
||||
<1> URLs that begin with `/admin/**` require `ROLE_ADMIN`.
|
||||
If the username is `admin`, then `FACTOR_OTT` and `FACTOR_PASSWORD` are also required.
|
||||
@@ -167,7 +168,7 @@ Our example uses an in memory mapping of usernames to the additional required au
|
||||
For more dynamic use cases that can be determined by the username, a custom implementation of javadoc:org.springframework.security.authorization.RequiredAuthoritiesRepository[] can be created.
|
||||
Possible examples would be looking up if a user has enabled MFA in an explicit setting, determining if a user has registered a passkey, etc.
|
||||
|
||||
For cases that need to determine MFA based upon the `Authentication`, a custom `AuthorizationManger` can be used as demonstrated in xref:./mfa.adoc#programmatic-mfa[]
|
||||
For cases that need to determine MFA based upon the `Authentication`, a custom `AuthorizationManger` can be used as demonstrated in xref:./mfa.adoc#programmatic-mfa[].
|
||||
|
||||
|
||||
[[hasallauthorities]]
|
||||
@@ -196,7 +197,7 @@ Can you imagine what it would be like to declare hundreds of rules like this?
|
||||
What's more that it becomes difficult to express more complicated authorization rules.
|
||||
For example, how would you require two factors and either `ROLE_ADMIN` or `ROLE_USER`?
|
||||
|
||||
The answer to these questions, as we have already seen, is to use xref:./mfa.adoc#egmfa[]
|
||||
The answer to these questions, as we have already seen, is to use xref:./mfa.adoc#emfa[]
|
||||
|
||||
[[re-authentication]]
|
||||
== Re-authentication
|
||||
@@ -211,7 +212,7 @@ By default, this application has two authentication mechanisms that it allows, m
|
||||
If there is a set of endpoints that require a specific factor, we can specify that in `authorizeHttpRequests` as follows:
|
||||
|
||||
include-code::./RequireOttConfiguration[tag=httpSecurity,indent=0]
|
||||
<1> - States that all `/profile/**` endpoints require one-time-token login to be authorized
|
||||
<1> States that all `/profile/**` endpoints require one-time-token login to be authorized
|
||||
|
||||
Given the above configuration, users can log in with any mechanism that you support.
|
||||
And, if they want to visit the profile page, then Spring Security will redirect them to the One-Time-Token Login page to obtain it.
|
||||
|
||||
@@ -24,7 +24,7 @@ The `RequestCache` is typically a `NullRequestCache` that does not save the requ
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The default HTTP Basic Auth Provider will suppress both Response body and `WWW-Authenticate` header in the 401 response when the request was made with a `X-Requested-By: XMLHttpRequest` header.
|
||||
The default HTTP Basic Auth Provider will suppress both Response body and `WWW-Authenticate` header in the 401 response when the request was made with a `X-Requested-With: XMLHttpRequest` header.
|
||||
This allows frontends to implement their own authentication code, instead of triggering the browser login dialog.
|
||||
To override, implement your own javadoc:org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint[].
|
||||
====
|
||||
|
||||
@@ -107,7 +107,7 @@ default void verify(Supplier<Authentication> authentication, Object secureObject
|
||||
}
|
||||
----
|
||||
|
||||
The ``AuthorizationManager``'s `check` method is passed all the relevant information it needs in order to make an authorization decision.
|
||||
The ``AuthorizationManager``'s `authorize` method is passed all the relevant information it needs in order to make an authorization decision.
|
||||
In particular, passing the secure `Object` enables those arguments contained in the actual secure object invocation to be inspected.
|
||||
For example, let's assume the secure object was a `MethodInvocation`.
|
||||
It would be easy to query the `MethodInvocation` for any `Customer` argument, and then implement some sort of security logic in the `AuthorizationManager` to ensure the principal is permitted to operate on that customer.
|
||||
|
||||
@@ -118,7 +118,7 @@ A given invocation to `MyCustomerService#readCustomer` may look something like t
|
||||
image::{figures}/methodsecurity.png[]
|
||||
|
||||
1. Spring AOP invokes its proxy method for `readCustomer`. Among the proxy's other advisors, it invokes an javadoc:org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor[] that matches <<annotation-method-pointcuts,the `@PreAuthorize` pointcut>>
|
||||
2. The interceptor invokes javadoc:org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager[`PreAuthorizeAuthorizationManager#check`]
|
||||
2. The interceptor invokes javadoc:org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager[`PreAuthorizeAuthorizationManager#authorize`]
|
||||
3. The authorization manager uses a `MethodSecurityExpressionHandler` to parse the annotation's <<authorization-expressions,SpEL expression>> and constructs a corresponding `EvaluationContext` from a `MethodSecurityExpressionRoot` containing xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[a `Supplier<Authentication>`] and `MethodInvocation`.
|
||||
4. The interceptor uses this context to evaluate the expression; specifically, it reads xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[the `Authentication`] from the `Supplier` and checks whether it has `permission:read` in its collection of xref:servlet/authorization/architecture.adoc#authz-authorities[authorities]
|
||||
5. If the evaluation passes, then Spring AOP proceeds to invoke the method.
|
||||
|
||||
@@ -399,7 +399,7 @@ Second, each xref:#httpsecuritydsl-bean[HttpSecurityDsl.() -> Unit Beans] is app
|
||||
This means that if there are multiple `HttpSecurity.() -> Unit` Beans, the https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/annotation/Order.html[@Order] annotation can be added to the Bean definitions to control the ordering.
|
||||
|
||||
Next, every xref:#top-level-dsl-bean[Top Level Security Dsl Beans] type is looked up and each is is applied using `ObjectProvider#orderedStream()`.
|
||||
If there is are differt types of top level security Beans (.e.g. `HeadersDsl.() -> Unit` and `HttpsRedirectDsl.() -> Unit`), then the order that each Dsl type is invoked is undefined.
|
||||
If there is are different types of top level security Beans (.e.g. `HeadersDsl.() -> Unit` and `HttpsRedirectDsl.() -> Unit`), then the order that each Dsl type is invoked is undefined.
|
||||
However, the order that each instance of of the same top level security Bean type is defined by `ObjectProvider#orderedStream()` and can be controlled using `@Order` on the Bean the definitions.
|
||||
|
||||
Finally, the `HttpSecurityDsl` Bean is injected as a Bean.
|
||||
|
||||
@@ -448,6 +448,72 @@ open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndV
|
||||
----
|
||||
======
|
||||
|
||||
[[mvc-current-security-context]]
|
||||
== @CurrentSecurityContext
|
||||
|
||||
Spring Security provides `CurrentSecurityContextArgumentResolver`, which can automatically resolve the current `SecurityContext` for Spring MVC arguments.
|
||||
By using `@EnableWebSecurity`, you automatically have this added to your Spring MVC configuration.
|
||||
If you use XML-based configuration, you must add this yourself:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<mvc:annotation-driven>
|
||||
<mvc:argument-resolvers>
|
||||
<bean class="org.springframework.security.web.method.annotation.CurrentSecurityContextArgumentResolver" />
|
||||
</mvc:argument-resolvers>
|
||||
</mvc:annotation-driven>
|
||||
----
|
||||
|
||||
Once `CurrentSecurityContextArgumentResolver` is configured, you can access the `SecurityContext` directly:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
public String me(@CurrentSecurityContext SecurityContext context) {
|
||||
return context.getAuthentication().getName();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
fun me(@CurrentSecurityContext context: SecurityContext): String {
|
||||
return context.authentication.name
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can also use a SpEL expression that is rooted at the `SecurityContext`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
public String me(@CurrentSecurityContext(expression = "authentication") Authentication authentication) {
|
||||
return authentication.getName();
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@GetMapping("/me")
|
||||
fun me(@CurrentSecurityContext(expression = "authentication") authentication: Authentication): String {
|
||||
return authentication.name
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[[mvc-async]]
|
||||
== Spring MVC Async Integration
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ spring:
|
||||
Public Clients are supported by using https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE).
|
||||
If the client is running in an untrusted environment (such as a native application or web browser-based application) and is therefore incapable of maintaining the confidentiality of its credentials, PKCE is automatically used when the following conditions are true:
|
||||
|
||||
. `client-secret` is omitted (or empty) and
|
||||
. `client-secret` is omitted (or empty)
|
||||
. `client-authentication-method` is set to `none` (`ClientAuthenticationMethod.NONE`)
|
||||
|
||||
or
|
||||
@@ -87,7 +87,7 @@ or
|
||||
|
||||
[TIP]
|
||||
====
|
||||
If the OAuth 2.0 Provider supports PKCE for https://tools.ietf.org/html/rfc6749#section-2.1[Confidential Clients], you may (optionally) configure it using `DefaultOAuth2AuthorizationRequestResolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce())`.
|
||||
If the OAuth 2.0 Provider doesn't support PKCE for https://tools.ietf.org/html/rfc6749#section-2.1[Confidential Clients], you need to disable it by setting `ClientRegistration.clientSettings.requireProofKey` to `false`.
|
||||
====
|
||||
|
||||
[[oauth2-client-authorization-code-redirect-uri]]
|
||||
|
||||
@@ -69,7 +69,7 @@ This information is available only if the Spring Boot property `spring.security.
|
||||
<15> `(userInfoEndpoint)authenticationMethod`: The authentication method used when sending the access token to the UserInfo Endpoint.
|
||||
The supported values are *header*, *form*, and *query*.
|
||||
<16> `userNameAttributeName`: The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.
|
||||
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `clientAuthenticationMethod` is `none`, then PKCE will be enabled.
|
||||
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `clientAuthenticationMethod` is `none`, then PKCE will be enabled. Defaults to `true` for `authorization_code` grant type and `false` for other grant types.
|
||||
|
||||
You can initially configure a `ClientRegistration` by using discovery of an OpenID Connect Provider's https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Configuration endpoint] or an Authorization Server's https://tools.ietf.org/html/rfc8414#section-3[Metadata endpoint].
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
|
||||
id 'io.spring.convention.repository'
|
||||
id 'security-kotlin'
|
||||
id 'java-toolchain'
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.docs'
|
||||
|
||||
+2
@@ -34,7 +34,9 @@ class AdminMfaAuthorizationManagerConfiguration {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
// <1>
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
// <2>
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(Customizer.withDefaults())
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ class RequiredAuthoritiesAuthorizationManagerConfiguration {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN") // <1>
|
||||
.anyRequest().authenticated() // <2>
|
||||
)
|
||||
.formLogin(Customizer.withDefaults())
|
||||
.oneTimeTokenLogin(Customizer.withDefaults());
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@ internal class RequiredAuthoritiesAuthorizationManagerConfiguration {
|
||||
// @formatter:off
|
||||
http {
|
||||
authorizeHttpRequests {
|
||||
authorize("/admin/**", hasRole("ADMIN"))
|
||||
authorize(anyRequest, authenticated)
|
||||
authorize("/admin/**", hasRole("ADMIN")) // <1>
|
||||
authorize(anyRequest, authenticated) // <2>
|
||||
}
|
||||
formLogin { }
|
||||
oneTimeTokenLogin { }
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
springBootVersion=4.0.0-SNAPSHOT
|
||||
version=7.0.2
|
||||
version=7.0.3
|
||||
samplesBranch=main
|
||||
org.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError
|
||||
org.gradle.parallel=true
|
||||
|
||||
+20
-20
@@ -4,20 +4,20 @@ io-rsocket = "1.1.5"
|
||||
io-spring-javaformat = "0.0.47"
|
||||
io-spring-nohttp = "0.0.11"
|
||||
jakarta-websocket = "2.2.0"
|
||||
org-apache-maven-resolver = "1.9.24"
|
||||
org-aspectj = "1.9.25"
|
||||
org-apache-maven-resolver = "1.9.25"
|
||||
org-aspectj = "1.9.25.1"
|
||||
org-bouncycastle = "1.80"
|
||||
org-eclipse-jetty = "11.0.26"
|
||||
org-jetbrains-kotlin = "2.2.21"
|
||||
org-jetbrains-kotlinx = "1.10.2"
|
||||
org-mockito = "5.17.0"
|
||||
org-opensaml5 = "5.1.6"
|
||||
org-springframework = "7.0.2"
|
||||
org-springframework = "7.0.4"
|
||||
com-password4j = "1.8.4"
|
||||
|
||||
[libraries]
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.22"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.20.1"
|
||||
ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.29"
|
||||
com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.20.2"
|
||||
com-google-inject-guice = "com.google.inject:guice:3.0"
|
||||
com-netflix-nebula-nebula-project-plugin = "com.netflix.nebula:nebula-project-plugin:8.2.0"
|
||||
com-nimbusds-nimbus-jose-jwt = "com.nimbusds:nimbus-jose-jwt:10.4"
|
||||
@@ -27,16 +27,16 @@ com-squareup-okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.
|
||||
com-unboundid-unboundid-ldapsdk = "com.unboundid:unboundid-ldapsdk:7.0.4"
|
||||
com-jayway-jsonpath-json-path = "com.jayway.jsonpath:json-path:2.9.0"
|
||||
commons-collections = "commons-collections:commons-collections:3.2.2"
|
||||
io-micrometer-context-propagation = "io.micrometer:context-propagation:1.1.3"
|
||||
io-micrometer-context-propagation = "io.micrometer:context-propagation:1.1.4"
|
||||
io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.14.14"
|
||||
io-mockk = "io.mockk:mockk:1.14.7"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2025.0.1"
|
||||
io-mockk = "io.mockk:mockk:1.14.9"
|
||||
io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2025.0.3"
|
||||
io-rsocket-rsocket-bom = { module = "io.rsocket:rsocket-bom", version.ref = "io-rsocket" }
|
||||
io-spring-javaformat-spring-javaformat-checkstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "io-spring-javaformat" }
|
||||
io-spring-javaformat-spring-javaformat-gradle-plugin = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "io-spring-javaformat" }
|
||||
io-spring-nohttp-nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-nohttp-nohttp-gradle = { module = "io.spring.nohttp:nohttp-gradle", version.ref = "io-spring-nohttp" }
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.13"
|
||||
io-spring-security-release-plugin = "io.spring.gradle:spring-security-release-plugin:1.0.14"
|
||||
jakarta-annotation-jakarta-annotation-api = "jakarta.annotation:jakarta.annotation-api:3.0.0"
|
||||
jakarta-inject-jakarta-inject-api = "jakarta.inject:jakarta.inject-api:2.0.1"
|
||||
jakarta-persistence-jakarta-persistence-api = "jakarta.persistence:jakarta.persistence-api:3.2.0"
|
||||
@@ -45,13 +45,13 @@ jakarta-servlet-jsp-jakarta-servlet-jsp-api = "jakarta.servlet.jsp:jakarta.servl
|
||||
jakarta-servlet-jsp-jstl-jakarta-servlet-jsp-jstl-api = "jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.2"
|
||||
jakarta-websocket-jakarta-websocket-api = { module = "jakarta.websocket:jakarta.websocket-api", version.ref = "jakarta-websocket" }
|
||||
jakarta-websocket-jakarta-websocket-client-api = { module = "jakarta.websocket:jakarta.websocket-client-api", version.ref = "jakarta-websocket" }
|
||||
jakarta-xml-bind-jakarta-xml-bind-api = "jakarta.xml.bind:jakarta.xml.bind-api:4.0.4"
|
||||
jakarta-xml-bind-jakarta-xml-bind-api = "jakarta.xml.bind:jakarta.xml.bind-api:4.0.5"
|
||||
ldapsdk = "ldapsdk:ldapsdk:4.1"
|
||||
net-sourceforge-htmlunit = "net.sourceforge.htmlunit:htmlunit:2.70.0"
|
||||
org-htmlunit-htmlunit = "org.htmlunit:htmlunit:4.11.1"
|
||||
org-apache-httpcomponents-httpclient = "org.apache.httpcomponents.client5:httpclient5:5.5.1"
|
||||
org-apache-httpcomponents-httpclient = "org.apache.httpcomponents.client5:httpclient5:5.5.2"
|
||||
org-apache-kerby-simplekdc='org.apache.kerby:kerb-simplekdc:2.1.1'
|
||||
org-apache-maven-maven-resolver-provider = "org.apache.maven:maven-resolver-provider:3.9.11"
|
||||
org-apache-maven-maven-resolver-provider = "org.apache.maven:maven-resolver-provider:3.9.12"
|
||||
org-apache-maven-resolver-maven-resolver-connector-basic = { module = "org.apache.maven.resolver:maven-resolver-connector-basic", version.ref = "org-apache-maven-resolver" }
|
||||
org-apache-maven-resolver-maven-resolver-impl = { module = "org.apache.maven.resolver:maven-resolver-impl", version.ref = "org-apache-maven-resolver" }
|
||||
org-apache-maven-resolver-maven-resolver-transport-http = { module = "org.apache.maven.resolver:maven-resolver-transport-http", version.ref = "org-apache-maven-resolver" }
|
||||
@@ -59,7 +59,7 @@ org-apereo-cas-client-cas-client-core = "org.apereo.cas.client:cas-client-core:4
|
||||
io-freefair-gradle-aspectj-plugin = "io.freefair.gradle:aspectj-plugin:8.13.1"
|
||||
org-aspectj-aspectjrt = { module = "org.aspectj:aspectjrt", version.ref = "org-aspectj" }
|
||||
org-aspectj-aspectjweaver = { module = "org.aspectj:aspectjweaver", version.ref = "org-aspectj" }
|
||||
org-assertj-assertj-core = "org.assertj:assertj-core:3.27.6"
|
||||
org-assertj-assertj-core = "org.assertj:assertj-core:3.27.7"
|
||||
org-bouncycastle-bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "org-bouncycastle" }
|
||||
org-bouncycastle-bcprov-jdk15on = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "org-bouncycastle" }
|
||||
org-eclipse-jetty-jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "org-eclipse-jetty" }
|
||||
@@ -70,7 +70,7 @@ org-hsqldb = "org.hsqldb:hsqldb:2.7.4"
|
||||
org-jetbrains-kotlin-kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "org-jetbrains-kotlin" }
|
||||
org-jetbrains-kotlin-kotlin-gradle-plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.21"
|
||||
org-jetbrains-kotlinx-kotlinx-coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version.ref = "org-jetbrains-kotlinx" }
|
||||
org-junit-junit-bom = "org.junit:junit-bom:6.0.1"
|
||||
org-junit-junit-bom = "org.junit:junit-bom:6.0.2"
|
||||
org-mockito-mockito-bom = { module = "org.mockito:mockito-bom", version.ref = "org-mockito" }
|
||||
org-opensaml-opensaml5-saml-api = { module = "org.opensaml:opensaml-saml-api", version.ref = "org-opensaml5" }
|
||||
org-opensaml-opensaml5-saml-impl = { module = "org.opensaml:opensaml-saml-impl", version.ref = "org-opensaml5" }
|
||||
@@ -81,28 +81,28 @@ org-seleniumhq-selenium-selenium-support = "org.seleniumhq.selenium:selenium-sup
|
||||
org-skyscreamer-jsonassert = "org.skyscreamer:jsonassert:1.5.3"
|
||||
org-slf4j-log4j-over-slf4j = "org.slf4j:log4j-over-slf4j:1.7.36"
|
||||
org-slf4j-slf4j-api = "org.slf4j:slf4j-api:2.0.17"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2025.1.1"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:4.0.0"
|
||||
org-springframework-data-spring-data-bom = "org.springframework.data:spring-data-bom:2025.1.3"
|
||||
org-springframework-ldap-spring-ldap-core = "org.springframework.ldap:spring-ldap-core:4.0.2"
|
||||
org-springframework-spring-framework-bom = { module = "org.springframework:spring-framework-bom", version.ref = "org-springframework" }
|
||||
org-synchronoss-cloud-nio-multipart-parser = "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
|
||||
tools-jackson-jackson-bom = "tools.jackson:jackson-bom:3.0.3"
|
||||
tools-jackson-jackson-bom = "tools.jackson:jackson-bom:3.0.4"
|
||||
|
||||
com-google-code-gson-gson = "com.google.code.gson:gson:2.13.2"
|
||||
com-thaiopensource-trag = "com.thaiopensource:trang:20091111"
|
||||
net-sourceforge-saxon-saxon = "net.sourceforge.saxon:saxon:9.1.0.8"
|
||||
org-yaml-snakeyaml = "org.yaml:snakeyaml:1.33"
|
||||
org-apache-commons-commons-io = "org.apache.commons:commons-io:1.3.2"
|
||||
io-github-gradle-nexus-publish-plugin = "io.github.gradle-nexus:publish-plugin:1.3.0"
|
||||
io-github-gradle-nexus-publish-plugin = "io.github.gradle-nexus:publish-plugin:2.0.0"
|
||||
org-gretty-gretty = "org.gretty:gretty:4.1.10"
|
||||
com-github-ben-manes-gradle-versions-plugin = "com.github.ben-manes:gradle-versions-plugin:0.52.0"
|
||||
com-github-spullara-mustache-java-compiler = "com.github.spullara.mustache.java:compiler:0.9.14"
|
||||
org-hidetake-gradle-ssh-plugin = "org.hidetake:gradle-ssh-plugin:2.10.1"
|
||||
org-jfrog-buildinfo-build-info-extractor-gradle = "org.jfrog.buildinfo:build-info-extractor-gradle:4.34.2"
|
||||
org-jfrog-buildinfo-build-info-extractor-gradle = "org.jfrog.buildinfo:build-info-extractor-gradle:6.0.4"
|
||||
org-sonarsource-scanner-gradle-sonarqube-gradle-plugin = "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.8.0.1969"
|
||||
org-instancio-instancio-junit = "org.instancio:instancio-junit:3.7.1"
|
||||
|
||||
spring-nullability = 'io.spring.nullability:io.spring.nullability.gradle.plugin:0.0.6'
|
||||
webauthn4j-core = 'com.webauthn4j:webauthn4j-core:0.29.7.RELEASE'
|
||||
webauthn4j-core = 'com.webauthn4j:webauthn4j-core:0.31.0.RELEASE'
|
||||
com-password4j-password4j = { module = "com.password4j:password4j", version.ref = "com-password4j" }
|
||||
|
||||
[plugins]
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
|
||||
distributionSha256Sum=f1771298a70f6db5a29daf62378c4e18a17fc33c9ba6b14362e0cdf40610380d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
@rem
|
||||
@rem Copyright 2004-present the original author or authors.
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
apply plugin: 'io.spring.convention.spring-test'
|
||||
apply plugin: 'java-toolchain'
|
||||
|
||||
dependencies {
|
||||
implementation platform(project(":spring-security-dependencies"))
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import org.springframework.util.Assert;
|
||||
* It needs a <code>KerberosTicketValidator</code>, which contains the code to validate
|
||||
* the ticket, as this code is different between SUN and IBM JRE.<br>
|
||||
* It also needs an <code>UserDetailsService</code> to load the user properties and the
|
||||
* <code>GrantedAuthorities</code>, as we only get back the username from Kerbeos
|
||||
* <code>GrantedAuthorities</code>, as we only get back the username from Kerberos
|
||||
* </p>
|
||||
*
|
||||
* You can see an example configuration in
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public interface KerberosTicketValidator {
|
||||
|
||||
/**
|
||||
* Validates a Kerberos/SPNEGO ticket.
|
||||
* @param token Kerbeos/SPNEGO ticket
|
||||
* @param token Kerberos/SPNEGO ticket
|
||||
* @return authenticated kerberos principal
|
||||
* @throws BadCredentialsException if the ticket is not valid
|
||||
*/
|
||||
|
||||
+2
-2
@@ -76,7 +76,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
* </sec:authentication-manager>
|
||||
*
|
||||
* <bean id="kerberosServiceAuthenticationProvider"
|
||||
* class="org.springframework.security.kerberos.authenitcation.KerberosServiceAuthenticationProvider">
|
||||
* class="org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider">
|
||||
* <property name="ticketValidator">
|
||||
* <bean class="org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator">
|
||||
* <property name="servicePrincipal" value="HTTP/web.springsource.com" />
|
||||
@@ -103,7 +103,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
* <a href="https://bugs.sun.com/view_bug.do?bug_id=6851973">bug</a>.
|
||||
* </p>
|
||||
* <p>
|
||||
* A workaround unti this is fixed in the JVM is to change
|
||||
* A workaround until this is fixed in the JVM is to change
|
||||
* </p>
|
||||
* HKEY_LOCAL_MACHINE\System \CurrentControlSet\Control\LSA\SuppressExtendedProtection to
|
||||
* 0x02
|
||||
|
||||
+4
-4
@@ -134,9 +134,9 @@ public final class PathPatternMessageMatcher implements MessageMatcher<Object> {
|
||||
* The following are valid patterns and their meaning
|
||||
* <ul>
|
||||
* <li>{@code /path} - match exactly and only `/path`</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendents</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendants</li>
|
||||
* <li>{@code /path/{value}/**} - match `/path/subdirectory` and any of its
|
||||
* descendents, capturing the value of the subdirectory in
|
||||
* descendants, capturing the value of the subdirectory in
|
||||
* {@link MessageAuthorizationContext#getVariables()}</li>
|
||||
* </ul>
|
||||
*
|
||||
@@ -169,9 +169,9 @@ public final class PathPatternMessageMatcher implements MessageMatcher<Object> {
|
||||
* The following are valid patterns and their meaning
|
||||
* <ul>
|
||||
* <li>{@code /path} - match exactly and only `/path`</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendents</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendants</li>
|
||||
* <li>{@code /path/{value}/**} - match `/path/subdirectory` and any of its
|
||||
* descendents, capturing the value of the subdirectory in
|
||||
* descendants, capturing the value of the subdirectory in
|
||||
* {@link MessageAuthorizationContext#getVariables()}</li>
|
||||
* </ul>
|
||||
*
|
||||
|
||||
-5
@@ -40,10 +40,8 @@ import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -132,8 +130,6 @@ public final class ResolvableMethod {
|
||||
|
||||
private static final SpringObjenesis objenesis = new SpringObjenesis();
|
||||
|
||||
private static final ParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
// Matches ValueConstants.DEFAULT_NONE (spring-web and spring-messaging)
|
||||
private static final String DEFAULT_VALUE_NONE = "\n\t\t\n\t\t\n\uE000\uE001\uE002\n\t\t\t\t\n";
|
||||
|
||||
@@ -634,7 +630,6 @@ public final class ResolvableMethod {
|
||||
List<MethodParameter> matches = new ArrayList<>();
|
||||
for (int i = 0; i < ResolvableMethod.this.method.getParameterCount(); i++) {
|
||||
MethodParameter param = new SynthesizingMethodParameter(ResolvableMethod.this.method, i);
|
||||
param.initParameterNameDiscovery(nameDiscoverer);
|
||||
if (this.filters.stream().allMatch((p) -> p.test(param))) {
|
||||
matches.add(param);
|
||||
}
|
||||
|
||||
+3
-4
@@ -63,10 +63,9 @@ public abstract class AbstractRestClientOAuth2AccessTokenResponseClient<T extend
|
||||
|
||||
// @formatter:off
|
||||
private RestClient restClient = RestClient.builder()
|
||||
.messageConverters((messageConverters) -> {
|
||||
messageConverters.clear();
|
||||
messageConverters.add(new FormHttpMessageConverter());
|
||||
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
|
||||
.configureMessageConverters((messageConverters) -> {
|
||||
messageConverters.addCustomConverter(new FormHttpMessageConverter());
|
||||
messageConverters.addCustomConverter(new OAuth2AccessTokenResponseHttpMessageConverter());
|
||||
})
|
||||
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
|
||||
.build();
|
||||
|
||||
+3
-1
@@ -98,9 +98,11 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication
|
||||
}
|
||||
|
||||
private static String getResourceMetadataParameter(HttpServletRequest request) {
|
||||
String path = request.getContextPath()
|
||||
+ OAuth2ProtectedResourceMetadataFilter.DEFAULT_OAUTH2_PROTECTED_RESOURCE_METADATA_ENDPOINT_URI;
|
||||
// @formatter:off
|
||||
return UriComponentsBuilder.fromUriString(UrlUtils.buildFullRequestUrl(request))
|
||||
.replacePath(OAuth2ProtectedResourceMetadataFilter.DEFAULT_OAUTH2_PROTECTED_RESOURCE_METADATA_ENDPOINT_URI)
|
||||
.replacePath(path)
|
||||
.replaceQuery(null)
|
||||
.fragment(null)
|
||||
.build()
|
||||
|
||||
+12
@@ -65,6 +65,18 @@ public class BearerTokenAuthenticationEntryPointTests {
|
||||
"Bearer realm=\"test\", resource_metadata=\"http://localhost/.well-known/oauth-protected-resource\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void commenceWhenNoBearerTokenErrorAndContextPathSetThenStatus401AndAuthHeaderWithContextPath() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContextPath("/ctx");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
this.authenticationEntryPoint.commence(request, response, new BadCredentialsException("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(401);
|
||||
assertThat(response.getHeader("WWW-Authenticate"))
|
||||
.isEqualTo("Bearer resource_metadata=\"http://localhost/ctx/.well-known/oauth-protected-resource\"");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithError() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public final class Saml2X509Credential implements Serializable {
|
||||
|
||||
/**
|
||||
* Creates a {@link Saml2X509Credential} using the provided parameters
|
||||
* @param certificate the credential's public certificiate
|
||||
* @param certificate the credential's public certificate
|
||||
* @param types the credential's intended usages, must be one of
|
||||
* {@link Saml2X509CredentialType#VERIFICATION} or
|
||||
* {@link Saml2X509CredentialType#ENCRYPTION} or both.
|
||||
|
||||
+2
-2
@@ -5,13 +5,13 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "io.spring.develocity.conventions" version "0.0.24"
|
||||
id "io.spring.develocity.conventions" version "0.0.25"
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
maven { url = "https://repo.spring.io/snapshot" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -148,7 +148,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
|
||||
/**
|
||||
* Populates the provided X509Certificate instances on the request.
|
||||
* @param certificates the X509Certificate instances to pouplate
|
||||
* @param certificates the X509Certificate instances to populate
|
||||
* @return the
|
||||
* {@link org.springframework.test.web.servlet.request.RequestPostProcessor} to use.
|
||||
*/
|
||||
@@ -157,7 +157,7 @@ public final class SecurityMockMvcRequestPostProcessors {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an X509Cetificate using a resoureName and populates it on the request.
|
||||
* Finds an X509Certificate using a resourceName and populates it on the request.
|
||||
* @param resourceName the name of the X509Certificate resource
|
||||
* @return the
|
||||
* {@link org.springframework.test.web.servlet.request.RequestPostProcessor} to use.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
plugins {
|
||||
id 'io.spring.convention.spring-module'
|
||||
id 'security-nullability'
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
configurations {
|
||||
javascript {
|
||||
canBeConsumed = false
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ interface EvaluationContextPostProcessor<I> {
|
||||
* that was passed in.
|
||||
* @param context the original {@link EvaluationContext}
|
||||
* @param invocation the security invocation object (i.e. FilterInvocation)
|
||||
* @return the upated context.
|
||||
* @return the updated context.
|
||||
*/
|
||||
EvaluationContext postProcess(EvaluationContext context, I invocation);
|
||||
|
||||
|
||||
+1
-7
@@ -52,20 +52,14 @@ public final class HaveIBeenPwnedRestApiPasswordChecker implements CompromisedPa
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final MessageDigest sha1Digest;
|
||||
|
||||
private RestClient restClient = RestClient.builder().baseUrl(API_URL).build();
|
||||
|
||||
public HaveIBeenPwnedRestApiPasswordChecker() {
|
||||
this.sha1Digest = getSha1Digest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompromisedPasswordDecision check(@Nullable String password) {
|
||||
if (password == null) {
|
||||
return new CompromisedPasswordDecision(false);
|
||||
}
|
||||
byte[] hash = this.sha1Digest.digest(password.getBytes(StandardCharsets.UTF_8));
|
||||
byte[] hash = getSha1Digest().digest(password.getBytes(StandardCharsets.UTF_8));
|
||||
String encoded = new String(Hex.encode(hash)).toUpperCase(Locale.ROOT);
|
||||
String prefix = encoded.substring(0, PREFIX_LENGTH);
|
||||
String suffix = encoded.substring(PREFIX_LENGTH);
|
||||
|
||||
+1
-7
@@ -55,12 +55,6 @@ public class HaveIBeenPwnedRestApiReactivePasswordChecker implements ReactiveCom
|
||||
|
||||
private WebClient webClient = WebClient.builder().baseUrl(API_URL).build();
|
||||
|
||||
private final MessageDigest sha1Digest;
|
||||
|
||||
public HaveIBeenPwnedRestApiReactivePasswordChecker() {
|
||||
this.sha1Digest = getSha1Digest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<CompromisedPasswordDecision> check(@Nullable String password) {
|
||||
return getHash(password).map((hash) -> new String(Hex.encode(hash)))
|
||||
@@ -98,7 +92,7 @@ public class HaveIBeenPwnedRestApiReactivePasswordChecker implements ReactiveCom
|
||||
|
||||
private Mono<byte[]> getHash(@Nullable String rawPassword) {
|
||||
return Mono.justOrEmpty(rawPassword)
|
||||
.map((password) -> this.sha1Digest.digest(password.getBytes(StandardCharsets.UTF_8)))
|
||||
.map((password) -> getSha1Digest().digest(password.getBytes(StandardCharsets.UTF_8)))
|
||||
.subscribeOn(Schedulers.boundedElastic())
|
||||
.publishOn(Schedulers.parallel());
|
||||
}
|
||||
|
||||
+3
-3
@@ -133,8 +133,8 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
return new ArrayList<>(groups);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.error("Exception occured while looking up groups for user", ex);
|
||||
throw new RuntimeException("Exception occured while looking up groups for user", ex);
|
||||
logger.error("Exception occurred while looking up groups for user", ex);
|
||||
throw new RuntimeException("Exception occurred while looking up groups for user", ex);
|
||||
}
|
||||
finally {
|
||||
closeContext(context);
|
||||
@@ -148,7 +148,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
}
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
logger.debug("Exception occured while closing context", ex);
|
||||
logger.debug("Exception occurred while closing context", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -164,7 +164,7 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
|
||||
* Called if the {@code AuthenticationManager} rejects the authentication object
|
||||
* returned from the {@code RememberMeServices} {@code autoLogin} method. This method
|
||||
* will not be called when no remember-me token is present in the request and
|
||||
* {@code autoLogin} reurns null.
|
||||
* {@code autoLogin} returns {@code null}.
|
||||
*/
|
||||
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException failed) {
|
||||
@@ -184,7 +184,7 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
|
||||
* successfully authenticated. By default, the filter will just allow the current
|
||||
* request to proceed, but if an {@code AuthenticationSuccessHandler} is set, it will
|
||||
* be invoked and the {@code doFilter()} method will return immediately, thus allowing
|
||||
* the application to redirect the user to a specific URL, regardless of whatthe
|
||||
* the application to redirect the user to a specific URL, regardless of what the
|
||||
* original request was for.
|
||||
* @param successHandler the strategy to invoke immediately before returning from
|
||||
* {@code doFilter()}.
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ public final class HttpSessionCsrfTokenRepository implements CsrfTokenRepository
|
||||
* @param sessionAttributeName the new attribute name to use
|
||||
*/
|
||||
public void setSessionAttributeName(String sessionAttributeName) {
|
||||
Assert.hasLength(sessionAttributeName, "sessionAttributename cannot be null or empty");
|
||||
Assert.hasLength(sessionAttributeName, "sessionAttributeName cannot be null or empty");
|
||||
this.sessionAttributeName = sessionAttributeName;
|
||||
}
|
||||
|
||||
|
||||
@@ -799,17 +799,17 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
Enumeration<String> paramaterNames = super.getParameterNames();
|
||||
Enumeration<String> parameterNames = super.getParameterNames();
|
||||
return new Enumeration<>() {
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return paramaterNames.hasMoreElements();
|
||||
return parameterNames.hasMoreElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nextElement() {
|
||||
String name = paramaterNames.nextElement();
|
||||
String name = parameterNames.nextElement();
|
||||
validateAllowedParameterName(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Provides support for
|
||||
* <a href="https://w3c.github.io/webappsec-permissions-policy//">Permisisons Policy</a>.
|
||||
* <a href="https://w3c.github.io/webappsec-permissions-policy//">Permissions Policy</a>.
|
||||
* <p>
|
||||
* Permissions Policy allows web developers to selectively enable, disable, and modify the
|
||||
* behavior of certain APIs and web features in the browser.
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Implementation which uses a regular expression to validate the supplied origin. If the
|
||||
* value of the HTTP parameter matches the pattern, then the result will be ALLOW-FROM
|
||||
* <paramter-value>.
|
||||
* <parameter-value>.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
* @since 3.2
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ public final class FastHttpDateFormat {
|
||||
* Parses date with given formatters.
|
||||
* @param value The string to parse
|
||||
* @param formats Array of formats to use
|
||||
* @return Parsed date (or <code>null</code> if no formatter mached)
|
||||
* @return Parsed date (or <code>null</code> if no formatter matched)
|
||||
*/
|
||||
private static @Nullable Long internalParseDate(String value, DateFormat[] formats) {
|
||||
Date date = null;
|
||||
|
||||
+4
-4
@@ -268,9 +268,9 @@ public final class PathPatternRequestMatcher implements RequestMatcher {
|
||||
* The following are valid patterns and their meaning
|
||||
* <ul>
|
||||
* <li>{@code /path} - match exactly and only `/path`</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendents</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendants</li>
|
||||
* <li>{@code /path/{value}/**} - match `/path/subdirectory` and any of its
|
||||
* descendents, capturing the value of the subdirectory in
|
||||
* descendants, capturing the value of the subdirectory in
|
||||
* {@link RequestAuthorizationContext#getVariables()}</li>
|
||||
* </ul>
|
||||
*
|
||||
@@ -303,9 +303,9 @@ public final class PathPatternRequestMatcher implements RequestMatcher {
|
||||
* The following are valid patterns and their meaning
|
||||
* <ul>
|
||||
* <li>{@code /path} - match exactly and only `/path`</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendents</li>
|
||||
* <li>{@code /path/**} - match `/path` and any of its descendants</li>
|
||||
* <li>{@code /path/{value}/**} - match `/path/subdirectory` and any of its
|
||||
* descendents, capturing the value of the subdirectory in
|
||||
* descendants, capturing the value of the subdirectory in
|
||||
* {@link RequestAuthorizationContext#getVariables()}</li>
|
||||
* </ul>
|
||||
*
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ThrowableAnalyzer {
|
||||
|
||||
/**
|
||||
* Map of registered cause extractors. key: Class<Throwable>; value:
|
||||
* ThrowableCauseExctractor
|
||||
* ThrowableCauseExtractor
|
||||
*/
|
||||
private final Map<Class<? extends Throwable>, ThrowableCauseExtractor> extractorMap;
|
||||
|
||||
|
||||
@@ -87,8 +87,8 @@ public final class UrlUtils {
|
||||
* (SEC-1255). This method is typically used to return a URL for matching against
|
||||
* secured paths, hence the decoded form is used in preference to the requestURI for
|
||||
* building the returned value. But this method may also be called using dummy request
|
||||
* objects which just have the requestURI and contextPatth set, for example, so it
|
||||
* will fall back to using those.
|
||||
* objects which just have the requestURI and contextPath set, for example, so it will
|
||||
* fall back to using those.
|
||||
* @return the decoded URL, excluding any server name, context path or servlet path
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
* @author Eddú Meléndez
|
||||
* @since 3.0.2
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface RequestMatcher {
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,10 +40,8 @@ import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -131,8 +129,6 @@ public final class ResolvableMethod {
|
||||
|
||||
private static final SpringObjenesis objenesis = new SpringObjenesis();
|
||||
|
||||
private static final ParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
private final Method method;
|
||||
|
||||
private ResolvableMethod(Method method) {
|
||||
@@ -620,7 +616,6 @@ public final class ResolvableMethod {
|
||||
List<MethodParameter> matches = new ArrayList<>();
|
||||
for (int i = 0; i < ResolvableMethod.this.method.getParameterCount(); i++) {
|
||||
MethodParameter param = new SynthesizingMethodParameter(ResolvableMethod.this.method, i);
|
||||
param.initParameterNameDiscovery(nameDiscoverer);
|
||||
if (this.filters.stream().allMatch((p) -> p.test(param))) {
|
||||
matches.add(param);
|
||||
}
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ public class HttpSessionEventPublisherTests {
|
||||
* It's not that complicated so we'll just run it straight through here.
|
||||
*/
|
||||
@Test
|
||||
public void publishedEventIsReceivedbyListener() {
|
||||
public void publishedEventIsReceivedByListener() {
|
||||
HttpSessionEventPublisher publisher = new HttpSessionEventPublisher();
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
@@ -66,7 +66,7 @@ public class HttpSessionEventPublisherTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishedEventIsReceivedbyListenerChildContext() {
|
||||
public void publishedEventIsReceivedByListenerChildContext() {
|
||||
HttpSessionEventPublisher publisher = new HttpSessionEventPublisher();
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
|
||||
@@ -16,10 +16,12 @@ dependencies {
|
||||
optional 'org.springframework:spring-jdbc'
|
||||
optional 'org.springframework:spring-tx'
|
||||
optional 'tools.jackson.core:jackson-databind'
|
||||
optional 'com.fasterxml.jackson.core:jackson-databind'
|
||||
|
||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||
|
||||
testImplementation project(path: ':spring-security-core', configuration: 'tests')
|
||||
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-cbor'
|
||||
testImplementation 'io.projectreactor:reactor-test'
|
||||
testImplementation 'jakarta.xml.bind:jakarta.xml.bind-api'
|
||||
testImplementation 'jakarta.websocket:jakarta.websocket-api'
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ public interface CredentialRecord {
|
||||
|
||||
/**
|
||||
* The <a href=
|
||||
* "https://www.w3.org/TR/webauthn-3/#abstract-opdef-credential-record-transports">transpots</a>
|
||||
* "https://www.w3.org/TR/webauthn-3/#abstract-opdef-credential-record-transports">transports</a>
|
||||
* is the value returned from {@code response.getTransports()}.
|
||||
* @return
|
||||
*/
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ public final class PublicKeyCredential<R extends AuthenticatorResponse> implemen
|
||||
|
||||
/**
|
||||
* Sets the {@link #getAuthenticatorAttachment()} property.
|
||||
* @param authenticatorAttachment the authenticator attachement
|
||||
* @param authenticatorAttachment the authenticator attachment
|
||||
* @return the PublicKeyCredentialBuilder
|
||||
*/
|
||||
public PublicKeyCredentialBuilder authenticatorAttachment(AuthenticatorAttachment authenticatorAttachment) {
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ public final class PublicKeyCredentialCreationOptions {
|
||||
/**
|
||||
* The <a href=
|
||||
* "https://www.w3.org/TR/webauthn-3/#dom-publickeycredentialcreationoptions-pubkeycredparams">publicKeyCredParams</a>
|
||||
* params lisst the key types and signature algorithms the Relying Party Supports,
|
||||
* params list the key types and signature algorithms the Relying Party Supports,
|
||||
* ordered from most preferred to least preferred.
|
||||
* @return the public key credential parameters
|
||||
*/
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ package org.springframework.security.web.webauthn.api;
|
||||
/**
|
||||
* The <a href=
|
||||
* "https://www.w3.org/TR/webauthn-3/#enumdef-residentkeyrequirement">ResidentKeyRequirement</a>
|
||||
* describes the Relying Partys requirements for client-side discoverable credentials.
|
||||
* describes the Relying Party requirements for client-side discoverable credentials.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 6.4
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public final class TestAuthenticatorAttestationResponses {
|
||||
public static AuthenticatorAttestationResponse.AuthenticatorAttestationResponseBuilder createAuthenticatorAttestationResponse() {
|
||||
return AuthenticatorAttestationResponse.builder()
|
||||
.attestationObject(Bytes.fromBase64(
|
||||
"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUy9GqwTRaMpzVDbXq1dyEAXVOxrou08k22ggRC45MKNhdAAAAALraVWanqkAfvZZFYZpVEg0AEDWRLOHq0Wxw4cOkCemynKqlAQIDJiABIVgg4Hkrn2kbGmpZTdoDZUNrppo93OqgQV7ONzVvo5GLCFciWCCrf6yIQggq2BfZntawxRsBBbWG_FWkYAoU8yPipS-5hg-p1VREax-qKTGn1Bp92fRMjRMunH7XwSlf9mMWJdY3VvAkicTChlxVd256yk4jEiXiJ5BuwugdpT7fBOYtymjpQECAyYgASFYIJK-2epPEw0ujHN-gvVp2Hp3ef8CzU3zqwO5ylx8L2OsIlggK5x5OlTGEPxLS-85TAABum4aqVK4CSWJ7LYDdkjuBLk"))
|
||||
"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUy9GqwTRaMpzVDbXq1dyEAXVOxrou08k22ggRC45MKNhdAAAAALraVWanqkAfvZZFYZpVEg0AEDWRLOHq0Wxw4cOkCemynKqlAQIDJiABIVgg4Hkrn2kbGmpZTdoDZUNrppo93OqgQV7ONzVvo5GLCFciWCCrf6yIQggq2BfZntawxRsBBbWG_FWkYAoU8yPipS-5hg=="))
|
||||
.clientDataJSON(Bytes.fromBase64(
|
||||
"eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoicTdsQ2RkM1NWUXhkQy12OHBuUkFHRW4xQjJNLXQ3WkVDV1B3Q0FtaFd2YyIsIm9yaWdpbiI6Imh0dHBzOi8vZXhhbXBsZS5sb2NhbGhvc3Q6ODQ0MyIsImNyb3NzT3JpZ2luIjpmYWxzZX0"))
|
||||
.transports(AuthenticatorTransport.HYBRID, AuthenticatorTransport.INTERNAL);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user