Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3e7d76b70 |
+20
-99
@@ -1,10 +1,12 @@
|
|||||||
version: 2
|
version: 2
|
||||||
registries:
|
registries:
|
||||||
|
spring-milestones:
|
||||||
|
type: maven-repository
|
||||||
|
url: https://repo.spring.io/milestone
|
||||||
shibboleth:
|
shibboleth:
|
||||||
type: maven-repository
|
type: maven-repository
|
||||||
url: https://build.shibboleth.net/maven/releases
|
url: https://build.shibboleth.net/maven/releases
|
||||||
updates:
|
updates:
|
||||||
# 6.5.x
|
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: 6.5.x
|
target-branch: 6.5.x
|
||||||
directory: /
|
directory: /
|
||||||
@@ -15,6 +17,7 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
|
- spring-milestones
|
||||||
- shibboleth
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
@@ -31,28 +34,8 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
- version-update:semver-minor
|
- version-update:semver-minor
|
||||||
- package-ecosystem: npm
|
|
||||||
target-branch: 6.5.x
|
|
||||||
directory: /docs
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
target-branch: 6.5.x
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
|
||||||
|
|
||||||
# 7.0.x
|
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: 7.0.x
|
target-branch: 6.4.x
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
@@ -61,10 +44,10 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
|
- spring-milestones
|
||||||
- shibboleth
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
- dependency-name: io.spring.nullability:*
|
|
||||||
- dependency-name: org.python:jython
|
- dependency-name: org.python:jython
|
||||||
- dependency-name: org.apache.directory.server:*
|
- dependency-name: org.apache.directory.server:*
|
||||||
- dependency-name: org.apache.directory.shared:*
|
- dependency-name: org.apache.directory.shared:*
|
||||||
@@ -74,34 +57,11 @@ updates:
|
|||||||
- dependency-name: org.mockito:mockito-bom
|
- dependency-name: org.mockito:mockito-bom
|
||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
- dependency-name: com.gradle.enterprise
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
- version-update:semver-minor
|
|
||||||
- dependency-name: '*'
|
- dependency-name: '*'
|
||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
- version-update:semver-minor
|
- version-update:semver-minor
|
||||||
- package-ecosystem: npm
|
|
||||||
target-branch: 7.0.x
|
|
||||||
directory: /docs
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
target-branch: 7.0.x
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
|
||||||
|
|
||||||
# main
|
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: main
|
target-branch: main
|
||||||
directory: /
|
directory: /
|
||||||
@@ -112,6 +72,7 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
|
- spring-milestones
|
||||||
- shibboleth
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
@@ -131,6 +92,17 @@ updates:
|
|||||||
- dependency-name: '*'
|
- dependency-name: '*'
|
||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
|
- version-update:semver-minor
|
||||||
|
|
||||||
|
- package-ecosystem: npm
|
||||||
|
target-branch: docs-build
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
labels:
|
||||||
|
- 'type: task'
|
||||||
|
- 'in: build'
|
||||||
|
|
||||||
- package-ecosystem: npm
|
- package-ecosystem: npm
|
||||||
target-branch: main
|
target-branch: main
|
||||||
directory: /docs
|
directory: /docs
|
||||||
@@ -138,63 +110,12 @@ updates:
|
|||||||
interval: weekly
|
interval: weekly
|
||||||
labels:
|
labels:
|
||||||
- 'type: task'
|
- 'type: task'
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
- 'in: build'
|
||||||
- package-ecosystem: github-actions
|
|
||||||
target-branch: main
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
|
||||||
|
|
||||||
# docs-build
|
|
||||||
- package-ecosystem: gradle
|
|
||||||
target-branch: docs-build
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
time: '03:00'
|
|
||||||
timezone: Etc/UTC
|
|
||||||
labels:
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
registries:
|
|
||||||
- shibboleth
|
|
||||||
ignore:
|
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
|
||||||
- dependency-name: org.python:jython
|
|
||||||
- dependency-name: org.apache.directory.server:*
|
|
||||||
- dependency-name: org.apache.directory.shared:*
|
|
||||||
- dependency-name: org.junit:junit-bom
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
- dependency-name: org.mockito:mockito-bom
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
- dependency-name: com.gradle.enterprise
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
- version-update:semver-minor
|
|
||||||
- dependency-name: '*'
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
- package-ecosystem: npm
|
- package-ecosystem: npm
|
||||||
target-branch: docs-build
|
target-branch: 6.3.x
|
||||||
directory: /
|
directory: /docs
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
labels:
|
labels:
|
||||||
- 'type: task'
|
- 'type: task'
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
target-branch: docs-build
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
- 'in: build'
|
- 'in: build'
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
name: Merge Dependabot PR
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- '*.x'
|
|
||||||
|
|
||||||
run-name: Merge Dependabot PR ${{ github.ref_name }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
merge-dependabot-pr:
|
|
||||||
permissions: write-all
|
|
||||||
uses: spring-io/spring-github-workflows/.github/workflows/spring-merge-dependabot-pr.yml@v7
|
|
||||||
with:
|
|
||||||
mergeArguments: --auto --rebase
|
|
||||||
@@ -14,12 +14,14 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
snapshot-test:
|
snapshot-test:
|
||||||
name: Test Against Snapshots
|
name: Test Against Snapshots
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@v1
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- java-version: 25
|
- java-version: 21-ea
|
||||||
toolchain: 25
|
toolchain: 21
|
||||||
|
- java-version: 17
|
||||||
|
toolchain: 17
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
|
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
|
||||||
@@ -31,6 +33,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send Notification
|
- name: Send Notification
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
with:
|
with:
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
|
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@v1
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
jdk: [ 25 ]
|
jdk: [ 17 ]
|
||||||
with:
|
with:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
java-version: ${{ matrix.jdk }}
|
java-version: ${{ matrix.jdk }}
|
||||||
@@ -30,24 +30,29 @@ jobs:
|
|||||||
deploy-artifacts:
|
deploy-artifacts:
|
||||||
name: Deploy Artifacts
|
name: Deploy Artifacts
|
||||||
needs: [ build]
|
needs: [ build]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@v1
|
||||||
with:
|
with:
|
||||||
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
default-publish-milestones-central: true
|
default-publish-milestones-central: true
|
||||||
java-version: 25
|
secrets: inherit
|
||||||
|
deploy-docs:
|
||||||
|
name: Deploy Docs
|
||||||
|
needs: [ build ]
|
||||||
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-docs.yml@v1
|
||||||
|
with:
|
||||||
|
should-deploy-docs: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
deploy-schema:
|
deploy-schema:
|
||||||
name: Deploy Schema
|
name: Deploy Schema
|
||||||
needs: [ build ]
|
needs: [ build ]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@v1
|
||||||
with:
|
with:
|
||||||
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
|
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
java-version: 25
|
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
perform-release:
|
perform-release:
|
||||||
name: Perform Release
|
name: Perform Release
|
||||||
needs: [ deploy-artifacts, deploy-schema ]
|
needs: [ deploy-artifacts, deploy-docs, deploy-schema ]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
|
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@v1
|
||||||
with:
|
with:
|
||||||
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
|
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
|
||||||
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
|
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
|
||||||
@@ -55,7 +60,6 @@ jobs:
|
|||||||
release-repo-url: https://repo1.maven.org/maven2
|
release-repo-url: https://repo1.maven.org/maven2
|
||||||
artifact-path: org/springframework/security/spring-security-core
|
artifact-path: org/springframework/security/spring-security-core
|
||||||
slack-announcing-id: spring-security-announcing
|
slack-announcing-id: spring-security-announcing
|
||||||
java-version: 25
|
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
send-notification:
|
send-notification:
|
||||||
name: Send Notification
|
name: Send Notification
|
||||||
@@ -64,6 +68,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send Notification
|
- name: Send Notification
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@b92832ecbc7cbe969201e6beafbde0ee400cf095 # v1.0.15
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
with:
|
with:
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
name: Defer Issues
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
defer-issues:
|
|
||||||
name: Defer Issues
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository_owner == 'spring-projects'
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
- name: Compute Version
|
|
||||||
id: compute-version
|
|
||||||
uses: spring-io/spring-release-actions/compute-version@0.0.3
|
|
||||||
- name: Get Today's Release Version
|
|
||||||
id: todays-release
|
|
||||||
uses: spring-io/spring-release-actions/get-todays-release-version@0.0.3
|
|
||||||
with:
|
|
||||||
snapshot-version: ${{ steps.compute-version.outputs.version }}
|
|
||||||
milestone-repository: ${{ github.repository }}
|
|
||||||
milestone-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Compute Next Version
|
|
||||||
id: next-version
|
|
||||||
uses: spring-io/spring-release-actions/compute-next-version@0.0.3
|
|
||||||
with:
|
|
||||||
version: ${{ steps.todays-release.outputs.release-version }}
|
|
||||||
- name: Schedule Next Milestone
|
|
||||||
uses: spring-io/spring-release-actions/schedule-milestone@0.0.3
|
|
||||||
with:
|
|
||||||
version: ${{ steps.next-version.outputs.version }}
|
|
||||||
version-date: ${{ steps.next-version.outputs.version-date }}
|
|
||||||
repository: ${{ github.repository }}
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Move Open Issues to Next Milestone
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
CURRENT_MILESTONE: ${{ steps.todays-release.outputs.release-version }}
|
|
||||||
NEXT_MILESTONE: ${{ steps.next-version.outputs.version }}
|
|
||||||
run: |
|
|
||||||
current_milestone_number=$(gh api repos/${{ github.repository }}/milestones \
|
|
||||||
--jq ".[] | select(.title == \"$CURRENT_MILESTONE\") | .number")
|
|
||||||
if [ -z "$current_milestone_number" ]; then
|
|
||||||
echo "No milestone found for $CURRENT_MILESTONE"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
next_milestone_number=$(gh api repos/${{ github.repository }}/milestones \
|
|
||||||
--jq ".[] | select(.title == \"$NEXT_MILESTONE\") | .number")
|
|
||||||
if [ -z "$next_milestone_number" ]; then
|
|
||||||
echo "No milestone found for $NEXT_MILESTONE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "Moving open issues from milestone '$CURRENT_MILESTONE' (#$current_milestone_number) to '$NEXT_MILESTONE' (#$next_milestone_number)"
|
|
||||||
page=1
|
|
||||||
while true; do
|
|
||||||
issues=$(gh api "repos/${{ github.repository }}/issues?milestone=$current_milestone_number&state=open&per_page=100&page=$page" \
|
|
||||||
--jq '.[].number')
|
|
||||||
if [ -z "$issues" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
for issue in $issues; do
|
|
||||||
echo "Moving issue/PR #$issue to milestone $NEXT_MILESTONE"
|
|
||||||
gh api repos/${{ github.repository }}/issues/$issue \
|
|
||||||
--method PATCH \
|
|
||||||
--field milestone=$next_milestone_number \
|
|
||||||
--silent
|
|
||||||
done
|
|
||||||
page=$((page + 1))
|
|
||||||
done
|
|
||||||
echo "Done."
|
|
||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
if: github.repository_owner == 'spring-projects'
|
if: github.repository_owner == 'spring-projects'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: docs-build
|
ref: docs-build
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ name: Finalize Release
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch: # Manual trigger
|
workflow_dispatch: # Manual trigger
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: The Spring Security release to finalize (e.g. 7.0.0-RC2)
|
|
||||||
required: true
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||||
@@ -14,14 +10,32 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
project-version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.project-version.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- id: project-version
|
||||||
|
run: echo "version=$(grep '^version=' gradle.properties | cut -d'=' -f2)" >> $GITHUB_OUTPUT
|
||||||
perform-release:
|
perform-release:
|
||||||
name: Perform Release
|
name: Perform Release
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
needs: [ project-version ]
|
||||||
|
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@v1
|
||||||
with:
|
with:
|
||||||
should-perform-release: true
|
should-perform-release: true
|
||||||
project-version: ${{ inputs.version }}
|
project-version: ${{ needs.project-version.outputs.version }}
|
||||||
milestone-repo-url: https://repo1.maven.org/maven2
|
milestone-repo-url: https://repo1.maven.org/maven2
|
||||||
release-repo-url: https://repo1.maven.org/maven2
|
release-repo-url: https://repo1.maven.org/maven2
|
||||||
artifact-path: org/springframework/security/spring-security-core
|
artifact-path: org/springframework/security/spring-security-core
|
||||||
slack-announcing-id: spring-security-announcing
|
slack-announcing-id: spring-security-announcing
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
send-notification:
|
||||||
|
name: Send Notification
|
||||||
|
needs: [ perform-release ]
|
||||||
|
if: ${{ !success() }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Send Notification
|
||||||
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
|
with:
|
||||||
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
upgrade_wrapper:
|
upgrade_wrapper:
|
||||||
name: Execution
|
name: Execution
|
||||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Git configuration
|
- name: Set up Git configuration
|
||||||
@@ -20,14 +19,14 @@ jobs:
|
|||||||
git config --global user.name 'github-actions[bot]'
|
git config --global user.name 'github-actions[bot]'
|
||||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@v4
|
||||||
- name: Set up JDK 25
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '25'
|
java-version: '17'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
- name: Set up Gradle
|
- name: Set up Gradle
|
||||||
uses: gradle/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # v5.0.1
|
uses: gradle/gradle-build-action@v2
|
||||||
- name: Upgrade Wrappers
|
- name: Upgrade Wrappers
|
||||||
run: ./gradlew clean upgradeGradleWrapperAll --continue -Porg.gradle.java.installations.auto-download=false
|
run: ./gradlew clean upgradeGradleWrapperAll --continue -Porg.gradle.java.installations.auto-download=false
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -30,6 +30,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send Notification
|
- name: Send Notification
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
with:
|
with:
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@v4
|
||||||
- name: Set up gradle
|
- name: Set up gradle
|
||||||
uses: spring-io/spring-gradle-build-action@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
|
uses: spring-io/spring-gradle-build-action@v2
|
||||||
with:
|
with:
|
||||||
java-version: '25'
|
java-version: '17'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew clean build -PskipCheckExpectedBranchVersion --continue --scan
|
run: ./gradlew clean build -PskipCheckExpectedBranchVersion --continue --scan
|
||||||
@@ -24,17 +24,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@v4
|
||||||
- name: Set up gradle
|
- name: Set up gradle
|
||||||
uses: spring-io/spring-gradle-build-action@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
|
uses: spring-io/spring-gradle-build-action@v2
|
||||||
with:
|
with:
|
||||||
java-version: '25'
|
java-version: '17'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
- name: Run Antora
|
- name: Run Antora
|
||||||
run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora
|
run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora
|
||||||
- name: Upload Docs
|
- name: Upload Docs
|
||||||
id: upload
|
id: upload
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: docs
|
name: docs
|
||||||
path: docs/build/site
|
path: docs/build/site
|
||||||
@@ -46,6 +46,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send Notification
|
- name: Send Notification
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
with:
|
with:
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# List of active maintenance branches.
|
# List of active maintenance branches.
|
||||||
branch: [ main, 7.0.x, 6.5.x, 6.4.x, 6.3.x ]
|
branch: [ main, 6.5.x, 6.4.x, 6.3.x ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
- name: Dispatch
|
- name: Dispatch
|
||||||
|
|||||||
@@ -12,25 +12,23 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-antora-ui-spring:
|
update-antora-ui-spring:
|
||||||
name: Update on Supported Branches
|
|
||||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
name: Update on Supported Branches
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
branch: [ '6.5.x', '7.0.x', 'main' ]
|
branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
|
||||||
steps:
|
steps:
|
||||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf
|
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||||
name: Update
|
name: Update
|
||||||
with:
|
with:
|
||||||
docs-branch: ${{ matrix.branch }}
|
docs-branch: ${{ matrix.branch }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
antora-file-path: 'docs/antora-playbook.yml'
|
antora-file-path: 'docs/antora-playbook.yml'
|
||||||
update-antora-ui-spring-docs-build:
|
update-antora-ui-spring-docs-build:
|
||||||
name: Update on docs-build
|
|
||||||
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
name: Update on docs-build
|
||||||
steps:
|
steps:
|
||||||
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf
|
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
|
||||||
name: Update
|
name: Update
|
||||||
with:
|
with:
|
||||||
docs-branch: 'docs-build'
|
docs-branch: 'docs-build'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
update-scheduled-release-version:
|
update-scheduled-release-version:
|
||||||
name: Update Scheduled Release Version
|
name: Update Scheduled Release Version
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@v1
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
send-notification:
|
send-notification:
|
||||||
name: Send Notification
|
name: Send Notification
|
||||||
@@ -18,6 +18,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send Notification
|
- name: Send Notification
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
with:
|
with:
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
@@ -3,4 +3,4 @@
|
|||||||
# See https://sdkman.io/usage#config
|
# See https://sdkman.io/usage#config
|
||||||
# A summary is to add the following to ~/.sdkman/etc/config
|
# A summary is to add the following to ~/.sdkman/etc/config
|
||||||
# sdkman_auto_env=true
|
# sdkman_auto_env=true
|
||||||
java=25-librca
|
java=17.0.3-tem
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"java.gradle.buildServer.enabled": "off"
|
"java.import.gradle.enabled": false
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -31,7 +31,7 @@ If you have a question, check Stack Overflow using
|
|||||||
https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags].
|
https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags].
|
||||||
Find an existing discussion, or start a new one if necessary.
|
Find an existing discussion, or start a new one if necessary.
|
||||||
|
|
||||||
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
|
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
|
||||||
Reading those discussions helps you to learn about the issue, and helps us to make a decision.
|
Reading those discussions helps you to learn about the issue, and helps us to make a decision.
|
||||||
|
|
||||||
[[find-an-issue]]
|
[[find-an-issue]]
|
||||||
@@ -94,7 +94,7 @@ Don't worry if you don't get them all correct the first time, we will help you.
|
|||||||
|
|
||||||
1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
|
1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
|
||||||
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
|
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
|
||||||
2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier to discuss with the team first to determine the right fix or enhancement.
|
2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier discuss with the team first to determine the right fix or enhancement.
|
||||||
For typos and straightforward bug fixes, starting with a pull request is encouraged.
|
For typos and straightforward bug fixes, starting with a pull request is encouraged.
|
||||||
Please include a description for context and motivation.
|
Please include a description for context and motivation.
|
||||||
Note that the team may close your pull request if it's not a fit for the project.
|
Note that the team may close your pull request if it's not a fit for the project.
|
||||||
|
|||||||
-21
@@ -68,27 +68,6 @@ The https://github.com/spring-projects/spring-security/tree/docs-build[playbook
|
|||||||
|
|
||||||
Discover more commands with `./gradlew tasks`.
|
Discover more commands with `./gradlew tasks`.
|
||||||
|
|
||||||
=== IDE setup (IntelliJ)
|
|
||||||
|
|
||||||
No special steps are needed to open Spring Security in IntelliJ.
|
|
||||||
|
|
||||||
=== IDE setup (Eclipse and VS Code)
|
|
||||||
|
|
||||||
To work in Eclipse or VS Code, first generate Eclipse metadata so you can import the project into Eclipse or VS Code:
|
|
||||||
|
|
||||||
[indent=0]
|
|
||||||
----
|
|
||||||
./gradlew cleanEclipse eclipse
|
|
||||||
----
|
|
||||||
|
|
||||||
If you have not built the project yet, run `./gradlew publishToMavenLocal` first so dependencies are resolved.
|
|
||||||
|
|
||||||
*VS Code:* Open the repository root as a folder. The repository includes `.vscode/settings.json` which disables automatic Gradle import so that the generated Eclipse metadata (`.classpath`, `.project`) is used. Do not use the Gradle for Java extension to import the project.
|
|
||||||
|
|
||||||
*Eclipse:* File → Import → General → Existing Projects into Workspace, then select the repository root.
|
|
||||||
|
|
||||||
The build uses a custom Eclipse plugin to work around Gradle dependency cycles that confuse IDE metadata generation. You may see Eclipse warnings about `xml-apis` from some test dependencies; those are excluded in the build and can be ignored.
|
|
||||||
|
|
||||||
== Getting Support
|
== Getting Support
|
||||||
Check out the https://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow].
|
Check out the https://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow].
|
||||||
https://spring.io/support[Commercial support] is available too.
|
https://spring.io/support[Commercial support] is available too.
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
plugins {
|
|
||||||
id 'compile-warnings-error'
|
|
||||||
id 'javadoc-warnings-error'
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
+1
-2
@@ -31,7 +31,6 @@ import org.jspecify.annotations.Nullable;
|
|||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;
|
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sources method security metadata from major JSR 250 security annotations.
|
* Sources method security metadata from major JSR 250 security annotations.
|
||||||
@@ -109,7 +108,7 @@ public class Jsr250MethodSecurityMetadataSource extends AbstractFallbackMethodSe
|
|||||||
if (role == null) {
|
if (role == null) {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
if (!StringUtils.hasLength(this.defaultRolePrefix)) {
|
if (this.defaultRolePrefix == null || this.defaultRolePrefix.length() == 0) {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
if (role.startsWith(this.defaultRolePrefix)) {
|
if (role.startsWith(this.defaultRolePrefix)) {
|
||||||
|
|||||||
+1
-3
@@ -53,9 +53,7 @@ import org.springframework.util.CollectionUtils;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @deprecated Use
|
* @deprecated Use {@link EnableMethodSecurity} or publish interceptors directly
|
||||||
* <code>org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity</code>
|
|
||||||
* or publish interceptors directly
|
|
||||||
*/
|
*/
|
||||||
@NullUnmarked
|
@NullUnmarked
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ interface EvaluationContextPostProcessor<I> {
|
|||||||
* that was passed in.
|
* that was passed in.
|
||||||
* @param context the original {@link EvaluationContext}
|
* @param context the original {@link EvaluationContext}
|
||||||
* @param invocation the security invocation object (i.e. Message)
|
* @param invocation the security invocation object (i.e. Message)
|
||||||
* @return the updated context.
|
* @return the upated context.
|
||||||
*/
|
*/
|
||||||
EvaluationContext postProcess(EvaluationContext context, I invocation);
|
EvaluationContext postProcess(EvaluationContext context, I invocation);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
plugins {
|
|
||||||
id 'compile-warnings-error'
|
|
||||||
id 'javadoc-warnings-error'
|
|
||||||
id 'security-nullability'
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.security.access.PermissionEvaluator;
|
import org.springframework.security.access.PermissionEvaluator;
|
||||||
@@ -45,7 +44,7 @@ import org.springframework.security.core.Authentication;
|
|||||||
/**
|
/**
|
||||||
* Used by Spring Security's expression-based access control implementation to evaluate
|
* Used by Spring Security's expression-based access control implementation to evaluate
|
||||||
* permissions for a particular object using the ACL module. Similar in behaviour to
|
* permissions for a particular object using the ACL module. Similar in behaviour to
|
||||||
* <code> org.springframework.security.acls.AclEntryVoter AclEntryVoter </code>
|
* {@link org.springframework.security.acls.AclEntryVoter AclEntryVoter}.
|
||||||
*
|
*
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
@@ -74,7 +73,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
|
|||||||
* be overridden using a null check in the expression itself).
|
* be overridden using a null check in the expression itself).
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPermission(Authentication authentication, @Nullable Object domainObject, Object permission) {
|
public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
|
||||||
if (domainObject == null) {
|
if (domainObject == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.acls.aot.hint;
|
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.aot.hint.MemberCategory;
|
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
|
||||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
|
||||||
import org.springframework.aot.hint.TypeReference;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.security.acls.domain.AclImpl;
|
|
||||||
import org.springframework.security.acls.domain.AuditLogger;
|
|
||||||
import org.springframework.security.acls.domain.BasePermission;
|
|
||||||
import org.springframework.security.acls.domain.GrantedAuthoritySid;
|
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
|
||||||
import org.springframework.security.acls.domain.PrincipalSid;
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
|
||||||
import org.springframework.security.acls.model.Acl;
|
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
|
||||||
import org.springframework.security.acls.model.Sid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link RuntimeHintsRegistrar} for ACL (Access Control List) classes.
|
|
||||||
*
|
|
||||||
* @author Josh Long
|
|
||||||
*/
|
|
||||||
class AclRuntimeHints implements RuntimeHintsRegistrar {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
|
||||||
registerAclDomainHints(hints);
|
|
||||||
registerJdbcSchemaHints(hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerAclDomainHints(RuntimeHints hints) {
|
|
||||||
// Register core ACL domain types
|
|
||||||
Stream
|
|
||||||
.of(Acl.class, AccessControlEntry.class, AuditableAccessControlEntry.class, ObjectIdentity.class, Sid.class,
|
|
||||||
AclImpl.class, AccessControlEntry.class, AuditLogger.class, ObjectIdentityImpl.class,
|
|
||||||
PrincipalSid.class, GrantedAuthoritySid.class, BasePermission.class)
|
|
||||||
.forEach((c) -> hints.reflection()
|
|
||||||
.registerType(TypeReference.of(c),
|
|
||||||
(builder) -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
|
||||||
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.ACCESS_DECLARED_FIELDS)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerJdbcSchemaHints(RuntimeHints hints) {
|
|
||||||
String[] sqlFiles = new String[] { "createAclSchema.sql", "createAclSchemaMySQL.sql",
|
|
||||||
"createAclSchemaOracle.sql", "createAclSchemaPostgres.sql", "createAclSchemaSqlServer.sql",
|
|
||||||
"createAclSchemaWithAclClassIdType.sql", "select.sql" };
|
|
||||||
for (String sqlFile : sqlFiles) {
|
|
||||||
Resource sqlResource = new ClassPathResource(sqlFile);
|
|
||||||
if (sqlResource.exists()) {
|
|
||||||
hints.resources().registerResource(sqlResource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AOT and native image hint support for ACLs.
|
|
||||||
*/
|
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.acls.aot.hint;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
+3
-5
@@ -18,8 +18,6 @@ package org.springframework.security.acls.domain;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
@@ -38,7 +36,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
|
|||||||
|
|
||||||
private Permission permission;
|
private Permission permission;
|
||||||
|
|
||||||
private final @Nullable Serializable id;
|
private final Serializable id;
|
||||||
|
|
||||||
private final Sid sid;
|
private final Sid sid;
|
||||||
|
|
||||||
@@ -48,7 +46,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
|
|||||||
|
|
||||||
private final boolean granting;
|
private final boolean granting;
|
||||||
|
|
||||||
public AccessControlEntryImpl(@Nullable Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
|
public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
|
||||||
boolean auditSuccess, boolean auditFailure) {
|
boolean auditSuccess, boolean auditFailure) {
|
||||||
Assert.notNull(acl, "Acl required");
|
Assert.notNull(acl, "Acl required");
|
||||||
Assert.notNull(sid, "Sid required");
|
Assert.notNull(sid, "Sid required");
|
||||||
@@ -135,7 +133,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Serializable getId() {
|
public Serializable getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+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
|
* Strategy used by {@link AclImpl} to determine whether a principal is permitted to call
|
||||||
* administrative methods on the <code>AclImpl</code>.
|
* adminstrative methods on the <code>AclImpl</code>.
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
|
|||||||
+3
-4
@@ -99,8 +99,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
|||||||
Authentication authentication = context.getAuthentication();
|
Authentication authentication = context.getAuthentication();
|
||||||
// Check if authorized by virtue of ACL ownership
|
// Check if authorized by virtue of ACL ownership
|
||||||
Sid currentUser = createCurrentUser(authentication);
|
Sid currentUser = createCurrentUser(authentication);
|
||||||
Sid owner = acl.getOwner();
|
if (currentUser.equals(acl.getOwner())
|
||||||
if (owner != null && currentUser.equals(owner)
|
|
||||||
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -109,8 +108,8 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
|||||||
Collection<? extends GrantedAuthority> reachableGrantedAuthorities = this.roleHierarchy
|
Collection<? extends GrantedAuthority> reachableGrantedAuthorities = this.roleHierarchy
|
||||||
.getReachableGrantedAuthorities(authentication.getAuthorities());
|
.getReachableGrantedAuthorities(authentication.getAuthorities());
|
||||||
Set<String> authorities = AuthorityUtils.authorityListToSet(reachableGrantedAuthorities);
|
Set<String> authorities = AuthorityUtils.authorityListToSet(reachableGrantedAuthorities);
|
||||||
if (owner instanceof GrantedAuthoritySid
|
if (acl.getOwner() instanceof GrantedAuthoritySid
|
||||||
&& authorities.contains(((GrantedAuthoritySid) owner).getGrantedAuthority())) {
|
&& authorities.contains(((GrantedAuthoritySid) acl.getOwner()).getGrantedAuthority())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import java.io.Serializable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.security.acls.model.AccessControlEntry;
|
import org.springframework.security.acls.model.AccessControlEntry;
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AuditableAcl;
|
import org.springframework.security.acls.model.AuditableAcl;
|
||||||
@@ -43,7 +41,7 @@ import org.springframework.util.ObjectUtils;
|
|||||||
*/
|
*/
|
||||||
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||||
|
|
||||||
private @Nullable Acl parentAcl;
|
private Acl parentAcl;
|
||||||
|
|
||||||
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||||
|
|
||||||
@@ -56,10 +54,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
private Serializable id;
|
private Serializable id;
|
||||||
|
|
||||||
// OwnershipAcl
|
// OwnershipAcl
|
||||||
private @Nullable Sid owner;
|
private Sid owner;
|
||||||
|
|
||||||
// includes all SIDs the WHERE clause covered, even if there was no ACE for a SID
|
// includes all SIDs the WHERE clause covered, even if there was no ACE for a SID
|
||||||
private @Nullable List<Sid> loadedSids = null;
|
private List<Sid> loadedSids = null;
|
||||||
|
|
||||||
private boolean entriesInheriting = true;
|
private boolean entriesInheriting = true;
|
||||||
|
|
||||||
@@ -99,8 +97,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
* @param owner the owner (required)
|
* @param owner the owner (required)
|
||||||
*/
|
*/
|
||||||
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
|
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
|
||||||
PermissionGrantingStrategy grantingStrategy, @Nullable Acl parentAcl, @Nullable List<Sid> loadedSids,
|
PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting,
|
||||||
boolean entriesInheriting, Sid owner) {
|
Sid owner) {
|
||||||
Assert.notNull(objectIdentity, "Object Identity required");
|
Assert.notNull(objectIdentity, "Object Identity required");
|
||||||
Assert.notNull(id, "Id required");
|
Assert.notNull(id, "Id required");
|
||||||
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
|
||||||
@@ -119,7 +117,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
* Private no-argument constructor for use by reflection-based persistence tools along
|
* Private no-argument constructor for use by reflection-based persistence tools along
|
||||||
* with field-level access.
|
* with field-level access.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unused", "NullAway.Init" })
|
@SuppressWarnings("unused")
|
||||||
private AclImpl() {
|
private AclImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +199,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSidLoaded(@Nullable List<Sid> sids) {
|
public boolean isSidLoaded(List<Sid> sids) {
|
||||||
// If loadedSides is null, this indicates all SIDs were loaded
|
// If loadedSides is null, this indicates all SIDs were loaded
|
||||||
// Also return true if the caller didn't specify a SID to find
|
// Also return true if the caller didn't specify a SID to find
|
||||||
if ((this.loadedSids == null) || (sids == null) || sids.isEmpty()) {
|
if ((this.loadedSids == null) || (sids == null) || sids.isEmpty()) {
|
||||||
@@ -240,19 +238,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Sid getOwner() {
|
public Sid getOwner() {
|
||||||
return this.owner;
|
return this.owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParent(@Nullable Acl newParent) {
|
public void setParent(Acl newParent) {
|
||||||
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
|
||||||
Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
|
Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
|
||||||
this.parentAcl = newParent;
|
this.parentAcl = newParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Acl getParentAcl() {
|
public Acl getParentAcl() {
|
||||||
return this.parentAcl;
|
return this.parentAcl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class GrantedAuthoritySid implements Sid {
|
|||||||
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
|
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
|
||||||
Assert.notNull(grantedAuthority, "GrantedAuthority required");
|
Assert.notNull(grantedAuthority, "GrantedAuthority required");
|
||||||
Assert.notNull(grantedAuthority.getAuthority(),
|
Assert.notNull(grantedAuthority.getAuthority(),
|
||||||
"This Sid is only compatible with GrantedAuthority that provide a non-null getAuthority()");
|
"This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
|
||||||
this.grantedAuthority = grantedAuthority.getAuthority();
|
this.grantedAuthority = grantedAuthority.getAuthority();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-10
@@ -18,8 +18,6 @@ package org.springframework.security.acls.domain;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.security.acls.model.AclCache;
|
import org.springframework.security.acls.model.AclCache;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
@@ -80,13 +78,13 @@ public class SpringCacheBasedAclCache implements AclCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
||||||
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
Assert.notNull(objectIdentity, "ObjectIdentity required");
|
||||||
return getFromCache((Object) objectIdentity);
|
return getFromCache((Object) objectIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable MutableAcl getFromCache(Serializable pk) {
|
public MutableAcl getFromCache(Serializable pk) {
|
||||||
Assert.notNull(pk, "Primary key (identifier) required");
|
Assert.notNull(pk, "Primary key (identifier) required");
|
||||||
return getFromCache((Object) pk);
|
return getFromCache((Object) pk);
|
||||||
}
|
}
|
||||||
@@ -103,16 +101,12 @@ public class SpringCacheBasedAclCache implements AclCache {
|
|||||||
this.cache.put(acl.getId(), acl);
|
this.cache.put(acl.getId(), acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable MutableAcl getFromCache(Object key) {
|
private MutableAcl getFromCache(Object key) {
|
||||||
Cache.ValueWrapper element = this.cache.get(key);
|
Cache.ValueWrapper element = this.cache.get(key);
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Object value = element.get();
|
return initializeTransientFields((MutableAcl) element.get());
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return initializeTransientFields((MutableAcl) value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableAcl initializeTransientFields(MutableAcl value) {
|
private MutableAcl initializeTransientFields(MutableAcl value) {
|
||||||
|
|||||||
@@ -17,7 +17,4 @@
|
|||||||
/**
|
/**
|
||||||
* Basic implementation of access control lists (ACLs) interfaces.
|
* Basic implementation of access control lists (ACLs) interfaces.
|
||||||
*/
|
*/
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.acls.domain;
|
package org.springframework.security.acls.domain;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
@@ -68,10 +67,10 @@ class AclClassIdUtils {
|
|||||||
* @return The identifier in the appropriate target Java type. Typically Long or UUID.
|
* @return The identifier in the appropriate target Java type. Typically Long or UUID.
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
@Nullable Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
||||||
Class<? extends Serializable> classIdType = classIdTypeFrom(resultSet);
|
if (isString(identifier) && hasValidClassIdType(resultSet)
|
||||||
if (isString(identifier) && classIdType != null && canConvertFromStringTo(classIdType)) {
|
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) {
|
||||||
return convertFromStringTo((String) identifier, classIdType);
|
return convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
|
||||||
}
|
}
|
||||||
// Assume it should be a Long type
|
// Assume it should be a Long type
|
||||||
return convertToLong(identifier);
|
return convertToLong(identifier);
|
||||||
@@ -87,38 +86,28 @@ class AclClassIdUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Class<? extends Serializable> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
||||||
try {
|
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
|
||||||
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
|
|
||||||
}
|
|
||||||
catch (SQLException ex) {
|
|
||||||
log.debug("Unable to obtain the class id type", ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Class<? extends Serializable> classIdTypeFrom(String className) {
|
private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
|
||||||
if (className == null) {
|
if (className == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return Class.forName(className).asSubclass(Serializable.class);
|
return (Class) Class.forName(className);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException ex) {
|
catch (ClassNotFoundException ex) {
|
||||||
log.debug("Unable to find class id type on classpath", ex);
|
log.debug("Unable to find class id type on classpath", ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
catch (ClassCastException ex) {
|
|
||||||
log.debug("Class id type is not a Serializable type", ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> boolean canConvertFromStringTo(Class<T> targetType) {
|
private <T> boolean canConvertFromStringTo(Class<T> targetType) {
|
||||||
return this.conversionService.canConvert(String.class, targetType);
|
return this.conversionService.canConvert(String.class, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Serializable> @Nullable T convertFromStringTo(String identifier, Class<T> targetType) {
|
private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
|
||||||
return this.conversionService.convert(identifier, targetType);
|
return this.conversionService.convert(identifier, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +121,7 @@ class AclClassIdUtils {
|
|||||||
* exception occurred
|
* exception occurred
|
||||||
* @throws IllegalArgumentException if targetType is null
|
* @throws IllegalArgumentException if targetType is null
|
||||||
*/
|
*/
|
||||||
private @Nullable Long convertToLong(Serializable identifier) {
|
private Long convertToLong(Serializable identifier) {
|
||||||
if (this.conversionService.canConvert(identifier.getClass(), Long.class)) {
|
if (this.conversionService.canConvert(identifier.getClass(), Long.class)) {
|
||||||
return this.conversionService.convert(identifier, Long.class);
|
return this.conversionService.convert(identifier, Long.class);
|
||||||
}
|
}
|
||||||
@@ -151,10 +140,10 @@ class AclClassIdUtils {
|
|||||||
private static class StringToLongConverter implements Converter<String, Long> {
|
private static class StringToLongConverter implements Converter<String, Long> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long convert(@Nullable String identifierAsString) {
|
public Long convert(String identifierAsString) {
|
||||||
if (identifierAsString == null) {
|
if (identifierAsString == null) {
|
||||||
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
|
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
|
||||||
TypeDescriptor.valueOf(Long.class), identifierAsString, new NullPointerException());
|
TypeDescriptor.valueOf(Long.class), null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
return Long.parseLong(identifierAsString);
|
return Long.parseLong(identifierAsString);
|
||||||
@@ -165,10 +154,10 @@ class AclClassIdUtils {
|
|||||||
private static class StringToUUIDConverter implements Converter<String, UUID> {
|
private static class StringToUUIDConverter implements Converter<String, UUID> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID convert(@Nullable String identifierAsString) {
|
public UUID convert(String identifierAsString) {
|
||||||
if (identifierAsString == null) {
|
if (identifierAsString == null) {
|
||||||
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
|
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
|
||||||
TypeDescriptor.valueOf(UUID.class), identifierAsString, new NullPointerException());
|
TypeDescriptor.valueOf(UUID.class), null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
return UUID.fromString(identifierAsString);
|
return UUID.fromString(identifierAsString);
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionException;
|
import org.springframework.core.convert.ConversionException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
@@ -226,8 +224,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
* @param findNow Long-based primary keys to retrieve
|
* @param findNow Long-based primary keys to retrieve
|
||||||
* @param sids
|
* @param sids
|
||||||
*/
|
*/
|
||||||
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow,
|
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow, final List<Sid> sids) {
|
||||||
final @Nullable List<Sid> sids) {
|
|
||||||
Assert.notNull(acls, "ACLs are required");
|
Assert.notNull(acls, "ACLs are required");
|
||||||
Assert.notEmpty(findNow, "Items to find now required");
|
Assert.notEmpty(findNow, "Items to find now required");
|
||||||
String sql = computeRepeatingSql(this.lookupPrimaryKeysWhereClause, findNow.size());
|
String sql = computeRepeatingSql(this.lookupPrimaryKeysWhereClause, findNow.size());
|
||||||
@@ -267,7 +264,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
* automatically create entries if required)
|
* automatically create entries if required)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids) {
|
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
|
||||||
Assert.isTrue(this.batchSize >= 1, "BatchSize must be >= 1");
|
Assert.isTrue(this.batchSize >= 1, "BatchSize must be >= 1");
|
||||||
Assert.notEmpty(objects, "Objects to lookup required");
|
Assert.notEmpty(objects, "Objects to lookup required");
|
||||||
// Map<ObjectIdentity,Acl>
|
// Map<ObjectIdentity,Acl>
|
||||||
@@ -326,7 +323,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
* properly-configured parent ACLs.
|
* properly-configured parent ACLs.
|
||||||
*/
|
*/
|
||||||
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities,
|
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities,
|
||||||
@Nullable List<Sid> sids) {
|
List<Sid> sids) {
|
||||||
Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
|
Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
|
||||||
|
|
||||||
// contains Acls with StubAclParents
|
// contains Acls with StubAclParents
|
||||||
@@ -402,10 +399,8 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now we have the parent (if there is one), create the true AclImpl
|
// Now we have the parent (if there is one), create the true AclImpl
|
||||||
Sid owner = inputAcl.getOwner();
|
|
||||||
Assert.isTrue(owner != null, "Owner is required");
|
|
||||||
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), this.aclAuthorizationStrategy,
|
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), this.aclAuthorizationStrategy,
|
||||||
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), owner);
|
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
|
||||||
|
|
||||||
// Copy the "aces" from the input to the destination
|
// Copy the "aces" from the input to the destination
|
||||||
|
|
||||||
@@ -511,9 +506,9 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
|
|
||||||
private final Map<Serializable, Acl> acls;
|
private final Map<Serializable, Acl> acls;
|
||||||
|
|
||||||
private final @Nullable List<Sid> sids;
|
private final List<Sid> sids;
|
||||||
|
|
||||||
ProcessResultSet(Map<Serializable, Acl> acls, @Nullable List<Sid> sids) {
|
ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
|
||||||
Assert.notNull(acls, "ACLs cannot be null");
|
Assert.notNull(acls, "ACLs cannot be null");
|
||||||
this.acls = acls;
|
this.acls = acls;
|
||||||
this.sids = sids; // can be null
|
this.sids = sids; // can be null
|
||||||
@@ -584,9 +579,6 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
// target id type, e.g. UUID.
|
// target id type, e.g. UUID.
|
||||||
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
|
Serializable identifier = (Serializable) rs.getObject("object_id_identity");
|
||||||
identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs);
|
identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs);
|
||||||
if (identifier == null) {
|
|
||||||
throw new IllegalStateException("Identifier cannot be null");
|
|
||||||
}
|
|
||||||
ObjectIdentity objectIdentity = BasicLookupStrategy.this.objectIdentityGenerator
|
ObjectIdentity objectIdentity = BasicLookupStrategy.this.objectIdentityGenerator
|
||||||
.createObjectIdentity(identifier, rs.getString("class"));
|
.createObjectIdentity(identifier, rs.getString("class"));
|
||||||
|
|
||||||
@@ -678,7 +670,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSidLoaded(@Nullable List<Sid> sids) {
|
public boolean isSidLoaded(List<Sid> sids) {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import javax.sql.DataSource;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.jdbc.core.JdbcOperations;
|
import org.springframework.jdbc.core.JdbcOperations;
|
||||||
@@ -99,7 +98,7 @@ public class JdbcAclService implements AclService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
||||||
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
|
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
|
||||||
List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql,
|
List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql,
|
||||||
(rs, rowNum) -> mapObjectIdentityRow(rs), args);
|
(rs, rowNum) -> mapObjectIdentityRow(rs), args);
|
||||||
@@ -110,14 +109,11 @@ public class JdbcAclService implements AclService {
|
|||||||
String javaType = rs.getString("class");
|
String javaType = rs.getString("class");
|
||||||
Serializable identifier = (Serializable) rs.getObject("obj_id");
|
Serializable identifier = (Serializable) rs.getObject("obj_id");
|
||||||
identifier = this.aclClassIdUtils.identifierFrom(identifier, rs);
|
identifier = this.aclClassIdUtils.identifierFrom(identifier, rs);
|
||||||
if (identifier == null) {
|
|
||||||
throw new IllegalStateException("Identifier cannot be null");
|
|
||||||
}
|
|
||||||
return this.objectIdentityGenerator.createObjectIdentity(identifier, javaType);
|
return this.objectIdentityGenerator.createObjectIdentity(identifier, javaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Acl readAclById(ObjectIdentity object, @Nullable List<Sid> sids) throws NotFoundException {
|
public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
|
||||||
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
|
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
|
||||||
Assert.isTrue(map.containsKey(object),
|
Assert.isTrue(map.containsKey(object),
|
||||||
() -> "There should have been an Acl entry for ObjectIdentity " + object);
|
() -> "There should have been an Acl entry for ObjectIdentity " + object);
|
||||||
@@ -135,7 +131,7 @@ public class JdbcAclService implements AclService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids)
|
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids);
|
Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids);
|
||||||
// Check every requested object identity was found (throw NotFoundException if
|
// Check every requested object identity was found (throw NotFoundException if
|
||||||
@@ -164,7 +160,7 @@ public class JdbcAclService implements AclService {
|
|||||||
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
|
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.debug("Find children statement has already been overridden, so not overriding the default");
|
log.debug("Find children statement has already been overridden, so not overridding the default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-42
@@ -22,8 +22,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||||
import org.springframework.security.acls.domain.AccessControlEntryImpl;
|
import org.springframework.security.acls.domain.AccessControlEntryImpl;
|
||||||
@@ -52,7 +50,7 @@ import org.springframework.util.Assert;
|
|||||||
* The default settings are for HSQLDB. If you are using a different database you will
|
* 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
|
* probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and
|
||||||
* {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The
|
* {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The
|
||||||
* other queries, SQL inserts and updates can also be customized to accommodate schema
|
* other queries, SQL inserts and updates can also be customized to accomodate schema
|
||||||
* variations, but must produce results consistent with those expected by the defaults.
|
* variations, but must produce results consistent with those expected by the defaults.
|
||||||
* <p>
|
* <p>
|
||||||
* See the appendix of the Spring Security reference manual for more information on the
|
* See the appendix of the Spring Security reference manual for more information on the
|
||||||
@@ -122,7 +120,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
// Need to retrieve the current principal, in order to know who "owns" this ACL
|
// Need to retrieve the current principal, in order to know who "owns" this ACL
|
||||||
// (can be changed later on)
|
// (can be changed later on)
|
||||||
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
|
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||||
Assert.isTrue(auth != null, "Authentication required");
|
|
||||||
PrincipalSid sid = new PrincipalSid(auth);
|
PrincipalSid sid = new PrincipalSid(auth);
|
||||||
|
|
||||||
// Create the acl_object_identity row
|
// Create the acl_object_identity row
|
||||||
@@ -158,12 +155,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
|
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
|
||||||
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
|
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
|
||||||
|
|
||||||
Assert.state(acl.getId() != null, "ACL ID cannot be null");
|
|
||||||
stmt.setLong(1, (Long) acl.getId());
|
stmt.setLong(1, (Long) acl.getId());
|
||||||
stmt.setInt(2, i);
|
stmt.setInt(2, i);
|
||||||
Long sidPrimaryKey = createOrRetrieveSidPrimaryKey(entry.getSid(), true);
|
stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true));
|
||||||
Assert.state(sidPrimaryKey != null, "SID primary key cannot be null");
|
|
||||||
stmt.setLong(3, sidPrimaryKey);
|
|
||||||
stmt.setInt(4, entry.getPermission().getMask());
|
stmt.setInt(4, entry.getPermission().getMask());
|
||||||
stmt.setBoolean(5, entry.isGranting());
|
stmt.setBoolean(5, entry.isGranting());
|
||||||
stmt.setBoolean(6, entry.isAuditSuccess());
|
stmt.setBoolean(6, entry.isAuditSuccess());
|
||||||
@@ -195,14 +189,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* @param allowCreate true if creation is permitted if not found
|
* @param allowCreate true if creation is permitted if not found
|
||||||
* @return the primary key or null if not found
|
* @return the primary key or null if not found
|
||||||
*/
|
*/
|
||||||
protected @Nullable Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
||||||
List<@Nullable Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
|
List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
|
||||||
|
|
||||||
if (!classIds.isEmpty()) {
|
if (!classIds.isEmpty()) {
|
||||||
Long result = classIds.get(0);
|
return classIds.get(0);
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowCreate) {
|
if (allowCreate) {
|
||||||
@@ -213,9 +204,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
this.jdbcOperations.update(this.insertClass, type, idType.getCanonicalName());
|
this.jdbcOperations.update(this.insertClass, type, idType.getCanonicalName());
|
||||||
}
|
}
|
||||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||||
Long result = this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
|
return this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
|
||||||
Assert.state(result != null, "Failed to retrieve class primary key");
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -230,7 +219,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
|
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
|
||||||
* implementation.
|
* implementation.
|
||||||
*/
|
*/
|
||||||
protected @Nullable Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
||||||
Assert.notNull(sid, "Sid required");
|
Assert.notNull(sid, "Sid required");
|
||||||
if (sid instanceof PrincipalSid) {
|
if (sid instanceof PrincipalSid) {
|
||||||
String sidName = ((PrincipalSid) sid).getPrincipal();
|
String sidName = ((PrincipalSid) sid).getPrincipal();
|
||||||
@@ -251,22 +240,16 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* @param allowCreate true if creation is permitted if not found
|
* @param allowCreate true if creation is permitted if not found
|
||||||
* @return the primary key or null if not found
|
* @return the primary key or null if not found
|
||||||
*/
|
*/
|
||||||
protected @Nullable Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal,
|
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
|
||||||
boolean allowCreate) {
|
List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class, sidIsPrincipal,
|
||||||
List<@Nullable Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class,
|
sidName);
|
||||||
sidIsPrincipal, sidName);
|
|
||||||
if (!sidIds.isEmpty()) {
|
if (!sidIds.isEmpty()) {
|
||||||
Long result = sidIds.get(0);
|
return sidIds.get(0);
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (allowCreate) {
|
if (allowCreate) {
|
||||||
this.jdbcOperations.update(this.insertSid, sidIsPrincipal, sidName);
|
this.jdbcOperations.update(this.insertSid, sidIsPrincipal, sidName);
|
||||||
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
|
||||||
Long result = this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
|
return this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
|
||||||
Assert.state(result != null, "Failed to retrieve sid primary key");
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -296,9 +279,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
}
|
}
|
||||||
|
|
||||||
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
|
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
|
||||||
if (oidPrimaryKey == null) {
|
|
||||||
throw new NotFoundException("Object identity not found: " + objectIdentity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete this ACL's ACEs in the acl_entry table
|
// Delete this ACL's ACEs in the acl_entry table
|
||||||
deleteEntries(oidPrimaryKey);
|
deleteEntries(oidPrimaryKey);
|
||||||
@@ -339,11 +319,10 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
* @param oid to find
|
* @param oid to find
|
||||||
* @return the object identity or null if not found
|
* @return the object identity or null if not found
|
||||||
*/
|
*/
|
||||||
protected @Nullable Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
||||||
try {
|
try {
|
||||||
Long result = this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class,
|
return this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, oid.getType(),
|
||||||
oid.getType(), oid.getIdentifier().toString());
|
oid.getIdentifier().toString());
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
catch (DataAccessException notFound) {
|
catch (DataAccessException notFound) {
|
||||||
return null;
|
return null;
|
||||||
@@ -361,11 +340,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
|
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
|
||||||
|
|
||||||
// Delete this ACL's ACEs in the acl_entry table
|
// Delete this ACL's ACEs in the acl_entry table
|
||||||
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity());
|
deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()));
|
||||||
if (oidPrimaryKey == null) {
|
|
||||||
throw new NotFoundException("Object identity not found for ACL: " + acl.getObjectIdentity());
|
|
||||||
}
|
|
||||||
deleteEntries(oidPrimaryKey);
|
|
||||||
|
|
||||||
// Create this ACL's ACEs in the acl_entry table
|
// Create this ACL's ACEs in the acl_entry table
|
||||||
createEntries(acl);
|
createEntries(acl);
|
||||||
@@ -496,7 +471,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
|||||||
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
|
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.debug("Insert class statement has already been overridden, so not overriding the default");
|
log.debug("Insert class statement has already been overridden, so not overridding the default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package org.springframework.security.acls.jdbc;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.NotFoundException;
|
import org.springframework.security.acls.model.NotFoundException;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
@@ -44,6 +42,6 @@ public interface LookupStrategy {
|
|||||||
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
|
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
|
||||||
* automatically create entries if required)
|
* automatically create entries if required)
|
||||||
*/
|
*/
|
||||||
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids);
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,4 @@
|
|||||||
/**
|
/**
|
||||||
* JDBC-based persistence of ACL information
|
* JDBC-based persistence of ACL information
|
||||||
*/
|
*/
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an individual permission assignment within an {@link Acl}.
|
* Represents an individual permission assignment within an {@link Acl}.
|
||||||
*
|
*
|
||||||
@@ -38,7 +36,7 @@ public interface AccessControlEntry extends Serializable {
|
|||||||
* Obtains an identifier that represents this ACE.
|
* Obtains an identifier that represents this ACE.
|
||||||
* @return the identifier, or <code>null</code> if unsaved
|
* @return the identifier, or <code>null</code> if unsaved
|
||||||
*/
|
*/
|
||||||
@Nullable Serializable getId();
|
Serializable getId();
|
||||||
|
|
||||||
Permission getPermission();
|
Permission getPermission();
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package org.springframework.security.acls.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an access control list (ACL) for a domain object.
|
* Represents an access control list (ACL) for a domain object.
|
||||||
*
|
*
|
||||||
@@ -84,7 +82,7 @@ public interface Acl extends Serializable {
|
|||||||
* @return the owner (may be <tt>null</tt> if the implementation does not use
|
* @return the owner (may be <tt>null</tt> if the implementation does not use
|
||||||
* ownership concepts)
|
* ownership concepts)
|
||||||
*/
|
*/
|
||||||
@Nullable Sid getOwner();
|
Sid getOwner();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A domain object may have a parent for the purpose of ACL inheritance. If there is a
|
* A domain object may have a parent for the purpose of ACL inheritance. If there is a
|
||||||
@@ -105,7 +103,7 @@ public interface Acl extends Serializable {
|
|||||||
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
|
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
|
||||||
* have a parent)
|
* have a parent)
|
||||||
*/
|
*/
|
||||||
@Nullable Acl getParentAcl();
|
Acl getParentAcl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down
|
* Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down
|
||||||
@@ -191,6 +189,6 @@ public interface Acl extends Serializable {
|
|||||||
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
|
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
|
||||||
* <tt>Acl</tt> instance
|
* <tt>Acl</tt> instance
|
||||||
*/
|
*/
|
||||||
boolean isSidLoaded(@Nullable List<Sid> sids);
|
boolean isSidLoaded(List<Sid> sids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.security.acls.jdbc.JdbcAclService;
|
import org.springframework.security.acls.jdbc.JdbcAclService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,9 +31,9 @@ public interface AclCache {
|
|||||||
|
|
||||||
void evictFromCache(ObjectIdentity objectIdentity);
|
void evictFromCache(ObjectIdentity objectIdentity);
|
||||||
|
|
||||||
@Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity);
|
MutableAcl getFromCache(ObjectIdentity objectIdentity);
|
||||||
|
|
||||||
@Nullable MutableAcl getFromCache(Serializable pk);
|
MutableAcl getFromCache(Serializable pk);
|
||||||
|
|
||||||
void putInCache(MutableAcl acl);
|
void putInCache(MutableAcl acl);
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package org.springframework.security.acls.model;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides retrieval of {@link Acl} instances.
|
* Provides retrieval of {@link Acl} instances.
|
||||||
*
|
*
|
||||||
@@ -34,7 +32,7 @@ public interface AclService {
|
|||||||
* @param parentIdentity to locate children of
|
* @param parentIdentity to locate children of
|
||||||
* @return the children (or <tt>null</tt> if none were found)
|
* @return the children (or <tt>null</tt> if none were found)
|
||||||
*/
|
*/
|
||||||
@Nullable List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
|
List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #readAclsById(List)} except it returns only a single Acl.
|
* Same as {@link #readAclsById(List)} except it returns only a single Acl.
|
||||||
@@ -61,7 +59,7 @@ public interface AclService {
|
|||||||
* @throws NotFoundException if an {@link Acl} was not found for the requested
|
* @throws NotFoundException if an {@link Acl} was not found for the requested
|
||||||
* {@link ObjectIdentity}
|
* {@link ObjectIdentity}
|
||||||
*/
|
*/
|
||||||
Acl readAclById(ObjectIdentity object, @Nullable List<Sid> sids) throws NotFoundException;
|
Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s.
|
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s.
|
||||||
@@ -100,7 +98,6 @@ public interface AclService {
|
|||||||
* @throws NotFoundException if an {@link Acl} was not found for each requested
|
* @throws NotFoundException if an {@link Acl} was not found for each requested
|
||||||
* {@link ObjectIdentity}
|
* {@link ObjectIdentity}
|
||||||
*/
|
*/
|
||||||
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids)
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException;
|
||||||
throws NotFoundException;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,4 @@
|
|||||||
* Interfaces and shared classes to manage access control lists (ACLs) for domain object
|
* Interfaces and shared classes to manage access control lists (ACLs) for domain object
|
||||||
* instances.
|
* instances.
|
||||||
*/
|
*/
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.acls.model;
|
package org.springframework.security.acls.model;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
|
|||||||
@@ -24,7 +24,4 @@
|
|||||||
* older and more verbose attribute/voter/after-invocation approach from versions before
|
* older and more verbose attribute/voter/after-invocation approach from versions before
|
||||||
* Spring Security 3.0.
|
* Spring Security 3.0.
|
||||||
*/
|
*/
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.acls;
|
package org.springframework.security.acls;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
org.springframework.aot.hint.RuntimeHintsRegistrar=\
|
|
||||||
org.springframework.security.acls.aot.hint.AclRuntimeHints
|
|
||||||
@@ -478,7 +478,6 @@ public class AclImplTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void hashCodeWithoutStackOverFlow() throws Exception {
|
public void hashCodeWithoutStackOverFlow() throws Exception {
|
||||||
Sid sid = new PrincipalSid("pSid");
|
Sid sid = new PrincipalSid("pSid");
|
||||||
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
|
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.junit.jupiter.api.AfterEach;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.ArgumentMatchers;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
@@ -47,6 +46,7 @@ import org.springframework.security.acls.model.Sid;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyList;
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
@@ -109,8 +109,7 @@ public class JdbcAclServiceTests {
|
|||||||
List<ObjectIdentity> result = new ArrayList<>();
|
List<ObjectIdentity> result = new ArrayList<>();
|
||||||
result.add(new ObjectIdentityImpl(Object.class, "5577"));
|
result.add(new ObjectIdentityImpl(Object.class, "5577"));
|
||||||
Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
|
Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
|
||||||
given(this.jdbcOperations.query(anyString(), ArgumentMatchers.<RowMapper<ObjectIdentity>>any(), eq(args)))
|
given(this.jdbcOperations.query(anyString(), any(RowMapper.class), eq(args))).willReturn(result);
|
||||||
.willReturn(result);
|
|
||||||
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
|
||||||
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
|
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
|
||||||
assertThat(objectIdentities).hasSize(1);
|
assertThat(objectIdentities).hasSize(1);
|
||||||
|
|||||||
+4
-2
@@ -80,10 +80,11 @@ public class SpringCacheBasedAclCacheTests {
|
|||||||
assertThatIllegalArgumentException().isThrownBy(() -> new SpringCacheBasedAclCache(null, null, null));
|
assertThatIllegalArgumentException().isThrownBy(() -> new SpringCacheBasedAclCache(null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
@Test
|
@Test
|
||||||
public void cacheOperationsAclWithoutParent() {
|
public void cacheOperationsAclWithoutParent() {
|
||||||
Cache cache = getCache();
|
Cache cache = getCache();
|
||||||
Map<?, ?> realCache = (Map<?, ?>) cache.getNativeCache();
|
Map realCache = (Map) cache.getNativeCache();
|
||||||
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
|
||||||
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
|
||||||
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
|
||||||
@@ -115,10 +116,11 @@ public class SpringCacheBasedAclCacheTests {
|
|||||||
assertThat(realCache).isEmpty();
|
assertThat(realCache).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
@Test
|
@Test
|
||||||
public void cacheOperationsAclWithParent() throws Exception {
|
public void cacheOperationsAclWithParent() throws Exception {
|
||||||
Cache cache = getCache();
|
Cache cache = getCache();
|
||||||
Map<?, ?> realCache = (Map<?, ?>) cache.getNativeCache();
|
Map realCache = (Map) cache.getNativeCache();
|
||||||
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
|
||||||
auth.setAuthenticated(true);
|
auth.setAuthenticated(true);
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
apply plugin: 'io.freefair.aspectj'
|
apply plugin: 'io.freefair.aspectj'
|
||||||
apply plugin: 'javadoc-warnings-error'
|
|
||||||
apply plugin: 'compile-warnings-error'
|
|
||||||
|
|
||||||
compileAspectj {
|
compileAspectj {
|
||||||
sourceCompatibility = "17"
|
sourceCompatibility "17"
|
||||||
targetCompatibility = "17"
|
targetCompatibility "17"
|
||||||
ajcOptions.compilerArgs += ['-Xlint:ignore']
|
|
||||||
}
|
}
|
||||||
compileTestAspectj {
|
compileTestAspectj {
|
||||||
sourceCompatibility = "17"
|
sourceCompatibility "17"
|
||||||
targetCompatibility = "17"
|
targetCompatibility "17"
|
||||||
ajcOptions.compilerArgs += ['-Xlint:ignore']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import io.spring.gradle.convention.SpringModulePlugin
|
import io.spring.gradle.convention.SpringModulePlugin
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.bom'
|
apply plugin: 'io.spring.convention.bom'
|
||||||
apply plugin: 'compile-warnings-error'
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
constraints {
|
constraints {
|
||||||
|
|||||||
+37
-12
@@ -1,7 +1,5 @@
|
|||||||
import io.spring.gradle.IncludeRepoTask
|
import io.spring.gradle.IncludeRepoTask
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
||||||
import trang.RncToXsd
|
import trang.RncToXsd
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -12,7 +10,7 @@ buildscript {
|
|||||||
classpath libs.com.netflix.nebula.nebula.project.plugin
|
classpath libs.com.netflix.nebula.nebula.project.plugin
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
maven { url='https://plugins.gradle.org/m2/' }
|
maven { url 'https://plugins.gradle.org/m2/' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,30 +35,57 @@ ext.milestoneBuild = !(snapshotBuild || releaseBuild)
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = "https://repo.spring.io/milestone" }
|
maven { url "https://repo.spring.io/milestone" }
|
||||||
}
|
}
|
||||||
|
|
||||||
springRelease {
|
springRelease {
|
||||||
weekOfMonth = 3
|
weekOfMonth = 3
|
||||||
dayOfWeek = 1
|
dayOfWeek = 1
|
||||||
referenceDocUrl = "https://docs.spring.io/spring-security/reference/{version}/index.html"
|
referenceDocUrl = "https://docs.spring.io/spring-security/reference/{version}/index.html"
|
||||||
apiDocUrl = "https://docs.spring.io/spring-security/reference/{version}/api/java/index.html"
|
apiDocUrl = "https://docs.spring.io/spring-security/site/docs/{version}/api/"
|
||||||
replaceSnapshotVersionInReferenceDocUrl = true
|
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 {
|
allprojects {
|
||||||
if (!['spring-security-bom', 'spring-security-docs'].contains(project.name)) {
|
if (!['spring-security-bom', 'spring-security-docs'].contains(project.name)) {
|
||||||
apply plugin: 'io.spring.javaformat'
|
apply plugin: 'io.spring.javaformat'
|
||||||
apply plugin: 'checkstyle'
|
apply plugin: 'checkstyle'
|
||||||
|
|
||||||
pluginManager.withPlugin("io.spring.convention.checkstyle") {
|
pluginManager.withPlugin("io.spring.convention.checkstyle", { plugin ->
|
||||||
dependencies {
|
configure(plugin) {
|
||||||
checkstyle libs.io.spring.javaformat.spring.javaformat.checkstyle
|
dependencies {
|
||||||
|
checkstyle libs.io.spring.javaformat.spring.javaformat.checkstyle
|
||||||
|
}
|
||||||
|
checkstyle {
|
||||||
|
toolVersion = '8.34'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
checkstyle {
|
})
|
||||||
toolVersion = '8.34'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (project.name.contains('sample')) {
|
if (project.name.contains('sample')) {
|
||||||
tasks.whenTaskAdded { task ->
|
tasks.whenTaskAdded { task ->
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ java {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = 'https://repo.spring.io/snapshot' }
|
maven { url 'https://repo.spring.io/snapshot' }
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -0,0 +1,5 @@
|
|||||||
|
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
|
||||||
+240
@@ -0,0 +1,240 @@
|
|||||||
|
#!/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
@@ -0,0 +1,91 @@
|
|||||||
|
@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
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import org.gradle.api.tasks.compile.JavaCompile
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.compilerArgs += "-Werror"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(KotlinCompile) {
|
|
||||||
kotlinOptions.allWarningsAsErrors = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -81,8 +81,8 @@ class ArtifactoryPlugin implements Plugin<Project> {
|
|||||||
repository {
|
repository {
|
||||||
repoKey = isSnapshot ? snapshotRepository : isMilestone ? milestoneRepository : releaseRepository
|
repoKey = isSnapshot ? snapshotRepository : isMilestone ? milestoneRepository : releaseRepository
|
||||||
if(project.hasProperty('artifactoryUsername')) {
|
if(project.hasProperty('artifactoryUsername')) {
|
||||||
username = project.artifactoryUsername
|
username = artifactoryUsername
|
||||||
password = project.artifactoryPassword
|
password = artifactoryPassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package io.spring.gradle.convention
|
||||||
|
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.api.tasks.bundling.Zip
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
public class DeployDocsPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Project project) {
|
||||||
|
project.getPluginManager().apply('org.hidetake.ssh')
|
||||||
|
|
||||||
|
project.ssh.settings {
|
||||||
|
knownHosts = allowAnyHosts
|
||||||
|
}
|
||||||
|
project.remotes {
|
||||||
|
docs {
|
||||||
|
role 'docs'
|
||||||
|
if (project.hasProperty('deployDocsHost')) {
|
||||||
|
host = project.findProperty('deployDocsHost')
|
||||||
|
} else {
|
||||||
|
host = 'docs.af.pivotal.io'
|
||||||
|
}
|
||||||
|
retryCount = 5 // retry 5 times (default is 0)
|
||||||
|
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
|
||||||
|
user = project.findProperty('deployDocsSshUsername')
|
||||||
|
if (project.hasProperty('deployDocsSshKeyPath')) {
|
||||||
|
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
|
||||||
|
} else if (project.hasProperty('deployDocsSshKey')) {
|
||||||
|
identity = project.findProperty('deployDocsSshKey')
|
||||||
|
}
|
||||||
|
if(project.hasProperty('deployDocsSshPassphrase')) {
|
||||||
|
passphrase = project.findProperty('deployDocsSshPassphrase')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.task('deployDocs') {
|
||||||
|
dependsOn 'docsZip'
|
||||||
|
doFirst {
|
||||||
|
project.ssh.run {
|
||||||
|
session(project.remotes.docs) {
|
||||||
|
def now = System.currentTimeMillis()
|
||||||
|
def name = project.rootProject.name
|
||||||
|
def version = project.rootProject.version
|
||||||
|
def tempPath = "/tmp/${name}-${now}-docs/".replaceAll(' ', '_')
|
||||||
|
execute "mkdir -p $tempPath"
|
||||||
|
|
||||||
|
project.tasks.docsZip.outputs.each { o ->
|
||||||
|
put from: o.files, into: tempPath
|
||||||
|
}
|
||||||
|
|
||||||
|
execute "unzip $tempPath*.zip -d $tempPath"
|
||||||
|
|
||||||
|
def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/docs/${name}/${version}/"
|
||||||
|
|
||||||
|
execute "rm -rf $extractPath"
|
||||||
|
execute "mkdir -p $extractPath"
|
||||||
|
execute "mv $tempPath/docs/* $extractPath"
|
||||||
|
execute "chmod -R g+w $extractPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ public class DocsPlugin implements Plugin<Project> {
|
|||||||
|
|
||||||
PluginManager pluginManager = project.getPluginManager();
|
PluginManager pluginManager = project.getPluginManager();
|
||||||
pluginManager.apply(BasePlugin);
|
pluginManager.apply(BasePlugin);
|
||||||
|
pluginManager.apply(DeployDocsPlugin);
|
||||||
pluginManager.apply(JavadocApiPlugin);
|
pluginManager.apply(JavadocApiPlugin);
|
||||||
|
|
||||||
Task docsZip = project.tasks.create('docsZip', Zip) {
|
Task docsZip = project.tasks.create('docsZip', Zip) {
|
||||||
@@ -31,12 +32,12 @@ public class DocsPlugin implements Plugin<Project> {
|
|||||||
into 'api'
|
into 'api'
|
||||||
}
|
}
|
||||||
into 'docs'
|
into 'docs'
|
||||||
duplicatesStrategy = 'exclude'
|
duplicatesStrategy 'exclude'
|
||||||
}
|
}
|
||||||
|
|
||||||
Task docs = project.tasks.create("docs") {
|
Task docs = project.tasks.create("docs") {
|
||||||
group = 'Documentation'
|
group = 'Documentation'
|
||||||
description = 'An aggregator task to generate all the documentation'
|
description 'An aggregator task to generate all the documentation'
|
||||||
dependsOn docsZip
|
dependsOn docsZip
|
||||||
}
|
}
|
||||||
project.tasks.assemble.dependsOn docs
|
project.tasks.assemble.dependsOn docs
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
|||||||
project.plugins.withType(IdeaPlugin) {
|
project.plugins.withType(IdeaPlugin) {
|
||||||
project.idea {
|
project.idea {
|
||||||
module {
|
module {
|
||||||
testSources.from(project.file('src/integration-test/java'))
|
testSourceDirs += project.file('src/integration-test/java')
|
||||||
scopes.TEST.plus += [ project.configurations.integrationTestCompileClasspath ]
|
scopes.TEST.plus += [ project.configurations.integrationTestCompileClasspath ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
|
|||||||
project.plugins.withType(IdeaPlugin) {
|
project.plugins.withType(IdeaPlugin) {
|
||||||
project.idea {
|
project.idea {
|
||||||
module {
|
module {
|
||||||
testSources.from(project.file('src/integration-test/groovy'))
|
testSourceDirs += project.file('src/integration-test/groovy')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class JacocoPlugin implements Plugin<Project> {
|
|||||||
project.tasks.check.dependsOn project.tasks.jacocoTestReport
|
project.tasks.check.dependsOn project.tasks.jacocoTestReport
|
||||||
|
|
||||||
project.jacoco {
|
project.jacoco {
|
||||||
toolVersion = '0.8.14'
|
toolVersion = '0.8.9'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.gradle.api.Action;
|
|||||||
import org.gradle.api.JavaVersion
|
import org.gradle.api.JavaVersion
|
||||||
import org.gradle.api.Plugin;
|
import org.gradle.api.Plugin;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.plugins.JavaPluginExtension;
|
import org.gradle.api.plugins.JavaPluginConvention;
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
import org.gradle.api.tasks.javadoc.Javadoc;
|
import org.gradle.api.tasks.javadoc.Javadoc;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -71,7 +71,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
api.setMaxMemory("1024m");
|
api.setMaxMemory("1024m");
|
||||||
api.setDestinationDir(project.layout.getBuildDirectory().dir("api").get().getAsFile());
|
api.setDestinationDir(new File(project.getBuildDir(), "api"));
|
||||||
|
|
||||||
project.getPluginManager().apply("io.spring.convention.javadoc-options");
|
project.getPluginManager().apply("io.spring.convention.javadoc-options");
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
|
|||||||
public void execute(SpringModulePlugin plugin) {
|
public void execute(SpringModulePlugin plugin) {
|
||||||
logger.info("Added sources for {}", project);
|
logger.info("Added sources for {}", project);
|
||||||
|
|
||||||
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
|
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
|
||||||
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
|
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
|
||||||
|
|
||||||
api.setSource(api.getSource().plus(mainSourceSet.getAllJava()));
|
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")
|
throw new IllegalStateException("Could not find schema file for resource name " + schemaResourceName + " in src/main/resources")
|
||||||
}
|
}
|
||||||
schemaZip.into (shortName) {
|
schemaZip.into (shortName) {
|
||||||
duplicatesStrategy = 'exclude'
|
duplicatesStrategy 'exclude'
|
||||||
from xsdFile.path
|
from xsdFile.path
|
||||||
}
|
}
|
||||||
versionlessXsd.getInputFiles().from(xsdFile.path)
|
versionlessXsd.getInputFiles().from(xsdFile.path)
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ class SpringModulePlugin extends AbstractSpringJavaPlugin {
|
|||||||
pluginManager.apply(SpringMavenPlugin.class);
|
pluginManager.apply(SpringMavenPlugin.class);
|
||||||
pluginManager.apply(CheckClasspathForProhibitedDependenciesPlugin.class);
|
pluginManager.apply(CheckClasspathForProhibitedDependenciesPlugin.class);
|
||||||
pluginManager.apply("io.spring.convention.jacoco");
|
pluginManager.apply("io.spring.convention.jacoco");
|
||||||
pluginManager.apply("java-toolchain");
|
|
||||||
|
|
||||||
def deployArtifacts = project.task("deployArtifacts")
|
def deployArtifacts = project.task("deployArtifacts")
|
||||||
deployArtifacts.group = 'Deploy tasks'
|
deployArtifacts.group = 'Deploy tasks'
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
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 25
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import org.gradle.api.tasks.javadoc.Javadoc
|
|
||||||
|
|
||||||
project.tasks.withType(Javadoc).configureEach {
|
|
||||||
options.addBooleanOption('Werror', true)
|
|
||||||
// temporarily disable missing to get build to pass with JDK 25
|
|
||||||
options.addStringOption('Xdoclint:all,-missing')
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import org.gradle.api.tasks.compile.JavaCompile
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We need to compile with JDK 25 for nullability support, but using JDK 25 means that our tests will fail due to the
|
|
||||||
* <a href="https://docs.oracle.com/en/java/javase/25/security/security-manager-is-permanently-disabled.html">removal
|
|
||||||
* of the Java Security Manager</a>. For example, in JDK 25 {@code Subject.getSubject(AccessControlContext)} throws an
|
|
||||||
* {@code UnsupportedOperationException}.
|
|
||||||
*
|
|
||||||
* To resolve this, we must migrate tests to use the new APIs (e.g. {@code Subject.current()}) but those APIs are not
|
|
||||||
* available in the JDK 17 source, so compiling with JDK 25 and release 17 fails. The plugin overrides the test
|
|
||||||
* compilation to use release 25.
|
|
||||||
*
|
|
||||||
* @see <a href="https://docs.oracle.com/en/java/javase/25/security/security-manager-is-permanently-disabled.html">The
|
|
||||||
* Security Manager Is Permanently Disabled</a>
|
|
||||||
* @see <a href="https://inside.java/2024/07/08/quality-heads-up/">Quality Outreach Heads-up - JDK 23: Re-Specified
|
|
||||||
* Subject.getSubject API</a>
|
|
||||||
*/
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach { task ->
|
|
||||||
if (task.name == 'compileTestJava' || task.name == 'compileIntegrationTestJava') {
|
|
||||||
task.options.release.set(25)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(KotlinCompile).configureEach { task ->
|
|
||||||
if (task.name == 'compileTestKotlin' || task.name == 'compileIntegrationTestKotlin') {
|
|
||||||
task.kotlinOptions.jvmTarget = '25'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+11
-1
@@ -30,6 +30,16 @@ ossrh: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
docs: {
|
||||||
|
stage('Deploy Docs') {
|
||||||
|
node {
|
||||||
|
checkout scm
|
||||||
|
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||||
|
sh "./gradlew deployDocs -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME --refresh-dependencies --no-daemon --stacktrace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
schema: {
|
schema: {
|
||||||
stage('Deploy Schema') {
|
stage('Deploy Schema') {
|
||||||
node {
|
node {
|
||||||
@@ -39,4 +49,4 @@ schema: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'security-nullability'
|
id 'security-nullability'
|
||||||
id 'javadoc-warnings-error'
|
|
||||||
id 'compile-warnings-error'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|||||||
+2
@@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.apereo.cas.client.validation.Assertion;
|
import org.apereo.cas.client.validation.Assertion;
|
||||||
import org.apereo.cas.client.validation.TicketValidationException;
|
import org.apereo.cas.client.validation.TicketValidationException;
|
||||||
import org.apereo.cas.client.validation.TicketValidator;
|
import org.apereo.cas.client.validation.TicketValidator;
|
||||||
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
@@ -165,6 +166,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
* @param authentication
|
* @param authentication
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@NullUnmarked
|
||||||
private @Nullable String getServiceUrl(Authentication authentication) {
|
private @Nullable String getServiceUrl(Authentication authentication) {
|
||||||
String serviceUrl;
|
String serviceUrl;
|
||||||
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
||||||
|
|||||||
@@ -17,7 +17,4 @@
|
|||||||
/**
|
/**
|
||||||
* Jackson 3+ serialization support for CAS.
|
* Jackson 3+ serialization support for CAS.
|
||||||
*/
|
*/
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.cas.jackson;
|
package org.springframework.security.cas.jackson;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
|
|||||||
+1
-2
@@ -91,8 +91,7 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
|
|||||||
*/
|
*/
|
||||||
protected String createServiceUrl(HttpServletRequest request, HttpServletResponse response) {
|
protected String createServiceUrl(HttpServletRequest request, HttpServletResponse response) {
|
||||||
return WebUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null,
|
return WebUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null,
|
||||||
this.serviceProperties.getServiceParameter(), this.serviceProperties.getArtifactParameter(),
|
this.serviceProperties.getArtifactParameter(), this.encodeServiceUrlWithSessionId);
|
||||||
this.encodeServiceUrlWithSessionId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
/**
|
/**
|
||||||
* Use this {@code RequestMatcher} to match proxy receptor requests. Without setting
|
* Use this {@code RequestMatcher} to match proxy receptor requests. Without setting
|
||||||
* this matcher, {@link CasAuthenticationFilter} will not capture any proxy receptor
|
* this matcher, {@link CasAuthenticationFilter} will not capture any proxy receptor
|
||||||
* requests.
|
* requets.
|
||||||
* @param proxyReceptorMatcher the {@link RequestMatcher} to use
|
* @param proxyReceptorMatcher the {@link RequestMatcher} to use
|
||||||
* @since 6.5
|
* @since 6.5
|
||||||
*/
|
*/
|
||||||
@@ -383,8 +383,8 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the request is eligible to process a service ticket. This method
|
* Indicates if the request is elgible to process a service ticket. This method exists
|
||||||
* exists for readability.
|
* for readability.
|
||||||
* @param request
|
* @param request
|
||||||
* @param response
|
* @param response
|
||||||
* @return
|
* @return
|
||||||
@@ -396,7 +396,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the request is eligible to process a proxy ticket.
|
* Indicates if the request is elgible to process a proxy ticket.
|
||||||
* @param request
|
* @param request
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -419,7 +419,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the request is eligible to be processed as the proxy receptor.
|
* Indicates if the request is elgible to be processed as the proxy receptor.
|
||||||
* @param request
|
* @param request
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
+6
-11
@@ -34,7 +34,6 @@ import org.springframework.util.Assert;
|
|||||||
* and using the current URL minus the artifact and the corresponding value.
|
* and using the current URL minus the artifact and the corresponding value.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @author Ngoc Nhan
|
|
||||||
*/
|
*/
|
||||||
final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
||||||
implements ServiceAuthenticationDetails {
|
implements ServiceAuthenticationDetails {
|
||||||
@@ -75,9 +74,10 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails that)) {
|
if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ServiceAuthenticationDetails that = (ServiceAuthenticationDetails) obj;
|
||||||
return this.serviceUrl.equals(that.getServiceUrl());
|
return this.serviceUrl.equals(that.getServiceUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,11 +101,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
/**
|
/**
|
||||||
* If present, removes the artifactParameterName and the corresponding value from the
|
* If present, removes the artifactParameterName and the corresponding value from the
|
||||||
* query String.
|
* query String.
|
||||||
* @param request the current {@link HttpServletRequest} to obtain the
|
* @param request
|
||||||
* {@link #getServiceUrl()} from.
|
|
||||||
* @param artifactPattern the {@link Pattern} that will be used to clean up the query
|
|
||||||
* string from containing the artifact name and value. This can be created using
|
|
||||||
* {@link #createArtifactPattern(String)}.
|
|
||||||
* @return the query String minus the artifactParameterName and the corresponding
|
* @return the query String minus the artifactParameterName and the corresponding
|
||||||
* value.
|
* value.
|
||||||
*/
|
*/
|
||||||
@@ -115,7 +111,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String result = artifactPattern.matcher(query).replaceFirst("");
|
String result = artifactPattern.matcher(query).replaceFirst("");
|
||||||
if (result.isEmpty()) {
|
if (result.length() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// strip off the trailing & only if the artifact was the first query param
|
// strip off the trailing & only if the artifact was the first query param
|
||||||
@@ -126,9 +122,8 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
* Creates a {@link Pattern} that can be passed into the constructor. This allows the
|
* Creates a {@link Pattern} that can be passed into the constructor. This allows the
|
||||||
* {@link Pattern} to be reused for every instance of
|
* {@link Pattern} to be reused for every instance of
|
||||||
* {@link DefaultServiceAuthenticationDetails}.
|
* {@link DefaultServiceAuthenticationDetails}.
|
||||||
* @param artifactParameterName the artifactParameterName that is removed from the
|
* @param artifactParameterName
|
||||||
* current URL. The result becomes the service url. Cannot be null or an empty String.
|
* @return
|
||||||
* @return a {@link Pattern}
|
|
||||||
*/
|
*/
|
||||||
static Pattern createArtifactPattern(String artifactParameterName) {
|
static Pattern createArtifactPattern(String artifactParameterName) {
|
||||||
Assert.hasLength(artifactParameterName, "artifactParameterName is expected to have a length");
|
Assert.hasLength(artifactParameterName, "artifactParameterName is expected to have a length");
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ import trang.RncToXsd
|
|||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
apply plugin: 'trang'
|
apply plugin: 'trang'
|
||||||
apply plugin: 'security-kotlin'
|
apply plugin: 'security-kotlin'
|
||||||
apply plugin: 'test-compile-target-jdk25'
|
|
||||||
apply plugin: 'compile-warnings-error'
|
|
||||||
apply plugin: 'javadoc-warnings-error'
|
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
opensaml5 {
|
opensaml5 {
|
||||||
@@ -147,14 +144,14 @@ tasks.named('processResources', ProcessResources).configure {
|
|||||||
into 'org/springframework/security/config/'
|
into 'org/springframework/security/config/'
|
||||||
}
|
}
|
||||||
from(rncToXsd) {
|
from(rncToXsd) {
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy DuplicatesStrategy.EXCLUDE
|
||||||
into 'org/springframework/security/config/'
|
into 'org/springframework/security/config/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('sourcesJar', Jar).configure {
|
tasks.named('sourcesJar', Jar).configure {
|
||||||
from(rncToXsd) {
|
from(rncToXsd) {
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy DuplicatesStrategy.EXCLUDE
|
||||||
into 'org/springframework/security/config/'
|
into 'org/springframework/security/config/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-97
@@ -31,7 +31,6 @@ import org.junit.jupiter.api.AfterAll;
|
|||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebDriverException;
|
import org.openqa.selenium.WebDriverException;
|
||||||
@@ -56,7 +55,6 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
@@ -69,7 +67,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*
|
*
|
||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
*/
|
*/
|
||||||
@Disabled
|
@org.junit.jupiter.api.Disabled
|
||||||
class WebAuthnWebDriverTests {
|
class WebAuthnWebDriverTests {
|
||||||
|
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
@@ -84,8 +82,6 @@ class WebAuthnWebDriverTests {
|
|||||||
|
|
||||||
private static final String PASSWORD = "password";
|
private static final String PASSWORD = "password";
|
||||||
|
|
||||||
private String authenticatorId = null;
|
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void startChromeDriverService() throws Exception {
|
static void startChromeDriverService() throws Exception {
|
||||||
driverService = new ChromeDriverService.Builder().usingAnyFreePort().build();
|
driverService = new ChromeDriverService.Builder().usingAnyFreePort().build();
|
||||||
@@ -148,7 +144,7 @@ class WebAuthnWebDriverTests {
|
|||||||
@Test
|
@Test
|
||||||
void loginWhenNoValidAuthenticatorCredentialsThenRejects() {
|
void loginWhenNoValidAuthenticatorCredentialsThenRejects() {
|
||||||
createVirtualAuthenticator(true);
|
createVirtualAuthenticator(true);
|
||||||
this.getAndWait("/", "/login");
|
this.driver.get(this.baseUrl);
|
||||||
this.driver.findElement(signinWithPasskeyButton()).click();
|
this.driver.findElement(signinWithPasskeyButton()).click();
|
||||||
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/login?error"));
|
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/login?error"));
|
||||||
}
|
}
|
||||||
@@ -157,7 +153,7 @@ class WebAuthnWebDriverTests {
|
|||||||
void registerWhenNoLabelThenRejects() {
|
void registerWhenNoLabelThenRejects() {
|
||||||
login();
|
login();
|
||||||
|
|
||||||
this.getAndWait("/webauthn/register");
|
this.driver.get(this.baseUrl + "/webauthn/register");
|
||||||
|
|
||||||
this.driver.findElement(registerPasskeyButton()).click();
|
this.driver.findElement(registerPasskeyButton()).click();
|
||||||
assertHasAlertStartingWith("error", "Error: Passkey Label is required");
|
assertHasAlertStartingWith("error", "Error: Passkey Label is required");
|
||||||
@@ -167,7 +163,7 @@ class WebAuthnWebDriverTests {
|
|||||||
void registerWhenAuthenticatorNoUserVerificationThenRejects() {
|
void registerWhenAuthenticatorNoUserVerificationThenRejects() {
|
||||||
createVirtualAuthenticator(false);
|
createVirtualAuthenticator(false);
|
||||||
login();
|
login();
|
||||||
this.getAndWait("/webauthn/register");
|
this.driver.get(this.baseUrl + "/webauthn/register");
|
||||||
this.driver.findElement(passkeyLabel()).sendKeys("Virtual authenticator");
|
this.driver.findElement(passkeyLabel()).sendKeys("Virtual authenticator");
|
||||||
this.driver.findElement(registerPasskeyButton()).click();
|
this.driver.findElement(registerPasskeyButton()).click();
|
||||||
|
|
||||||
@@ -182,8 +178,7 @@ class WebAuthnWebDriverTests {
|
|||||||
* <li>Step 1: Log in with username / password</li>
|
* <li>Step 1: Log in with username / password</li>
|
||||||
* <li>Step 2: Register a credential from the virtual authenticator</li>
|
* <li>Step 2: Register a credential from the virtual authenticator</li>
|
||||||
* <li>Step 3: Log out</li>
|
* <li>Step 3: Log out</li>
|
||||||
* <li>Step 4: Log in with the authenticator (no allowCredentials)</li>
|
* <li>Step 4: Log in with the authenticator</li>
|
||||||
* <li>Step 5: Log in again with the same authenticator (with allowCredentials)</li>
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@@ -195,7 +190,7 @@ class WebAuthnWebDriverTests {
|
|||||||
login();
|
login();
|
||||||
|
|
||||||
// Step 2: register a credential from the virtual authenticator
|
// Step 2: register a credential from the virtual authenticator
|
||||||
this.getAndWait("/webauthn/register");
|
this.driver.get(this.baseUrl + "/webauthn/register");
|
||||||
this.driver.findElement(passkeyLabel()).sendKeys("Virtual authenticator");
|
this.driver.findElement(passkeyLabel()).sendKeys("Virtual authenticator");
|
||||||
this.driver.findElement(registerPasskeyButton()).click();
|
this.driver.findElement(registerPasskeyButton()).click();
|
||||||
|
|
||||||
@@ -217,58 +212,9 @@ class WebAuthnWebDriverTests {
|
|||||||
logout();
|
logout();
|
||||||
|
|
||||||
// Step 4: log in with the virtual authenticator
|
// Step 4: log in with the virtual authenticator
|
||||||
this.getAndWait("/webauthn/register", "/login");
|
this.driver.get(this.baseUrl + "/webauthn/register");
|
||||||
this.driver.findElement(signinWithPasskeyButton()).click();
|
this.driver.findElement(signinWithPasskeyButton()).click();
|
||||||
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/webauthn/register?continue"));
|
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/webauthn/register?continue"));
|
||||||
|
|
||||||
// Step 5: authenticate while being already logged in
|
|
||||||
// This simulates some use-cases with MFA. Since the user is already logged in,
|
|
||||||
// the "allowCredentials" property is populated
|
|
||||||
this.getAndWait("/login");
|
|
||||||
this.driver.findElement(signinWithPasskeyButton()).click();
|
|
||||||
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void registerWhenAuthenticatorAlreadyRegisteredThenRejects() {
|
|
||||||
createVirtualAuthenticator(true);
|
|
||||||
login();
|
|
||||||
registerAuthenticator("Virtual authenticator");
|
|
||||||
|
|
||||||
// Cannot re-register the same authenticator because excludeCredentials
|
|
||||||
// is not empty and contains the given authenticator
|
|
||||||
this.driver.findElement(passkeyLabel()).sendKeys("Same authenticator");
|
|
||||||
this.driver.findElement(registerPasskeyButton()).click();
|
|
||||||
|
|
||||||
await(() -> assertHasAlertStartingWith("error", "Registration failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void registerSecondAuthenticatorThenSucceeds() {
|
|
||||||
createVirtualAuthenticator(true);
|
|
||||||
login();
|
|
||||||
|
|
||||||
registerAuthenticator("Virtual authenticator");
|
|
||||||
this.getAndWait("/webauthn/register");
|
|
||||||
List<WebElement> passkeyRows = this.driver.findElements(passkeyTableRows());
|
|
||||||
assertThat(passkeyRows).hasSize(1)
|
|
||||||
.first()
|
|
||||||
.extracting((row) -> row.findElement(firstCell()))
|
|
||||||
.extracting(WebElement::getText)
|
|
||||||
.isEqualTo("Virtual authenticator");
|
|
||||||
|
|
||||||
// Create second authenticator and register
|
|
||||||
removeAuthenticator();
|
|
||||||
createVirtualAuthenticator(true);
|
|
||||||
registerAuthenticator("Second virtual authenticator");
|
|
||||||
|
|
||||||
this.getAndWait("/webauthn/register");
|
|
||||||
|
|
||||||
passkeyRows = this.driver.findElements(passkeyTableRows());
|
|
||||||
assertThat(passkeyRows).hasSize(2)
|
|
||||||
.extracting((row) -> row.findElement(firstCell()))
|
|
||||||
.extracting(WebElement::getText)
|
|
||||||
.contains("Second virtual authenticator");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -285,14 +231,11 @@ class WebAuthnWebDriverTests {
|
|||||||
* "https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/">https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/</a>
|
* "https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/">https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/</a>
|
||||||
*/
|
*/
|
||||||
private void createVirtualAuthenticator(boolean userIsVerified) {
|
private void createVirtualAuthenticator(boolean userIsVerified) {
|
||||||
if (StringUtils.hasText(this.authenticatorId)) {
|
|
||||||
throw new IllegalStateException("Authenticator already exists, please remove it before re-creating one");
|
|
||||||
}
|
|
||||||
HasCdp cdpDriver = (HasCdp) this.driver;
|
HasCdp cdpDriver = (HasCdp) this.driver;
|
||||||
cdpDriver.executeCdpCommand("WebAuthn.enable", Map.of("enableUI", false));
|
cdpDriver.executeCdpCommand("WebAuthn.enable", Map.of("enableUI", false));
|
||||||
// this.driver.addVirtualAuthenticator(createVirtualAuthenticatorOptions());
|
// this.driver.addVirtualAuthenticator(createVirtualAuthenticatorOptions());
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
Map<String, Object> cmdResponse = cdpDriver.executeCdpCommand("WebAuthn.addVirtualAuthenticator",
|
cdpDriver.executeCdpCommand("WebAuthn.addVirtualAuthenticator",
|
||||||
Map.of(
|
Map.of(
|
||||||
"options",
|
"options",
|
||||||
Map.of(
|
Map.of(
|
||||||
@@ -305,38 +248,21 @@ class WebAuthnWebDriverTests {
|
|||||||
)
|
)
|
||||||
));
|
));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
this.authenticatorId = cmdResponse.get("authenticatorId").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeAuthenticator() {
|
|
||||||
HasCdp cdpDriver = (HasCdp) this.driver;
|
|
||||||
cdpDriver.executeCdpCommand("WebAuthn.removeVirtualAuthenticator",
|
|
||||||
Map.of("authenticatorId", this.authenticatorId));
|
|
||||||
this.authenticatorId = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void login() {
|
private void login() {
|
||||||
this.getAndWait("/", "/login");
|
this.driver.get(this.baseUrl);
|
||||||
this.driver.findElement(usernameField()).sendKeys(USERNAME);
|
this.driver.findElement(usernameField()).sendKeys(USERNAME);
|
||||||
this.driver.findElement(passwordField()).sendKeys(PASSWORD);
|
this.driver.findElement(passwordField()).sendKeys(PASSWORD);
|
||||||
this.driver.findElement(signinWithUsernamePasswordButton()).click();
|
this.driver.findElement(signinWithUsernamePasswordButton()).click();
|
||||||
// Ensure login has completed
|
|
||||||
await(() -> assertThat(this.driver.getCurrentUrl()).doesNotContain("/login"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logout() {
|
private void logout() {
|
||||||
this.getAndWait("/logout");
|
this.driver.get(this.baseUrl + "/logout");
|
||||||
this.driver.findElement(logoutButton()).click();
|
this.driver.findElement(logoutButton()).click();
|
||||||
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/login?logout"));
|
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/login?logout"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerAuthenticator(String passkeyName) {
|
|
||||||
this.getAndWait("/webauthn/register");
|
|
||||||
this.driver.findElement(passkeyLabel()).sendKeys(passkeyName);
|
|
||||||
this.driver.findElement(registerPasskeyButton()).click();
|
|
||||||
await(() -> assertThat(this.driver.getCurrentUrl()).endsWith("/webauthn/register?success"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private AbstractStringAssert<?> assertHasAlertStartingWith(String alertType, String alertMessage) {
|
private AbstractStringAssert<?> assertHasAlertStartingWith(String alertType, String alertMessage) {
|
||||||
WebElement alert = this.driver.findElement(new By.ById(alertType));
|
WebElement alert = this.driver.findElement(new By.ById(alertType));
|
||||||
assertThat(alert.isDisplayed())
|
assertThat(alert.isDisplayed())
|
||||||
@@ -363,15 +289,6 @@ class WebAuthnWebDriverTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getAndWait(String endpoint) {
|
|
||||||
this.getAndWait(endpoint, endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getAndWait(String endpoint, String redirectUrl) {
|
|
||||||
this.driver.get(this.baseUrl + endpoint);
|
|
||||||
this.await(() -> assertThat(this.driver.getCurrentUrl()).endsWith(redirectUrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static By.ById passkeyLabel() {
|
private static By.ById passkeyLabel() {
|
||||||
return new By.ById("label");
|
return new By.ById("label");
|
||||||
}
|
}
|
||||||
@@ -408,10 +325,6 @@ class WebAuthnWebDriverTests {
|
|||||||
return new By.ByCssSelector("button");
|
return new By.ByCssSelector("button");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static By.ByCssSelector deletePasskeyButton() {
|
|
||||||
return new By.ByCssSelector("table > tbody > tr > button");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration for WebAuthN tests. It accesses the Server's current port, so we
|
* The configuration for WebAuthN tests. It accesses the Server's current port, so we
|
||||||
* can configurer WebAuthnConfigurer#allowedOrigin
|
* can configurer WebAuthnConfigurer#allowedOrigin
|
||||||
|
|||||||
-143
@@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.config.ldap;
|
|
||||||
|
|
||||||
import javax.naming.Name;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.ldap.core.DistinguishedName;
|
|
||||||
import org.springframework.ldap.core.support.BaseLdapPathAware;
|
|
||||||
import org.springframework.ldap.core.support.BaseLdapPathBeanPostProcessor;
|
|
||||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
|
||||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
|
||||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
|
||||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
@ExtendWith(SpringTestContextExtension.class)
|
|
||||||
public class Ldap247ITests {
|
|
||||||
|
|
||||||
public final SpringTestContext spring = new SpringTestContext(this);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private LdapGroupDao ldapGroupDao;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void verifyThatBasePathIsProperlyPopulated() {
|
|
||||||
this.spring.register(FromContextSourceConfig.class).autowire();
|
|
||||||
assertThat(this.ldapGroupDao).isNotNull();
|
|
||||||
assertThat(this.ldapGroupDao.getBasePath()).isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableMethodSecurity
|
|
||||||
@Import(BaseLdapServerConfig.class)
|
|
||||||
static class FromContextSourceConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource) {
|
|
||||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
|
||||||
factory.setUserDnPatterns("uid={0},ou=people");
|
|
||||||
return factory.createAuthenticationManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
static MethodSecurityExpressionHandler securityExpressionHandler(LdapGroupDao ldap) {
|
|
||||||
return new MethodSecurityExpressionHandler(ldap);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
static LdapGroupDao ldapGroupDao() {
|
|
||||||
return new LdapGroupDao();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
static BaseLdapPathBeanPostProcessor baseLdapPathBeanPostProcessor() {
|
|
||||||
return new BaseLdapPathBeanPostProcessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
static class BaseLdapServerConfig implements DisposableBean {
|
|
||||||
|
|
||||||
private UnboundIdContainer container;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
UnboundIdContainer ldapServer() {
|
|
||||||
this.container = new UnboundIdContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
|
||||||
this.container.setPort(0);
|
|
||||||
return this.container;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
BaseLdapPathContextSource contextSource(UnboundIdContainer container) {
|
|
||||||
int port = container.getPort();
|
|
||||||
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
this.container.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
|
|
||||||
|
|
||||||
private final LdapGroupDao groupDao;
|
|
||||||
|
|
||||||
MethodSecurityExpressionHandler(LdapGroupDao groupDao) {
|
|
||||||
this.groupDao = groupDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class LdapGroupDao implements BaseLdapPathAware {
|
|
||||||
|
|
||||||
private Name basePath;
|
|
||||||
|
|
||||||
LdapGroupDao() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBaseLdapPath(DistinguishedName baseLdapPath) {
|
|
||||||
this.basePath = baseLdapPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
Name getBasePath() {
|
|
||||||
return this.basePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-3
@@ -20,7 +20,6 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
@@ -99,14 +98,12 @@ public class LdapBindAuthenticationManagerFactoryITests {
|
|||||||
public void authenticationManagerFactoryWhenCustomUserDetailsContextMapperThenUsed() throws Exception {
|
public void authenticationManagerFactoryWhenCustomUserDetailsContextMapperThenUsed() throws Exception {
|
||||||
CustomUserDetailsContextMapperConfig.CONTEXT_MAPPER = new UserDetailsContextMapper() {
|
CustomUserDetailsContextMapperConfig.CONTEXT_MAPPER = new UserDetailsContextMapper() {
|
||||||
@Override
|
@Override
|
||||||
@NullMarked
|
|
||||||
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
|
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
|
||||||
Collection<? extends GrantedAuthority> authorities) {
|
Collection<? extends GrantedAuthority> authorities) {
|
||||||
return User.withUsername("other").password("password").roles("USER").build();
|
return User.withUsername("other").password("password").roles("USER").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NullMarked
|
|
||||||
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
|
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-2
@@ -94,7 +94,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
if (!namespaceMatchesVersion(element)) {
|
if (!namespaceMatchesVersion(element)) {
|
||||||
pc.getReaderContext()
|
pc.getReaderContext()
|
||||||
.fatal("You cannot use any XSD older than spring-security-7.1.xsd. Either change to spring-security.xsd or spring-security-7.1.xsd",
|
.fatal("You cannot use any XSD older than spring-security-7.0.xsd. Either change to spring-security.xsd or spring-security-7.0.xsd",
|
||||||
element);
|
element);
|
||||||
}
|
}
|
||||||
String name = pc.getDelegate().getLocalName(element);
|
String name = pc.getDelegate().getLocalName(element);
|
||||||
@@ -219,7 +219,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
|
|
||||||
private boolean matchesVersionInternal(Element element) {
|
private boolean matchesVersionInternal(Element element) {
|
||||||
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||||
return schemaLocation.matches("(?m).*spring-security-7\\.1.*.xsd.*")
|
return schemaLocation.matches("(?m).*spring-security-7\\.0.*.xsd.*")
|
||||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -177,7 +177,7 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a shared Object. Note that object hierarchies are not considered.
|
* Gets a shared Object. Note that object heirarchies are not considered.
|
||||||
* @param sharedType the type of the shared Object
|
* @param sharedType the type of the shared Object
|
||||||
* @return the shared Object or null if it is not found
|
* @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.
|
* Subclasses must implement this method to build the object that is being returned.
|
||||||
* @return the Object to be built or null if the implementation allows it
|
* @return the Object to be buit or null if the implementation allows it
|
||||||
*/
|
*/
|
||||||
protected abstract O performBuild();
|
protected abstract O performBuild();
|
||||||
|
|
||||||
@@ -414,13 +414,13 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||||||
private enum BuildState {
|
private enum BuildState {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the state before the {@link SecurityBuilder#build()} is invoked
|
* This is the state before the {@link Builder#build()} is invoked
|
||||||
*/
|
*/
|
||||||
UNBUILT(0),
|
UNBUILT(0),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state from when {@link SecurityBuilder#build()} is first invoked until all
|
* The state from when {@link Builder#build()} is first invoked until all the
|
||||||
* the {@link SecurityConfigurer#init(SecurityBuilder)} methods have been invoked.
|
* {@link SecurityConfigurer#init(SecurityBuilder)} methods have been invoked.
|
||||||
*/
|
*/
|
||||||
INITIALIZING(1),
|
INITIALIZING(1),
|
||||||
|
|
||||||
|
|||||||
-2
@@ -36,7 +36,6 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.lang.Contract;
|
|
||||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||||
@@ -303,7 +302,6 @@ public class AuthenticationConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Contract("!null -> !null; null -> null")
|
|
||||||
public String encode(CharSequence rawPassword) {
|
public String encode(CharSequence rawPassword) {
|
||||||
return getPasswordEncoder().encode(rawPassword);
|
return getPasswordEncoder().encode(rawPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -42,8 +42,7 @@ final class MethodSecuritySelector implements ImportSelector {
|
|||||||
.isPresent("org.springframework.security.data.aot.hint.AuthorizeReturnObjectDataHintsRegistrar", null);
|
.isPresent("org.springframework.security.data.aot.hint.AuthorizeReturnObjectDataHintsRegistrar", null);
|
||||||
|
|
||||||
private static final boolean isWebPresent = ClassUtils
|
private static final boolean isWebPresent = ClassUtils
|
||||||
.isPresent("org.springframework.web.servlet.DispatcherServlet", null)
|
.isPresent("org.springframework.web.servlet.DispatcherServlet", null);
|
||||||
&& ClassUtils.isPresent("org.springframework.security.web.util.ThrowableAnalyzer", null);
|
|
||||||
|
|
||||||
private static final boolean isObservabilityPresent = ClassUtils
|
private static final boolean isObservabilityPresent = ClassUtils
|
||||||
.isPresent("io.micrometer.observation.ObservationRegistry", null);
|
.isPresent("io.micrometer.observation.ObservationRegistry", null);
|
||||||
|
|||||||
+1
-1
@@ -82,7 +82,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>>
|
|||||||
<C> void setSharedObject(Class<C> sharedType, C object);
|
<C> void setSharedObject(Class<C> sharedType, C object);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a shared Object. Note that object hierarchies are not considered.
|
* Gets a shared Object. Note that object heirarchies are not considered.
|
||||||
* @param sharedType the type of the shared Object
|
* @param sharedType the type of the shared Object
|
||||||
* @return the shared Object or null if it is not found
|
* @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
|
* 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
|
* already registered before, the position previously defined is not going to be
|
||||||
* overridden
|
* overriden
|
||||||
* @param filter the {@link Filter} to register
|
* @param filter the {@link Filter} to register
|
||||||
* @param position the position to associate with the {@link Filter}
|
* @param position the position to associate with the {@link Filter}
|
||||||
*/
|
*/
|
||||||
|
|||||||
+7
-4
@@ -1881,7 +1881,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatchers(Customizer)} will not override previous
|
* Invoking {@link #securityMatchers(Customizer)} will not override previous
|
||||||
* invocations of {@link #securityMatchers(Customizer)}
|
* invocations of {@link #securityMatchers()}}, {@link #securityMatchers(Customizer)}
|
||||||
* {@link #securityMatcher(String...)} and {@link #securityMatcher(RequestMatcher)}
|
* {@link #securityMatcher(String...)} and {@link #securityMatcher(RequestMatcher)}
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
@@ -2004,7 +2004,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatcher(RequestMatcher)} will override previous
|
* Invoking {@link #securityMatcher(RequestMatcher)} will override previous
|
||||||
* invocations of {@link #securityMatcher(RequestMatcher)},
|
* invocations of {@link #securityMatcher(RequestMatcher)},
|
||||||
* {@link #securityMatcher(String...)} and {@link #securityMatchers(Customizer)}
|
* {@link #securityMatcher(String...)}, {@link #securityMatchers(Customizer)} and
|
||||||
|
* {@link #securityMatchers()}
|
||||||
* </p>
|
* </p>
|
||||||
* @param requestMatcher the {@link RequestMatcher} to use, for example,
|
* @param requestMatcher the {@link RequestMatcher} to use, for example,
|
||||||
* {@code PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/admin/**")}
|
* {@code PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/admin/**")}
|
||||||
@@ -2023,8 +2024,9 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
||||||
* {@link #securityMatcher(String...)}, {@link #securityMatcher(RequestMatcher)} and
|
* {@link #securityMatcher(String...)} (String)}},
|
||||||
* {@link #securityMatchers(Customizer)}.
|
* {@link #securityMatcher(RequestMatcher)} ()}, {@link #securityMatchers(Customizer)}
|
||||||
|
* (String)} and {@link #securityMatchers()} (String)}.
|
||||||
* </p>
|
* </p>
|
||||||
* @param patterns the pattern to match on (i.e. "/admin/**")
|
* @param patterns the pattern to match on (i.e. "/admin/**")
|
||||||
* @return the {@link HttpSecurity} for further customizations
|
* @return the {@link HttpSecurity} for further customizations
|
||||||
@@ -2050,6 +2052,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
* http
|
* http
|
||||||
* // ...
|
* // ...
|
||||||
* .webAuthn((webAuthn) -> webAuthn
|
* .webAuthn((webAuthn) -> webAuthn
|
||||||
|
* .rpName("Spring Security Relying Party")
|
||||||
* .rpId("example.com")
|
* .rpId("example.com")
|
||||||
* .allowedOrigins("https://example.com")
|
* .allowedOrigins("https://example.com")
|
||||||
* );
|
* );
|
||||||
|
|||||||
+1
-1
@@ -226,7 +226,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Typically this method is invoked automatically within the framework from
|
* Typically this method is invoked automatically within the framework from
|
||||||
* {@link WebSecurityConfiguration#springSecurityFilterChain(ObjectProvider)}
|
* {@link WebSecurityConfiguration#springSecurityFilterChain()}
|
||||||
* </p>
|
* </p>
|
||||||
* @param securityFilterChainBuilder the builder to use to create the
|
* @param securityFilterChainBuilder the builder to use to create the
|
||||||
* {@link SecurityFilterChain} instances
|
* {@link SecurityFilterChain} instances
|
||||||
|
|||||||
-2
@@ -30,7 +30,6 @@ import org.springframework.context.annotation.Scope;
|
|||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
import org.springframework.lang.Contract;
|
|
||||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||||
@@ -294,7 +293,6 @@ class HttpSecurityConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Contract("!null -> !null; null -> null")
|
|
||||||
public String encode(CharSequence rawPassword) {
|
public String encode(CharSequence rawPassword) {
|
||||||
return getPasswordEncoder().encode(rawPassword);
|
return getPasswordEncoder().encode(rawPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -39,7 +39,6 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
|
|||||||
* other than applying this {@link SecurityConfigurer}.
|
* other than applying this {@link SecurityConfigurer}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @author DingHao
|
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
@@ -159,7 +158,7 @@ public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
this.authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
this.authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
||||||
this.authenticationFilter.afterPropertiesSet();
|
this.authenticationFilter.afterPropertiesSet();
|
||||||
http.addFilter(postProcess(this.authenticationFilter));
|
http.addFilter(this.authenticationFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey() {
|
private String getKey() {
|
||||||
|
|||||||
+1
-1
@@ -305,7 +305,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the logoutSuccessUrl or null if a
|
* Gets the logoutSuccesUrl or null if a
|
||||||
* {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured.
|
* {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured.
|
||||||
* @return the logoutSuccessUrl
|
* @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
|
* This should not use RequestAttributeSecurityContextRepository since that is
|
||||||
* stateless and session management is about state management.
|
* stateless and sesison management is about state management.
|
||||||
*/
|
*/
|
||||||
private SecurityContextRepository sessionManagementSecurityContextRepository = new HttpSessionSecurityContextRepository();
|
private SecurityContextRepository sessionManagementSecurityContextRepository = new HttpSessionSecurityContextRepository();
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -177,7 +177,6 @@ public class WebAuthnConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
WebAuthnAuthenticationFilter webAuthnAuthnFilter = new WebAuthnAuthenticationFilter();
|
WebAuthnAuthenticationFilter webAuthnAuthnFilter = new WebAuthnAuthenticationFilter();
|
||||||
webAuthnAuthnFilter.setAuthenticationManager(
|
webAuthnAuthnFilter.setAuthenticationManager(
|
||||||
new ProviderManager(new WebAuthnAuthenticationProvider(rpOperations, userDetailsService)));
|
new ProviderManager(new WebAuthnAuthenticationProvider(rpOperations, userDetailsService)));
|
||||||
webAuthnAuthnFilter = postProcess(webAuthnAuthnFilter);
|
|
||||||
WebAuthnRegistrationFilter webAuthnRegistrationFilter = new WebAuthnRegistrationFilter(userCredentials,
|
WebAuthnRegistrationFilter webAuthnRegistrationFilter = new WebAuthnRegistrationFilter(userCredentials,
|
||||||
rpOperations);
|
rpOperations);
|
||||||
PublicKeyCredentialCreationOptionsFilter creationOptionsFilter = new PublicKeyCredentialCreationOptionsFilter(
|
PublicKeyCredentialCreationOptionsFilter creationOptionsFilter = new PublicKeyCredentialCreationOptionsFilter(
|
||||||
@@ -257,10 +256,9 @@ public class WebAuthnConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
PublicKeyCredentialUserEntityRepository userEntities, UserCredentialRepository userCredentials) {
|
PublicKeyCredentialUserEntityRepository userEntities, UserCredentialRepository userCredentials) {
|
||||||
Optional<WebAuthnRelyingPartyOperations> webauthnOperationsBean = getBeanOrNull(
|
Optional<WebAuthnRelyingPartyOperations> webauthnOperationsBean = getBeanOrNull(
|
||||||
WebAuthnRelyingPartyOperations.class);
|
WebAuthnRelyingPartyOperations.class);
|
||||||
String rpName = (this.rpName != null) ? this.rpName : this.rpId;
|
return webauthnOperationsBean.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities,
|
||||||
return webauthnOperationsBean
|
userCredentials, PublicKeyCredentialRpEntity.builder().id(this.rpId).name(this.rpName).build(),
|
||||||
.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities, userCredentials,
|
this.allowedOrigins));
|
||||||
PublicKeyCredentialRpEntity.builder().id(this.rpId).name(rpName).build(), this.allowedOrigins));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-4
@@ -47,8 +47,8 @@ import org.springframework.util.Assert;
|
|||||||
* The following configuration options are available:
|
* The following configuration options are available:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #authorizationCodeGrant(Customizer)} - support for the OAuth 2.0
|
* <li>{@link #authorizationCodeGrant()} - support for the OAuth 2.0 Authorization Code
|
||||||
* Authorization Code Grant</li>
|
* Grant</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
@@ -59,8 +59,7 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* <h2>Security Filters</h2>
|
* <h2>Security Filters</h2>
|
||||||
*
|
*
|
||||||
* The following {@code Filter}'s are populated for
|
* The following {@code Filter}'s are populated for {@link #authorizationCodeGrant()}:
|
||||||
* {@link #authorizationCodeGrant(Customizer)}:
|
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link OAuth2AuthorizationRequestRedirectFilter}</li>
|
* <li>{@link OAuth2AuthorizationRequestRedirectFilter}</li>
|
||||||
|
|||||||
+3
-29
@@ -16,12 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
|
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
@@ -38,12 +36,10 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
|
|||||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationValidator;
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationValidator;
|
||||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationProvider;
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationProvider;
|
||||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationToken;
|
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationToken;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
|
||||||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter;
|
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeRequestAuthenticationConverter;
|
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeRequestAuthenticationConverter;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationConsentAuthenticationConverter;
|
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationConsentAuthenticationConverter;
|
||||||
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
|
||||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
@@ -54,7 +50,6 @@ import org.springframework.security.web.servlet.util.matcher.PathPatternRequestM
|
|||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,8 +83,6 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
|||||||
|
|
||||||
private Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authorizationCodeRequestAuthenticationValidator;
|
private Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authorizationCodeRequestAuthenticationValidator;
|
||||||
|
|
||||||
private Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authorizationCodeRequestAuthenticationValidatorComposite;
|
|
||||||
|
|
||||||
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
|
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,16 +248,8 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
|||||||
authenticationProviders.addAll(0, this.authenticationProviders);
|
authenticationProviders.addAll(0, this.authenticationProviders);
|
||||||
}
|
}
|
||||||
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
this.authenticationProvidersConsumer.accept(authenticationProviders);
|
||||||
authenticationProviders.forEach((authenticationProvider) -> {
|
authenticationProviders.forEach(
|
||||||
httpSecurity.authenticationProvider(postProcess(authenticationProvider));
|
(authenticationProvider) -> httpSecurity.authenticationProvider(postProcess(authenticationProvider)));
|
||||||
if (authenticationProvider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider) {
|
|
||||||
Method method = ReflectionUtils.findMethod(OAuth2AuthorizationCodeRequestAuthenticationProvider.class,
|
|
||||||
"getAuthenticationValidatorComposite");
|
|
||||||
ReflectionUtils.makeAccessible(method);
|
|
||||||
this.authorizationCodeRequestAuthenticationValidatorComposite = (Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext>) ReflectionUtils
|
|
||||||
.invokeMethod(method, authenticationProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -297,18 +282,7 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
|
|||||||
if (this.sessionAuthenticationStrategy != null) {
|
if (this.sessionAuthenticationStrategy != null) {
|
||||||
authorizationEndpointFilter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy);
|
authorizationEndpointFilter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy);
|
||||||
}
|
}
|
||||||
httpSecurity.addFilterAfter(postProcess(authorizationEndpointFilter), AuthorizationFilter.class);
|
httpSecurity.addFilterBefore(postProcess(authorizationEndpointFilter),
|
||||||
// Create and add
|
|
||||||
// OAuth2AuthorizationEndpointFilter.OAuth2AuthorizationCodeRequestValidatingFilter
|
|
||||||
Method method = ReflectionUtils.findMethod(OAuth2AuthorizationEndpointFilter.class,
|
|
||||||
"createAuthorizationCodeRequestValidatingFilter", RegisteredClientRepository.class, Consumer.class);
|
|
||||||
ReflectionUtils.makeAccessible(method);
|
|
||||||
RegisteredClientRepository registeredClientRepository = OAuth2ConfigurerUtils
|
|
||||||
.getRegisteredClientRepository(httpSecurity);
|
|
||||||
Filter authorizationCodeRequestValidatingFilter = (Filter) ReflectionUtils.invokeMethod(method,
|
|
||||||
authorizationEndpointFilter, registeredClientRepository,
|
|
||||||
this.authorizationCodeRequestAuthenticationValidatorComposite);
|
|
||||||
httpSecurity.addFilterBefore(postProcess(authorizationCodeRequestValidatingFilter),
|
|
||||||
AbstractPreAuthenticatedProcessingFilter.class);
|
AbstractPreAuthenticatedProcessingFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-3
@@ -16,9 +16,14 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
|
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.jwk.source.JWKSource;
|
||||||
import com.nimbusds.jose.proc.SecurityContext;
|
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.context.ApplicationContext;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
@@ -40,6 +45,7 @@ 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.OAuth2TokenCustomizer;
|
||||||
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
|
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for the OAuth 2.0 Configurers.
|
* Utility methods for the OAuth 2.0 Configurers.
|
||||||
@@ -201,16 +207,41 @@ final class OAuth2ConfigurerUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static <T> T getBean(HttpSecurity httpSecurity, Class<T> type) {
|
static <T> T getBean(HttpSecurity httpSecurity, Class<T> type) {
|
||||||
return httpSecurity.getSharedObject(ApplicationContext.class).getBeanProvider(type).getObject();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> T getOptionalBean(HttpSecurity httpSecurity, Class<T> type) {
|
static <T> T getOptionalBean(HttpSecurity httpSecurity, Class<T> type) {
|
||||||
return httpSecurity.getSharedObject(ApplicationContext.class).getBeanProvider(type).getIfUnique();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static <T> T getOptionalBean(HttpSecurity httpSecurity, ResolvableType type) {
|
static <T> T getOptionalBean(HttpSecurity httpSecurity, ResolvableType type) {
|
||||||
return (T) httpSecurity.getSharedObject(ApplicationContext.class).getBeanProvider(type).getIfUnique();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -40,11 +40,11 @@ import org.springframework.security.oauth2.server.authorization.settings.Authori
|
|||||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2DeviceVerificationEndpointFilter;
|
import org.springframework.security.oauth2.server.authorization.web.OAuth2DeviceVerificationEndpointFilter;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceAuthorizationConsentAuthenticationConverter;
|
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceAuthorizationConsentAuthenticationConverter;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceVerificationAuthenticationConverter;
|
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceVerificationAuthenticationConverter;
|
||||||
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
|
||||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.authentication.DelegatingAuthenticationConverter;
|
import org.springframework.security.web.authentication.DelegatingAuthenticationConverter;
|
||||||
|
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
@@ -279,7 +279,8 @@ public final class OAuth2DeviceVerificationEndpointConfigurer extends AbstractOA
|
|||||||
if (StringUtils.hasText(this.consentPage)) {
|
if (StringUtils.hasText(this.consentPage)) {
|
||||||
deviceVerificationEndpointFilter.setConsentPage(this.consentPage);
|
deviceVerificationEndpointFilter.setConsentPage(this.consentPage);
|
||||||
}
|
}
|
||||||
builder.addFilterAfter(postProcess(deviceVerificationEndpointFilter), AuthorizationFilter.class);
|
builder.addFilterBefore(postProcess(deviceVerificationEndpointFilter),
|
||||||
|
AbstractPreAuthenticatedProcessingFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+4
-8
@@ -521,10 +521,8 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||||||
public OpaqueTokenConfigurer introspectionUri(String introspectionUri) {
|
public OpaqueTokenConfigurer introspectionUri(String introspectionUri) {
|
||||||
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
||||||
this.introspectionUri = introspectionUri;
|
this.introspectionUri = introspectionUri;
|
||||||
this.introspector = () -> SpringOpaqueTokenIntrospector.withIntrospectionUri(this.introspectionUri)
|
this.introspector = () -> new SpringOpaqueTokenIntrospector(this.introspectionUri, this.clientId,
|
||||||
.clientId(this.clientId)
|
this.clientSecret);
|
||||||
.clientSecret(this.clientSecret)
|
|
||||||
.build();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,10 +531,8 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||||||
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
this.clientSecret = clientSecret;
|
this.clientSecret = clientSecret;
|
||||||
this.introspector = () -> SpringOpaqueTokenIntrospector.withIntrospectionUri(this.introspectionUri)
|
this.introspector = () -> new SpringOpaqueTokenIntrospector(this.introspectionUri, this.clientId,
|
||||||
.clientId(this.clientId)
|
this.clientSecret);
|
||||||
.clientSecret(this.clientSecret)
|
|
||||||
.build();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -21,7 +21,6 @@ import java.util.function.Function;
|
|||||||
import org.opensaml.core.Version;
|
import org.opensaml.core.Version;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.security.config.Customizer;
|
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
@@ -43,8 +42,7 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Defaults are provided for all configuration options with the only required
|
* Defaults are provided for all configuration options with the only required
|
||||||
* configuration being a
|
* configuration being a {@link Saml2LoginConfigurer#relyingPartyRegistrationRepository}.
|
||||||
* {@link Saml2LoginConfigurer#relyingPartyRegistrationRepository(HttpSecurityBuilder)}.
|
|
||||||
* Alternatively, a {@link RelyingPartyRegistrationRepository} {@code @Bean} may be
|
* Alternatively, a {@link RelyingPartyRegistrationRepository} {@code @Bean} may be
|
||||||
* registered instead.
|
* registered instead.
|
||||||
*
|
*
|
||||||
@@ -69,7 +67,7 @@ import org.springframework.util.Assert;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
* @see HttpSecurity#saml2Metadata(Customizer)
|
* @see HttpSecurity#saml2Metadata()
|
||||||
* @see Saml2MetadataFilter
|
* @see Saml2MetadataFilter
|
||||||
* @see RelyingPartyRegistrationRepository
|
* @see RelyingPartyRegistrationRepository
|
||||||
*/
|
*/
|
||||||
@@ -97,7 +95,7 @@ public class Saml2MetadataConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* If there is no {@code registrationId} and your
|
* If there is no {@code registrationId} and your
|
||||||
* {@link RelyingPartyRegistrationRepository} is {code Iterable}, the metadata
|
* {@link RelyingPartyRegistrationRepository} is {code Iterable}, the metadata
|
||||||
* endpoint will try and show all relying parties' metadata in a single
|
* endpoint will try and show all relying parties' metadata in a single
|
||||||
* {@code <md:EntitiesDescriptor} element.
|
* {@code <md:EntitiesDecriptor} element.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If you need a more sophisticated lookup strategy than these, use
|
* If you need a more sophisticated lookup strategy than these, use
|
||||||
|
|||||||
+2
-4
@@ -167,7 +167,7 @@ class ServerHttpSecurityConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies all {@code Customizer<ServerHttpSecurity>} Beans to
|
* Applies all {@code Custmizer<ServerHttpSecurity>} Beans to
|
||||||
* {@link ServerHttpSecurity}.
|
* {@link ServerHttpSecurity}.
|
||||||
* @param context the {@link ApplicationContext}
|
* @param context the {@link ApplicationContext}
|
||||||
* @param http the {@link ServerHttpSecurity}
|
* @param http the {@link ServerHttpSecurity}
|
||||||
@@ -255,9 +255,7 @@ class ServerHttpSecurityConfiguration {
|
|||||||
if (this.passwordEncoder != null) {
|
if (this.passwordEncoder != null) {
|
||||||
manager.setPasswordEncoder(this.passwordEncoder);
|
manager.setPasswordEncoder(this.passwordEncoder);
|
||||||
}
|
}
|
||||||
if (this.userDetailsPasswordService != null) {
|
manager.setUserDetailsPasswordService(this.userDetailsPasswordService);
|
||||||
manager.setUserDetailsPasswordService(this.userDetailsPasswordService);
|
|
||||||
}
|
|
||||||
manager.setCompromisedPasswordChecker(this.compromisedPasswordChecker);
|
manager.setCompromisedPasswordChecker(this.compromisedPasswordChecker);
|
||||||
return this.postProcessor.postProcess(manager);
|
return this.postProcessor.postProcess(manager);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -538,7 +538,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
}
|
}
|
||||||
injectAuthenticationDetailsSource(x509Elt, filterBuilder);
|
injectAuthenticationDetailsSource(x509Elt, filterBuilder);
|
||||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||||
createPreauthEntryPoint(x509Elt);
|
createPrauthEntryPoint(x509Elt);
|
||||||
createX509Provider();
|
createX509Provider();
|
||||||
}
|
}
|
||||||
this.x509Filter = filter;
|
this.x509Filter = filter;
|
||||||
@@ -562,7 +562,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
this.x509ProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
|
this.x509ProviderRef = new RuntimeBeanReference(this.pc.getReaderContext().registerWithGeneratedName(provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPreauthEntryPoint(Element source) {
|
private void createPrauthEntryPoint(Element source) {
|
||||||
if (this.preAuthEntryPoint == null) {
|
if (this.preAuthEntryPoint == null) {
|
||||||
this.preAuthEntryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
|
this.preAuthEntryPoint = new RootBeanDefinition(Http403ForbiddenEntryPoint.class);
|
||||||
this.preAuthEntryPoint.setSource(this.pc.extractSource(source));
|
this.preAuthEntryPoint.setSource(this.pc.extractSource(source));
|
||||||
@@ -595,7 +595,7 @@ final class AuthenticationConfigBuilder {
|
|||||||
adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
|
adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever);
|
||||||
filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
|
filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition());
|
||||||
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
|
||||||
createPreauthEntryPoint(jeeElt);
|
createPrauthEntryPoint(jeeElt);
|
||||||
createJeeProvider();
|
createJeeProvider();
|
||||||
}
|
}
|
||||||
this.jeeFilter = filter;
|
this.jeeFilter = filter;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user