mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-03-11 17:14:49 +00:00
Compare commits
No commits in common. "main" and "6.5.8" have entirely different histories.
145
.github/dependabot.yml
vendored
145
.github/dependabot.yml
vendored
@ -1,12 +1,11 @@
|
|||||||
version: 2
|
version: 2
|
||||||
registries:
|
registries:
|
||||||
shibboleth:
|
spring-milestones:
|
||||||
type: maven-repository
|
type: maven-repository
|
||||||
url: https://build.shibboleth.net/maven/releases
|
url: https://repo.spring.io/milestone
|
||||||
updates:
|
updates:
|
||||||
# 6.5.x
|
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: 6.5.x
|
target-branch: 6.4.x
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
@ -15,7 +14,7 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- shibboleth
|
- spring-milestones
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
- dependency-name: org.python:jython
|
- dependency-name: org.python:jython
|
||||||
@ -31,28 +30,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.3.x
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
@ -61,10 +40,9 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- shibboleth
|
- spring-milestones
|
||||||
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 +52,10 @@ 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,7 +66,7 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- shibboleth
|
- spring-milestones
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
- dependency-name: org.python:jython
|
- dependency-name: org.python:jython
|
||||||
@ -131,6 +85,36 @@ updates:
|
|||||||
- dependency-name: '*'
|
- dependency-name: '*'
|
||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
|
- version-update:semver-minor
|
||||||
|
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
target-branch: 6.3.x
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
labels:
|
||||||
|
- 'type: task'
|
||||||
|
- 'in: build'
|
||||||
|
ignore:
|
||||||
|
- dependency-name: sjohnr/*
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
target-branch: docs-build
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
labels:
|
||||||
|
- 'type: task'
|
||||||
|
- 'in: build'
|
||||||
|
|
||||||
|
- 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 +122,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'
|
||||||
|
|||||||
16
.github/workflows/auto-merge-dependabot.yml
vendored
16
.github/workflows/auto-merge-dependabot.yml
vendored
@ -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
|
|
||||||
36
.github/workflows/check-snapshots.yml
vendored
36
.github/workflows/check-snapshots.yml
vendored
@ -1,36 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 10 * * *' # Once per day at 10am UTC
|
|
||||||
workflow_dispatch: # Manual trigger
|
|
||||||
|
|
||||||
env:
|
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
snapshot-test:
|
|
||||||
name: Test Against Snapshots
|
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- java-version: 25
|
|
||||||
toolchain: 25
|
|
||||||
with:
|
|
||||||
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
|
|
||||||
secrets: inherit
|
|
||||||
send-notification:
|
|
||||||
name: Send Notification
|
|
||||||
needs: [ snapshot-test ]
|
|
||||||
if: ${{ !success() }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Send Notification
|
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
|
||||||
with:
|
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
|
||||||
@ -21,28 +21,62 @@ jobs:
|
|||||||
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 }}
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
test:
|
||||||
|
name: Test Against Snapshots
|
||||||
|
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- java-version: 21-ea
|
||||||
|
toolchain: 21
|
||||||
|
- java-version: 17
|
||||||
|
toolchain: 17
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.java-version }}
|
||||||
|
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=6.2.+ -PreactorVersion=2023.0.+ -PspringDataVersion=2024.0.+ --stacktrace
|
||||||
|
secrets: inherit
|
||||||
|
check-samples:
|
||||||
|
name: Check Samples
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.repository_owner == 'spring-projects' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- name: Set up gradle
|
||||||
|
uses: spring-io/spring-gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
java-version: 17
|
||||||
|
distribution: temurin
|
||||||
|
- name: Check samples project
|
||||||
|
env:
|
||||||
|
LOCAL_REPOSITORY_PATH: ${{ github.workspace }}/build/publications/repos
|
||||||
|
SAMPLES_DIR: ../spring-security-samples
|
||||||
|
run: |
|
||||||
|
# Extract version from gradle.properties
|
||||||
|
version=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}')
|
||||||
|
# Extract samplesBranch from gradle.properties
|
||||||
|
samples_branch=$(cat gradle.properties | grep "samplesBranch=" | awk -F'=' '{print $2}')
|
||||||
|
./gradlew publishMavenJavaPublicationToLocalRepository
|
||||||
|
./gradlew cloneRepository -PrepositoryName="spring-projects/spring-security-samples" -Pref="$samples_branch" -PcloneOutputDirectory="$SAMPLES_DIR"
|
||||||
|
./gradlew --refresh-dependencies --project-dir "$SAMPLES_DIR" --init-script spring-security-ci.gradle -PlocalRepositoryPath="$LOCAL_REPOSITORY_PATH" -PspringSecurityVersion="$version" test integrationTest
|
||||||
deploy-artifacts:
|
deploy-artifacts:
|
||||||
name: Deploy Artifacts
|
name: Deploy Artifacts
|
||||||
needs: [ build]
|
needs: [ build, test, check-samples ]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||||
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
|
|
||||||
java-version: 25
|
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
deploy-schema:
|
deploy-schema:
|
||||||
name: Deploy Schema
|
name: Deploy Schema
|
||||||
needs: [ build ]
|
needs: [ build, test, check-samples ]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||||
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
|
||||||
@ -51,11 +85,10 @@ jobs:
|
|||||||
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 }}
|
||||||
milestone-repo-url: https://repo1.maven.org/maven2
|
milestone-repo-url: https://repo.spring.io/artifactory/milestone
|
||||||
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
|
||||||
|
|||||||
27
.github/workflows/finalize-release.yml
vendored
27
.github/workflows/finalize-release.yml
vendored
@ -1,27 +0,0 @@
|
|||||||
name: Finalize Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch: # Manual trigger
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: The Spring Security release to finalize (e.g. 7.0.0-RC2)
|
|
||||||
required: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
perform-release:
|
|
||||||
name: Perform Release
|
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
|
||||||
with:
|
|
||||||
should-perform-release: true
|
|
||||||
project-version: ${{ inputs.version }}
|
|
||||||
milestone-repo-url: https://repo1.maven.org/maven2
|
|
||||||
release-repo-url: https://repo1.maven.org/maven2
|
|
||||||
artifact-path: org/springframework/security/spring-security-core
|
|
||||||
slack-announcing-id: spring-security-announcing
|
|
||||||
secrets: inherit
|
|
||||||
@ -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
|
||||||
@ -21,10 +20,10 @@ jobs:
|
|||||||
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
- name: Set up JDK 25
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
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/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # v5.0.1
|
||||||
|
|||||||
6
.github/workflows/pr-build-workflow.yml
vendored
6
.github/workflows/pr-build-workflow.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
- 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@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
|
||||||
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
|
||||||
@ -28,13 +28,13 @@ jobs:
|
|||||||
- 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@efc55f07f4dfa22f2afd97f9ea1be4212eeed737 # v2.0.5
|
||||||
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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||||
with:
|
with:
|
||||||
name: docs
|
name: docs
|
||||||
path: docs/build/site
|
path: docs/build/site
|
||||||
|
|||||||
2
.github/workflows/release-scheduler.yml
vendored
2
.github/workflows/release-scheduler.yml
vendored
@ -11,7 +11,7 @@ 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.4.x, 6.3.x ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@ -12,12 +12,11 @@ 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@415e2b11a766ba64799fffb5c97a4f7e17f677cf
|
||||||
name: Update
|
name: Update
|
||||||
@ -26,9 +25,8 @@ jobs:
|
|||||||
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@415e2b11a766ba64799fffb5c97a4f7e17f677cf
|
||||||
name: Update
|
name: Update
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,7 +25,6 @@ atlassian-ide-plugin.xml
|
|||||||
s101plugin.state
|
s101plugin.state
|
||||||
.attach_pid*
|
.attach_pid*
|
||||||
.~lock.*#
|
.~lock.*#
|
||||||
.kotlin/
|
|
||||||
|
|
||||||
!.idea/checkstyle-idea.xml
|
!.idea/checkstyle-idea.xml
|
||||||
!.idea/externalDependencies.xml
|
!.idea/externalDependencies.xml
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"java.gradle.buildServer.enabled": "off"
|
"java.import.gradle.enabled": false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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]]
|
||||||
@ -79,9 +79,6 @@ See https://github.com/spring-projects/spring-security/tree/main#building-from-s
|
|||||||
|
|
||||||
The wiki pages https://github.com/spring-projects/spring-framework/wiki/Code-Style[Code Style] and https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings[IntelliJ IDEA Editor Settings] define the source file coding standards we use along with some IDEA editor settings we customize.
|
The wiki pages https://github.com/spring-projects/spring-framework/wiki/Code-Style[Code Style] and https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings[IntelliJ IDEA Editor Settings] define the source file coding standards we use along with some IDEA editor settings we customize.
|
||||||
|
|
||||||
Additionally, since Streams are https://github.com/spring-projects/spring-security/issues/7154[much slower] than `for` loops, please use them judiciously.
|
|
||||||
The team may ask you to change to a `for` loop if the given code is along a hot path.
|
|
||||||
|
|
||||||
To format the code as well as check the style, run `./gradlew format && ./gradlew check`.
|
To format the code as well as check the style, run `./gradlew format && ./gradlew check`.
|
||||||
|
|
||||||
[[submit-a-pull-request]]
|
[[submit-a-pull-request]]
|
||||||
@ -94,7 +91,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
README.adoc
21
README.adoc
@ -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,54 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'compile-warnings-error'
|
|
||||||
id 'javadoc-warnings-error'
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
management platform(project(":spring-security-dependencies"))
|
|
||||||
api project(':spring-security-crypto')
|
|
||||||
api project(':spring-security-core')
|
|
||||||
api 'org.springframework:spring-aop'
|
|
||||||
api 'org.springframework:spring-beans'
|
|
||||||
api 'org.springframework:spring-context'
|
|
||||||
api 'org.springframework:spring-core'
|
|
||||||
api 'org.springframework:spring-expression'
|
|
||||||
api 'io.micrometer:micrometer-observation'
|
|
||||||
|
|
||||||
optional project(':spring-security-acl')
|
|
||||||
optional project(':spring-security-messaging')
|
|
||||||
optional project(':spring-security-web')
|
|
||||||
optional 'org.springframework:spring-websocket'
|
|
||||||
optional 'com.fasterxml.jackson.core:jackson-databind'
|
|
||||||
optional 'io.micrometer:context-propagation'
|
|
||||||
optional 'io.projectreactor:reactor-core'
|
|
||||||
optional 'jakarta.annotation:jakarta.annotation-api'
|
|
||||||
optional 'org.aspectj:aspectjrt'
|
|
||||||
optional 'org.springframework:spring-jdbc'
|
|
||||||
optional 'org.springframework:spring-tx'
|
|
||||||
optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor'
|
|
||||||
|
|
||||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
|
||||||
|
|
||||||
testImplementation project(path : ':spring-security-web', configuration : 'tests')
|
|
||||||
testImplementation 'commons-collections:commons-collections'
|
|
||||||
testImplementation 'io.projectreactor:reactor-test'
|
|
||||||
testImplementation "org.assertj:assertj-core"
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-engine"
|
|
||||||
testImplementation "org.mockito:mockito-core"
|
|
||||||
testImplementation "org.mockito:mockito-junit-jupiter"
|
|
||||||
testImplementation "org.springframework:spring-core-test"
|
|
||||||
testImplementation "org.springframework:spring-test"
|
|
||||||
testImplementation 'org.skyscreamer:jsonassert'
|
|
||||||
testImplementation 'org.springframework:spring-test'
|
|
||||||
testImplementation 'org.jetbrains.kotlin:kotlin-reflect'
|
|
||||||
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
|
||||||
testImplementation 'io.mockk:mockk'
|
|
||||||
|
|
||||||
testRuntimeOnly 'org.hsqldb:hsqldb'
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.access;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the interface of a secured object.
|
|
||||||
*
|
|
||||||
* @author Ben Alex
|
|
||||||
*/
|
|
||||||
public interface ITargetObject {
|
|
||||||
|
|
||||||
Integer computeHashCode(String input);
|
|
||||||
|
|
||||||
int countLength(String input);
|
|
||||||
|
|
||||||
String makeLowerCase(String input);
|
|
||||||
|
|
||||||
String makeUpperCase(String input);
|
|
||||||
|
|
||||||
String publicMakeLowerCase(String input);
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.access;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simply extends {@link TargetObject} so we have a different object to put configuration
|
|
||||||
* attributes against.
|
|
||||||
* <P>
|
|
||||||
* There is no different behaviour. We have to define each method so that
|
|
||||||
* <code>Class.getMethod(methodName, args)</code> returns a <code>Method</code>
|
|
||||||
* referencing this class rather than the parent class.
|
|
||||||
* </p>
|
|
||||||
* <P>
|
|
||||||
* We need to implement <code>ITargetObject</code> again because the
|
|
||||||
* <code>MethodDefinitionAttributes</code> only locates attributes on interfaces
|
|
||||||
* explicitly defined by the intercepted class (not the interfaces defined by its parent
|
|
||||||
* class or classes).
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Ben Alex
|
|
||||||
*/
|
|
||||||
public class OtherTargetObject extends TargetObject implements ITargetObject {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String makeLowerCase(String input) {
|
|
||||||
return super.makeLowerCase(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String makeUpperCase(String input) {
|
|
||||||
return super.makeUpperCase(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String publicMakeLowerCase(String input) {
|
|
||||||
return super.publicMakeLowerCase(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
|
||||||
*
|
|
||||||
* 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.access;
|
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a secured object.
|
|
||||||
*
|
|
||||||
* @author Ben Alex
|
|
||||||
*/
|
|
||||||
public class TargetObject implements ITargetObject {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer computeHashCode(String input) {
|
|
||||||
return input.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int countLength(String input) {
|
|
||||||
return input.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the lowercase string, followed by security environment information.
|
|
||||||
* @param input the message to make lowercase
|
|
||||||
* @return the lowercase message, a space, the <code>Authentication</code> class that
|
|
||||||
* was on the <code>SecurityContext</code> at the time of method invocation, and a
|
|
||||||
* boolean indicating if the <code>Authentication</code> object is authenticated or
|
|
||||||
* not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String makeLowerCase(String input) {
|
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
if (auth == null) {
|
|
||||||
return input.toLowerCase() + " Authentication empty";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return input.toLowerCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the uppercase string, followed by security environment information.
|
|
||||||
* @param input the message to make uppercase
|
|
||||||
* @return the uppercase message, a space, the <code>Authentication</code> class that
|
|
||||||
* was on the <code>SecurityContext</code> at the time of method invocation, and a
|
|
||||||
* boolean indicating if the <code>Authentication</code> object is authenticated or
|
|
||||||
* not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String makeUpperCase(String input) {
|
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
return input.toUpperCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delegates through to the {@link #makeLowerCase(String)} method.
|
|
||||||
* @param input the message to be made lower-case
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String publicMakeLowerCase(String input) {
|
|
||||||
return this.makeLowerCase(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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 {
|
||||||
|
|||||||
@ -71,7 +71,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* <tt>AclEntryVoter</tt>:
|
* <tt>AclEntryVoter</tt>:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
|
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
|
||||||
* <code>VOTE_ACL_BANK_ACCOUNT_READ</code>, require permission
|
* <code>VOTE_ACL_BANK_ACCONT_READ</code>, require permission
|
||||||
* <code>BasePermission.READ</code></li>
|
* <code>BasePermission.READ</code></li>
|
||||||
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
|
* <li>Process domain object class <code>BankAccount</code>, configuration attribute
|
||||||
* <code>VOTE_ACL_BANK_ACCOUNT_WRITE</code>, require permission list
|
* <code>VOTE_ACL_BANK_ACCOUNT_WRITE</code>, require permission list
|
||||||
@ -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;
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
@ -67,11 +65,10 @@ import org.springframework.util.Assert;
|
|||||||
* NB: This implementation does attempt to provide reasonably optimised lookups - within
|
* NB: This implementation does attempt to provide reasonably optimised lookups - within
|
||||||
* the constraints of a normalised database and standard ANSI SQL features. If you are
|
* the constraints of a normalised database and standard ANSI SQL features. If you are
|
||||||
* willing to sacrifice either of these constraints (e.g. use a particular database
|
* willing to sacrifice either of these constraints (e.g. use a particular database
|
||||||
* feature such as hierarchical queries or materialized views, or reduce normalisation)
|
* feature such as hierarchical queries or materalized views, or reduce normalisation) you
|
||||||
* you are likely to achieve better performance. In such situations you will need to
|
* are likely to achieve better performance. In such situations you will need to provide
|
||||||
* provide your own custom <code>LookupStrategy</code>. This class does not support
|
* your own custom <code>LookupStrategy</code>. This class does not support subclassing,
|
||||||
* subclassing, as it is likely to change in future releases and therefore subclassing is
|
* as it is likely to change in future releases and therefore subclassing is unsupported.
|
||||||
* unsupported.
|
|
||||||
* <p>
|
* <p>
|
||||||
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
|
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
|
||||||
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order
|
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order
|
||||||
@ -226,8 +223,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 +263,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 +322,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 +398,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 +505,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 +578,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 +669,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 {
|
||||||
@ -22,8 +18,6 @@ dependencies {
|
|||||||
api 'org.springframework:spring-context'
|
api 'org.springframework:spring-context'
|
||||||
api 'org.springframework:spring-core'
|
api 'org.springframework:spring-core'
|
||||||
|
|
||||||
optional project(':spring-security-access')
|
|
||||||
|
|
||||||
testImplementation 'org.springframework:spring-aop'
|
testImplementation 'org.springframework:spring-aop'
|
||||||
testImplementation "org.assertj:assertj-core"
|
testImplementation "org.assertj:assertj-core"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
47
build.gradle
47
build.gradle
@ -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,7 +35,7 @@ ext.milestoneBuild = !(snapshotBuild || releaseBuild)
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = "https://repo.spring.io/milestone" }
|
maven { url "https://repo.spring.io/milestone" }
|
||||||
}
|
}
|
||||||
|
|
||||||
springRelease {
|
springRelease {
|
||||||
@ -48,19 +46,46 @@ springRelease {
|
|||||||
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 ->
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java-gradle-plugin"
|
id "java-gradle-plugin"
|
||||||
id "groovy-gradle-plugin"
|
|
||||||
id "java"
|
id "java"
|
||||||
id "groovy"
|
id "groovy"
|
||||||
}
|
}
|
||||||
@ -12,7 +11,7 @@ java {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = 'https://repo.spring.io/snapshot' }
|
maven { url 'https://repo.spring.io/milestone' }
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@ -64,7 +63,6 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation platform(libs.io.projectreactor.reactor.bom)
|
implementation platform(libs.io.projectreactor.reactor.bom)
|
||||||
|
|
||||||
implementation libs.spring.nullability
|
|
||||||
implementation libs.com.google.code.gson.gson
|
implementation libs.com.google.code.gson.gson
|
||||||
implementation libs.com.thaiopensource.trag
|
implementation libs.com.thaiopensource.trag
|
||||||
implementation libs.net.sourceforge.saxon.saxon
|
implementation libs.net.sourceforge.saxon.saxon
|
||||||
@ -78,7 +76,6 @@ dependencies {
|
|||||||
implementation libs.com.github.spullara.mustache.java.compiler
|
implementation libs.com.github.spullara.mustache.java.compiler
|
||||||
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
|
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
|
||||||
implementation libs.io.spring.nohttp.nohttp.gradle
|
implementation libs.io.spring.nohttp.nohttp.gradle
|
||||||
implementation libs.org.jetbrains.kotlin.kotlin.gradle.plugin
|
|
||||||
implementation (libs.net.sourceforge.htmlunit) {
|
implementation (libs.net.sourceforge.htmlunit) {
|
||||||
exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client'
|
exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,12 +31,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()));
|
||||||
|
|||||||
@ -61,7 +61,7 @@ public class ManagementConfigurationPlugin implements Plugin<Project> {
|
|||||||
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
|
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
|
||||||
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
|
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
|
||||||
mavenPublication.versionMapping((versions) ->
|
mavenPublication.versionMapping((versions) ->
|
||||||
versions.allVariants((versionMapping) -> versionMapping.fromResolutionResult())
|
versions.allVariants(versionMapping -> versionMapping.fromResolutionResult())
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|||||||
@ -80,11 +80,6 @@ class RepositoryConventionPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
url = 'https://repo.spring.io/release/'
|
url = 'https://repo.spring.io/release/'
|
||||||
}
|
}
|
||||||
forceMavenRepositories.findAll { it.startsWith('https://') || it.startsWith('file://') }.each { mavenUrl ->
|
|
||||||
maven {
|
|
||||||
url mavenUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,15 +32,12 @@ public class SchemaZipPlugin implements Plugin<Project> {
|
|||||||
for (def key : schemas.keySet()) {
|
for (def key : schemas.keySet()) {
|
||||||
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
||||||
assert shortName != key
|
assert shortName != key
|
||||||
def schemaResourceName = schemas.get(key)
|
|
||||||
File xsdFile = module.sourceSets.main.resources.find {
|
File xsdFile = module.sourceSets.main.resources.find {
|
||||||
it.path.endsWith(schemaResourceName)
|
it.path.endsWith(schemas.get(key))
|
||||||
}
|
|
||||||
if (xsdFile == null) {
|
|
||||||
throw new IllegalStateException("Could not find schema file for resource name " + schemaResourceName + " in src/main/resources")
|
|
||||||
}
|
}
|
||||||
|
assert xsdFile != null
|
||||||
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,17 +0,0 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id 'kotlin'
|
|
||||||
}
|
|
||||||
|
|
||||||
project.plugins.withId("org.jetbrains.kotlin.jvm", (kotlinProject) -> {
|
|
||||||
project.tasks.withType(KotlinCompile).configureEach {
|
|
||||||
kotlinOptions {
|
|
||||||
languageVersion = '2.2'
|
|
||||||
apiVersion = '2.2'
|
|
||||||
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings"]
|
|
||||||
jvmTarget = '17'
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'io.spring.nullability'
|
|
||||||
}
|
|
||||||
@ -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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -81,6 +81,9 @@ public class CheckClasspathForProhibitedDependencies extends DefaultTask {
|
|||||||
if (group.startsWith("javax")) {
|
if (group.startsWith("javax")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (group.equals("commons-logging")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (group.equals("org.slf4j") && id.getName().equals("jcl-over-slf4j")) {
|
if (group.equals("org.slf4j") && id.getName().equals("jcl-over-slf4j")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public class CheckExpectedBranchVersionPlugin implements Plugin<Project> {
|
|||||||
task.setDescription("Check if the project version matches the branch version");
|
task.setDescription("Check if the project version matches the branch version");
|
||||||
task.onlyIf("skipCheckExpectedBranchVersion property is false or not present", CheckExpectedBranchVersionPlugin::skipPropertyFalseOrNotPresent);
|
task.onlyIf("skipCheckExpectedBranchVersion property is false or not present", CheckExpectedBranchVersionPlugin::skipPropertyFalseOrNotPresent);
|
||||||
task.getVersion().convention(project.provider(() -> project.getVersion().toString()));
|
task.getVersion().convention(project.provider(() -> project.getVersion().toString()));
|
||||||
task.getBranchName().convention(project.getProviders().exec((execSpec) -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
|
task.getBranchName().convention(project.getProviders().exec(execSpec -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
|
||||||
task.getOutputFile().convention(project.getLayout().getBuildDirectory().file("check-expected-branch-version"));
|
task.getOutputFile().convention(project.getLayout().getBuildDirectory().file("check-expected-branch-version"));
|
||||||
});
|
});
|
||||||
project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, checkTask -> checkTask.dependsOn(checkExpectedBranchVersionTask));
|
project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, checkTask -> checkTask.dependsOn(checkExpectedBranchVersionTask));
|
||||||
|
|||||||
@ -83,8 +83,12 @@ public class VerifyDependenciesVersionsPlugin implements Plugin<Project> {
|
|||||||
String transitiveNimbusJoseJwtVersion = TransitiveDependencyLookupUtils.lookupJwtVersion(oauth2OidcSdkVersion);
|
String transitiveNimbusJoseJwtVersion = TransitiveDependencyLookupUtils.lookupJwtVersion(oauth2OidcSdkVersion);
|
||||||
String expectedNimbusJoseJwtVersion = this.getExpectedNimbusJoseJwtVersion().get();
|
String expectedNimbusJoseJwtVersion = this.getExpectedNimbusJoseJwtVersion().get();
|
||||||
if (!transitiveNimbusJoseJwtVersion.equals(expectedNimbusJoseJwtVersion)) {
|
if (!transitiveNimbusJoseJwtVersion.equals(expectedNimbusJoseJwtVersion)) {
|
||||||
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, but the project contains a different version of nimbus-jose-jwt [%s]. Please align the versions.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
|
String transitiveNimbusJoseJwtMajorMinorVersion = transitiveNimbusJoseJwtVersion.substring(0, transitiveNimbusJoseJwtVersion.lastIndexOf("."));
|
||||||
throw new VerificationException(message);
|
String expectedNimbusJoseJwtMajorMinorVersion = expectedNimbusJoseJwtVersion.substring(0, expectedNimbusJoseJwtVersion.lastIndexOf("."));
|
||||||
|
if (!transitiveNimbusJoseJwtMajorMinorVersion.equals(expectedNimbusJoseJwtMajorMinorVersion)) {
|
||||||
|
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, but the project contains a different version of nimbus-jose-jwt [%s]. Please align the major/minor versions.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
|
||||||
|
throw new VerificationException(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, the project contains expected version of nimbus-jose-jwt [%s]. Verified all versions align.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
|
String message = String.format("Found transitive nimbus-jose-jwt:%s in oauth2-oidc-sdk:%s, the project contains expected version of nimbus-jose-jwt [%s]. Verified all versions align.", transitiveNimbusJoseJwtVersion, oauth2OidcSdkVersion, expectedNimbusJoseJwtVersion);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -17,6 +17,8 @@ package io.spring.gradle;
|
|||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.gradle.testkit.runner.GradleRunner;
|
import org.gradle.testkit.runner.GradleRunner;
|
||||||
|
import org.junit.runner.Description;
|
||||||
|
import org.junit.runners.model.Statement;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@ -23,6 +23,8 @@ import org.gradle.testfixtures.ProjectBuilder;
|
|||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import org.apache.commons.io.FileUtils;
|
|||||||
import org.gradle.testkit.runner.BuildResult;
|
import org.gradle.testkit.runner.BuildResult;
|
||||||
import org.gradle.testkit.runner.TaskOutcome;
|
import org.gradle.testkit.runner.TaskOutcome;
|
||||||
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.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,3 @@
|
|||||||
plugins {
|
|
||||||
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'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -17,11 +11,9 @@ dependencies {
|
|||||||
api 'org.springframework:spring-web'
|
api 'org.springframework:spring-web'
|
||||||
|
|
||||||
optional 'com.fasterxml.jackson.core:jackson-databind'
|
optional 'com.fasterxml.jackson.core:jackson-databind'
|
||||||
optional 'tools.jackson.core:jackson-databind'
|
|
||||||
|
|
||||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||||
|
|
||||||
testImplementation project(path : ':spring-security-web', configuration : 'tests')
|
|
||||||
testImplementation "org.assertj:assertj-core"
|
testImplementation "org.assertj:assertj-core"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
||||||
|
|||||||
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas;
|
package org.springframework.security.cas;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -36,7 +34,7 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
|
|
||||||
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
|
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
|
||||||
|
|
||||||
private @Nullable String service;
|
private String service;
|
||||||
|
|
||||||
private boolean authenticateAllArtifacts;
|
private boolean authenticateAllArtifacts;
|
||||||
|
|
||||||
@ -64,7 +62,7 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
* </pre>
|
* </pre>
|
||||||
* @return the URL of the service the user is authenticating to
|
* @return the URL of the service the user is authenticating to
|
||||||
*/
|
*/
|
||||||
public final @Nullable String getService() {
|
public final String getService() {
|
||||||
return this.service;
|
return this.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import java.util.ArrayList;
|
|||||||
import org.apereo.cas.client.validation.Assertion;
|
import org.apereo.cas.client.validation.Assertion;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporary authentication object needed to load the user details service.
|
* Temporary authentication object needed to load the user details service.
|
||||||
@ -30,7 +31,7 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
|
|||||||
*/
|
*/
|
||||||
public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
|
public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
private final Assertion assertion;
|
private final Assertion assertion;
|
||||||
|
|
||||||
|
|||||||
@ -16,15 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
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.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.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
@ -37,9 +33,7 @@ import org.springframework.security.authentication.BadCredentialsException;
|
|||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||||
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||||
@ -68,9 +62,6 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
||||||
|
|
||||||
private static final String AUTHORITY = FactorGrantedAuthority.CAS_AUTHORITY;
|
|
||||||
|
|
||||||
@SuppressWarnings("NullAway.Init")
|
|
||||||
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
||||||
|
|
||||||
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
||||||
@ -79,13 +70,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
|
|
||||||
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
||||||
|
|
||||||
@SuppressWarnings("NullAway.Init")
|
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
@SuppressWarnings("NullAway.Init")
|
|
||||||
private TicketValidator ticketValidator;
|
private TicketValidator ticketValidator;
|
||||||
|
|
||||||
private @Nullable ServiceProperties serviceProperties;
|
private ServiceProperties serviceProperties;
|
||||||
|
|
||||||
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
||||||
|
|
||||||
@ -100,7 +89,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
if (!supports(authentication.getClass())) {
|
if (!supports(authentication.getClass())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -140,17 +129,12 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
|
|
||||||
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
|
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
|
||||||
try {
|
try {
|
||||||
Object credentials = authentication.getCredentials();
|
Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(),
|
||||||
if (credentials == null) {
|
getServiceUrl(authentication));
|
||||||
throw new BadCredentialsException("Authentication.getCredentials() cannot be null");
|
|
||||||
}
|
|
||||||
Assertion assertion = this.ticketValidator.validate(credentials.toString(), getServiceUrl(authentication));
|
|
||||||
UserDetails userDetails = loadUserByAssertion(assertion);
|
UserDetails userDetails = loadUserByAssertion(assertion);
|
||||||
this.userDetailsChecker.check(userDetails);
|
this.userDetailsChecker.check(userDetails);
|
||||||
Collection<GrantedAuthority> authorities = new ArrayList<>(
|
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
|
||||||
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()));
|
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
|
||||||
authorities.add(FactorGrantedAuthority.fromAuthority(AUTHORITY));
|
|
||||||
return new CasAuthenticationToken(this.key, userDetails, credentials, authorities, userDetails, assertion);
|
|
||||||
}
|
}
|
||||||
catch (TicketValidationException ex) {
|
catch (TicketValidationException ex) {
|
||||||
throw new BadCredentialsException(ex.getMessage(), ex);
|
throw new BadCredentialsException(ex.getMessage(), ex);
|
||||||
@ -165,7 +149,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
* @param authentication
|
* @param authentication
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private @Nullable String getServiceUrl(Authentication authentication) {
|
private String getServiceUrl(Authentication authentication) {
|
||||||
String serviceUrl;
|
String serviceUrl;
|
||||||
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
||||||
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
|
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
|
||||||
@ -231,7 +215,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
return this.statelessTicketCache;
|
return this.statelessTicketCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @Nullable TicketValidator getTicketValidator() {
|
protected TicketValidator getTicketValidator() {
|
||||||
return this.ticketValidator;
|
return this.ticketValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,10 +20,10 @@ import java.io.Serializable;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.apereo.cas.client.validation.Assertion;
|
import org.apereo.cas.client.validation.Assertion;
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
@ -36,7 +36,7 @@ import org.springframework.util.ObjectUtils;
|
|||||||
*/
|
*/
|
||||||
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
private final Object credentials;
|
private final Object credentials;
|
||||||
|
|
||||||
@ -105,19 +105,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
setAuthenticated(true);
|
setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CasAuthenticationToken(Builder<?> builder) {
|
|
||||||
super(builder);
|
|
||||||
Assert.isTrue(!"".equals(builder.principal), "principal cannot be null or empty");
|
|
||||||
Assert.notNull(!"".equals(builder.credentials), "credentials cannot be null or empty");
|
|
||||||
Assert.notNull(builder.userDetails, "userDetails cannot be null");
|
|
||||||
Assert.notNull(builder.assertion, "assertion cannot be null");
|
|
||||||
this.keyHash = builder.keyHash;
|
|
||||||
this.principal = builder.principal;
|
|
||||||
this.credentials = builder.credentials;
|
|
||||||
this.userDetails = builder.userDetails;
|
|
||||||
this.assertion = builder.assertion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Integer extractKeyHash(String key) {
|
private static Integer extractKeyHash(String key) {
|
||||||
Assert.hasLength(key, "key cannot be null or empty");
|
Assert.hasLength(key, "key cannot be null or empty");
|
||||||
return key.hashCode();
|
return key.hashCode();
|
||||||
@ -167,11 +154,6 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
return this.userDetails;
|
return this.userDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder<?> toBuilder() {
|
|
||||||
return new Builder<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@ -181,81 +163,4 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
|||||||
return (sb.toString());
|
return (sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder of {@link CasAuthenticationToken} instances
|
|
||||||
*
|
|
||||||
* @since 7.0
|
|
||||||
*/
|
|
||||||
public static class Builder<B extends Builder<B>> extends AbstractAuthenticationBuilder<B> {
|
|
||||||
|
|
||||||
private Integer keyHash;
|
|
||||||
|
|
||||||
private Object principal;
|
|
||||||
|
|
||||||
private Object credentials;
|
|
||||||
|
|
||||||
private UserDetails userDetails;
|
|
||||||
|
|
||||||
private Assertion assertion;
|
|
||||||
|
|
||||||
protected Builder(CasAuthenticationToken token) {
|
|
||||||
super(token);
|
|
||||||
this.keyHash = token.keyHash;
|
|
||||||
this.principal = token.principal;
|
|
||||||
this.credentials = token.credentials;
|
|
||||||
this.userDetails = token.userDetails;
|
|
||||||
this.assertion = token.assertion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this key
|
|
||||||
* @param key the key to use
|
|
||||||
* @return the {@link Builder} for further configurations
|
|
||||||
*/
|
|
||||||
public B key(String key) {
|
|
||||||
this.keyHash = key.hashCode();
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public B principal(@Nullable Object principal) {
|
|
||||||
Assert.notNull(principal, "principal cannot be null");
|
|
||||||
this.principal = principal;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public B credentials(@Nullable Object credentials) {
|
|
||||||
Assert.notNull(credentials, "credentials cannot be null");
|
|
||||||
this.credentials = credentials;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this {@link UserDetails}
|
|
||||||
* @param userDetails the {@link UserDetails} to use
|
|
||||||
* @return the {@link Builder} for further configurations
|
|
||||||
*/
|
|
||||||
public B userDetails(UserDetails userDetails) {
|
|
||||||
this.userDetails = userDetails;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this {@link Assertion}
|
|
||||||
* @param assertion the {@link Assertion} to use
|
|
||||||
* @return the {@link Builder} for further configurations
|
|
||||||
*/
|
|
||||||
public B assertion(Assertion assertion) {
|
|
||||||
this.assertion = assertion;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CasAuthenticationToken build() {
|
|
||||||
return new CasAuthenticationToken(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,10 +19,9 @@ package org.springframework.security.cas.authentication;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,11 +38,11 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
|
static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
private final String identifier;
|
private final String identifier;
|
||||||
|
|
||||||
private @Nullable Object credentials;
|
private Object credentials;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor can be safely used by any code that wishes to create a
|
* This constructor can be safely used by any code that wishes to create a
|
||||||
@ -52,7 +51,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public CasServiceTicketAuthenticationToken(String identifier, Object credentials) {
|
public CasServiceTicketAuthenticationToken(String identifier, Object credentials) {
|
||||||
super((Collection<? extends GrantedAuthority>) null);
|
super(null);
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
setAuthenticated(false);
|
setAuthenticated(false);
|
||||||
@ -75,12 +74,6 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
super.setAuthenticated(true);
|
super.setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CasServiceTicketAuthenticationToken(Builder<?> builder) {
|
|
||||||
super(builder);
|
|
||||||
this.identifier = builder.principal;
|
|
||||||
this.credentials = builder.credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CasServiceTicketAuthenticationToken stateful(Object credentials) {
|
public static CasServiceTicketAuthenticationToken stateful(Object credentials) {
|
||||||
return new CasServiceTicketAuthenticationToken(CAS_STATEFUL_IDENTIFIER, credentials);
|
return new CasServiceTicketAuthenticationToken(CAS_STATEFUL_IDENTIFIER, credentials);
|
||||||
}
|
}
|
||||||
@ -94,7 +87,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return this.credentials;
|
return this.credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,46 +109,4 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
this.credentials = null;
|
this.credentials = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder<?> toBuilder() {
|
|
||||||
return new Builder<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder of {@link CasServiceTicketAuthenticationToken} instances
|
|
||||||
*
|
|
||||||
* @since 7.0
|
|
||||||
*/
|
|
||||||
public static class Builder<B extends Builder<B>> extends AbstractAuthenticationBuilder<B> {
|
|
||||||
|
|
||||||
private String principal;
|
|
||||||
|
|
||||||
private @Nullable Object credentials;
|
|
||||||
|
|
||||||
protected Builder(CasServiceTicketAuthenticationToken token) {
|
|
||||||
super(token);
|
|
||||||
this.principal = token.identifier;
|
|
||||||
this.credentials = token.credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public B principal(@Nullable Object principal) {
|
|
||||||
Assert.isInstanceOf(String.class, principal, "principal must be of type String");
|
|
||||||
this.principal = (String) principal;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public B credentials(@Nullable Object credentials) {
|
|
||||||
Assert.notNull(credentials, "credentials cannot be null");
|
|
||||||
this.credentials = credentials;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CasServiceTicketAuthenticationToken build() {
|
|
||||||
return new CasServiceTicketAuthenticationToken(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
|
* Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
|
||||||
* in instances where storing of tickets for stateless session management is not required.
|
* in instances where storing of tickets for stateless session management is not required.
|
||||||
@ -35,7 +33,7 @@ public final class NullStatelessTicketCache implements StatelessTicketCache {
|
|||||||
* @return null since we are not storing any tickets.
|
* @return null since we are not storing any tickets.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@ package org.springframework.security.cas.authentication;
|
|||||||
|
|
||||||
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.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
@ -43,7 +42,7 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
||||||
final Cache.ValueWrapper element = (serviceTicket != null) ? this.cache.get(serviceTicket) : null;
|
final Cache.ValueWrapper element = (serviceTicket != null) ? this.cache.get(serviceTicket) : null;
|
||||||
logger.debug(LogMessage.of(() -> "Cache hit: " + (element != null) + "; service ticket: " + serviceTicket));
|
logger.debug(LogMessage.of(() -> "Cache hit: " + (element != null) + "; service ticket: " + serviceTicket));
|
||||||
return (element != null) ? (CasAuthenticationToken) element.get() : null;
|
return (element != null) ? (CasAuthenticationToken) element.get() : null;
|
||||||
|
|||||||
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches CAS service tickets and CAS proxy tickets for stateless connections.
|
* Caches CAS service tickets and CAS proxy tickets for stateless connections.
|
||||||
*
|
*
|
||||||
@ -71,7 +69,7 @@ public interface StatelessTicketCache {
|
|||||||
* </p>
|
* </p>
|
||||||
* @return the fully populated authentication token
|
* @return the fully populated authentication token
|
||||||
*/
|
*/
|
||||||
@Nullable CasAuthenticationToken getByTicketId(String serviceTicket);
|
CasAuthenticationToken getByTicketId(String serviceTicket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the specified <code>CasAuthenticationToken</code> to the cache.
|
* Adds the specified <code>CasAuthenticationToken</code> to the cache.
|
||||||
|
|||||||
@ -18,7 +18,4 @@
|
|||||||
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
|
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
|
||||||
* tickets.
|
* tickets.
|
||||||
*/
|
*/
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
|
|||||||
@ -1,60 +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.cas.jackson;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|
||||||
import org.apereo.cas.client.authentication.AttributePrincipal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helps in jackson deserialization of class
|
|
||||||
* {@link org.apereo.cas.client.validation.AssertionImpl}, which is used with
|
|
||||||
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}.
|
|
||||||
*
|
|
||||||
* @author Sebastien Deleuze
|
|
||||||
* @author Jitendra Singh
|
|
||||||
* @since 7.0
|
|
||||||
* @see CasJacksonModule
|
|
||||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
|
||||||
*/
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
|
||||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
|
||||||
class AssertionImplMixin {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mixin Constructor helps in deserialize
|
|
||||||
* {@link org.apereo.cas.client.validation.AssertionImpl}
|
|
||||||
* @param principal the Principal to associate with the Assertion.
|
|
||||||
* @param validFromDate when the assertion is valid from.
|
|
||||||
* @param validUntilDate when the assertion is valid to.
|
|
||||||
* @param authenticationDate when the assertion is authenticated.
|
|
||||||
* @param attributes the key/value pairs for this attribute.
|
|
||||||
*/
|
|
||||||
@JsonCreator
|
|
||||||
AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal,
|
|
||||||
@JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate,
|
|
||||||
@JsonProperty("authenticationDate") Date authenticationDate,
|
|
||||||
@JsonProperty("attributes") Map<String, Object> attributes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,59 +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.cas.jackson;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|
||||||
import org.apereo.cas.client.proxy.ProxyRetriever;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helps in deserialize
|
|
||||||
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl} which is used with
|
|
||||||
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}.
|
|
||||||
*
|
|
||||||
* @author Sebastien Deleuze
|
|
||||||
* @author Jitendra Singh
|
|
||||||
* @since 7.0
|
|
||||||
* @see CasJacksonModule
|
|
||||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
|
||||||
*/
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
|
||||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
|
||||||
class AttributePrincipalImplMixin {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mixin Constructor helps in deserialize
|
|
||||||
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl}
|
|
||||||
* @param name the unique identifier for the principal.
|
|
||||||
* @param attributes the key/value pairs for this principal.
|
|
||||||
* @param proxyGrantingTicket the ticket associated with this principal.
|
|
||||||
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS
|
|
||||||
* server.
|
|
||||||
*/
|
|
||||||
@JsonCreator
|
|
||||||
AttributePrincipalImplMixin(@JsonProperty("name") String name,
|
|
||||||
@JsonProperty("attributes") Map<String, Object> attributes,
|
|
||||||
@JsonProperty("proxyGrantingTicket") String proxyGrantingTicket,
|
|
||||||
@JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,69 +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.cas.jackson;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|
||||||
import org.apereo.cas.client.validation.Assertion;
|
|
||||||
|
|
||||||
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
|
|
||||||
import org.springframework.security.cas.authentication.CasAuthenticationToken;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mixin class which helps in deserialize {@link CasAuthenticationToken} using jackson.
|
|
||||||
*
|
|
||||||
* @author Sebastien Deleuze
|
|
||||||
* @author Jitendra Singh
|
|
||||||
* @since 7.0
|
|
||||||
* @see CasJacksonModule
|
|
||||||
* @see org.springframework.security.jackson.SecurityJacksonModules
|
|
||||||
*/
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
|
|
||||||
getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY)
|
|
||||||
class CasAuthenticationTokenMixin {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mixin Constructor helps in deserialize {@link CasAuthenticationToken}
|
|
||||||
* @param keyHash hashCode of provided key to identify if this object made by a given
|
|
||||||
* {@link CasAuthenticationProvider}
|
|
||||||
* @param principal typically the UserDetails object (cannot be <code>null</code>)
|
|
||||||
* @param credentials the service/proxy ticket ID from CAS (cannot be
|
|
||||||
* <code>null</code>)
|
|
||||||
* @param authorities the authorities granted to the user (from the
|
|
||||||
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
|
||||||
* be <code>null</code>)
|
|
||||||
* @param userDetails the user details (from the
|
|
||||||
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
|
|
||||||
* be <code>null</code>)
|
|
||||||
* @param assertion the assertion returned from the CAS servers. It contains the
|
|
||||||
* principal and how to obtain a proxy ticket for the user.
|
|
||||||
*/
|
|
||||||
@JsonCreator
|
|
||||||
CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal,
|
|
||||||
@JsonProperty("credentials") Object credentials,
|
|
||||||
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities,
|
|
||||||
@JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,71 +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.cas.jackson;
|
|
||||||
|
|
||||||
import org.apereo.cas.client.authentication.AttributePrincipalImpl;
|
|
||||||
import org.apereo.cas.client.validation.AssertionImpl;
|
|
||||||
import tools.jackson.core.Version;
|
|
||||||
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
|
|
||||||
|
|
||||||
import org.springframework.security.cas.authentication.CasAuthenticationToken;
|
|
||||||
import org.springframework.security.jackson.SecurityJacksonModule;
|
|
||||||
import org.springframework.security.jackson.SecurityJacksonModules;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jackson module for spring-security-cas. This module register
|
|
||||||
* {@link AssertionImplMixin}, {@link AttributePrincipalImplMixin} and
|
|
||||||
* {@link CasAuthenticationTokenMixin}. If no default typing enabled by default then it'll
|
|
||||||
* enable it because typing info is needed to properly serialize/deserialize objects. In
|
|
||||||
* order to use this module just add this module into your JsonMapper configuration.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The recommended way to configure it is to use {@link SecurityJacksonModules} in order
|
|
||||||
* to enable properly automatic inclusion of type information with related validation.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* ClassLoader loader = getClass().getClassLoader();
|
|
||||||
* JsonMapper mapper = JsonMapper.builder()
|
|
||||||
* .addModules(SecurityJacksonModules.getModules(loader))
|
|
||||||
* .build();
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Sebastien Deleuze
|
|
||||||
* @author Jitendra Singh
|
|
||||||
* @since 7.0
|
|
||||||
* @see SecurityJacksonModules
|
|
||||||
*/
|
|
||||||
public class CasJacksonModule extends SecurityJacksonModule {
|
|
||||||
|
|
||||||
public CasJacksonModule() {
|
|
||||||
super(CasJacksonModule.class.getName(), new Version(1, 0, 0, null, null, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Builder builder) {
|
|
||||||
builder.allowIfSubType(AssertionImpl.class)
|
|
||||||
.allowIfSubType(AttributePrincipalImpl.class)
|
|
||||||
.allowIfSubType(CasAuthenticationToken.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupModule(SetupContext context) {
|
|
||||||
context.setMixIn(AssertionImpl.class, AssertionImplMixin.class);
|
|
||||||
context.setMixIn(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class);
|
|
||||||
context.setMixIn(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jackson 3+ serialization support for CAS.
|
|
||||||
*/
|
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.cas.jackson;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
@ -33,7 +33,6 @@ import org.apereo.cas.client.authentication.AttributePrincipal;
|
|||||||
* this class we need to register with
|
* this class we need to register with
|
||||||
* {@link com.fasterxml.jackson.databind.ObjectMapper}. Type information will be stored
|
* {@link com.fasterxml.jackson.databind.ObjectMapper}. Type information will be stored
|
||||||
* in @class property.
|
* in @class property.
|
||||||
*
|
|
||||||
* <p>
|
* <p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* ObjectMapper mapper = new ObjectMapper();
|
* ObjectMapper mapper = new ObjectMapper();
|
||||||
@ -44,11 +43,7 @@ import org.apereo.cas.client.authentication.AttributePrincipal;
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
* @see CasJackson2Module
|
* @see CasJackson2Module
|
||||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||||
* @deprecated as of 7.0 in favor of
|
|
||||||
* {@code org.springframework.security.cas.jackson.AssertionImplMixin} based on Jackson 3
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||||
|
|||||||
@ -30,7 +30,6 @@ import org.apereo.cas.client.proxy.ProxyRetriever;
|
|||||||
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl} which is used with
|
* {@link org.apereo.cas.client.authentication.AttributePrincipalImpl} which is used with
|
||||||
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. Type
|
* {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. Type
|
||||||
* information will be stored in property named @class.
|
* information will be stored in property named @class.
|
||||||
*
|
|
||||||
* <p>
|
* <p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* ObjectMapper mapper = new ObjectMapper();
|
* ObjectMapper mapper = new ObjectMapper();
|
||||||
@ -41,12 +40,7 @@ import org.apereo.cas.client.proxy.ProxyRetriever;
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
* @see CasJackson2Module
|
* @see CasJackson2Module
|
||||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||||
* @deprecated as of 7.0 in favor of
|
|
||||||
* {@code org.springframework.security.cas.jackson.AttributePrincipalImplMixin} based on
|
|
||||||
* Jackson 3
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import org.springframework.security.core.userdetails.UserDetails;
|
|||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* ObjectMapper mapper = new ObjectMapper();
|
* ObjectMapper mapper = new ObjectMapper();
|
||||||
* mapper.registerModule(new CasJackson2Module());
|
* mapper.registerModule(new CasJackson2Module());
|
||||||
@ -49,12 +50,7 @@ import org.springframework.security.core.userdetails.UserDetails;
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
* @see CasJackson2Module
|
* @see CasJackson2Module
|
||||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||||
* @deprecated as of 7.0 in favor of
|
|
||||||
* {@code org.springframework.security.cas.jackson.CasAuthenticationTokenMixin} based on
|
|
||||||
* Jackson 3
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
|
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||||
getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY)
|
getterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY)
|
||||||
|
|||||||
@ -37,14 +37,11 @@ import org.springframework.security.jackson2.SecurityJackson2Modules;
|
|||||||
* </pre> <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list
|
* </pre> <b>Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list
|
||||||
* of all security modules on the classpath.</b>
|
* of all security modules on the classpath.</b>
|
||||||
*
|
*
|
||||||
* @author Jitendra Singh
|
* @author Jitendra Singh.
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
* @see org.springframework.security.jackson2.SecurityJackson2Modules
|
||||||
* @deprecated as of 7.0 in favor of
|
|
||||||
* {@link org.springframework.security.cas.jackson.CasJacksonModule} based on Jackson 3
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@SuppressWarnings("serial")
|
||||||
@SuppressWarnings({ "serial", "removal" })
|
|
||||||
public class CasJackson2Module extends SimpleModule {
|
public class CasJackson2Module extends SimpleModule {
|
||||||
|
|
||||||
public CasJackson2Module() {
|
public CasJackson2Module() {
|
||||||
|
|||||||
@ -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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jackson 2 support for CAS.
|
|
||||||
*/
|
|
||||||
@NullMarked
|
|
||||||
package org.springframework.security.cas.jackson2;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.NullMarked;
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user