mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-03-06 11:44:45 +00:00
Compare commits
405 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56055605cd | ||
|
|
de3c72735e | ||
|
|
96bf048dd2 | ||
|
|
07297e7a80 | ||
|
|
b1f4deafe6 | ||
|
|
9893048ec9 | ||
|
|
e17d85e460 | ||
|
|
94829a1551 | ||
|
|
4f97217f68 | ||
|
|
4907d56a04 | ||
|
|
fdaa883fb7 | ||
|
|
f12036db05 | ||
|
|
b308c74c5e | ||
|
|
fbd9880a33 | ||
|
|
f14d2d2242 | ||
|
|
5e38c2aa88 | ||
|
|
7b5c502a97 | ||
|
|
e7bf4b561c | ||
|
|
41e3aeb246 | ||
|
|
89260a3a9c | ||
|
|
a84b506196 | ||
|
|
57434fc597 | ||
|
|
a01c0d003c | ||
|
|
20a7f96062 | ||
|
|
706b059ea8 | ||
|
|
f8d58fb267 | ||
|
|
7c49e0b457 | ||
|
|
2ac079dd1a | ||
|
|
04b270a0a3 | ||
|
|
7e4a926527 | ||
|
|
ea3b112bea | ||
|
|
17776e4738 | ||
|
|
1261c229a3 | ||
|
|
25ccb1fd70 | ||
|
|
587ac2cbad | ||
|
|
498b0cb59c | ||
|
|
b05b25f2d6 | ||
|
|
a5c0113ff0 | ||
|
|
bafd4034a0 | ||
|
|
ca34ec26d8 | ||
|
|
30dd328272 | ||
|
|
9f9bc0f729 | ||
|
|
9ce2d76508 | ||
|
|
0bb697c4a7 | ||
|
|
fb84e24893 | ||
|
|
b19e0e1ff3 | ||
|
|
c869565ab6 | ||
|
|
6118557b3e | ||
|
|
b9f974b18f | ||
|
|
e43275d1db | ||
|
|
18995c89ee | ||
|
|
0c42016781 | ||
|
|
1575610d49 | ||
|
|
3a14745d92 | ||
|
|
bd51ecd691 | ||
|
|
c29af014f4 | ||
|
|
4501ae7d1c | ||
|
|
48112d3d74 | ||
|
|
b8735abb63 | ||
|
|
50caf0cb28 | ||
|
|
7c3c8bbdcb | ||
|
|
b7dbb12c66 | ||
|
|
731848d5d3 | ||
|
|
eb25bbaa24 | ||
|
|
68a02ff176 | ||
|
|
ee97c83042 | ||
|
|
6304ea78cc | ||
|
|
10b835693c | ||
|
|
ba12f5e6d0 | ||
|
|
f37a706d62 | ||
|
|
e30d9240c9 | ||
|
|
c208410a91 | ||
|
|
aabc9fc1cc | ||
|
|
d3474e704f | ||
|
|
b48967eebc | ||
|
|
522c48b3b5 | ||
|
|
9cc3161055 | ||
|
|
6898de8003 | ||
|
|
1dae9aa459 | ||
|
|
4b0be84a0e | ||
|
|
73ee893d98 | ||
|
|
bec25edeb0 | ||
|
|
4d43edfb20 | ||
|
|
9f9699f8a5 | ||
|
|
6d4726bfb7 | ||
|
|
d31ca7a758 | ||
|
|
ac06067d02 | ||
|
|
9f1381c382 | ||
|
|
f700aeac0f | ||
|
|
41a8d6aca5 | ||
|
|
e81c64b94d | ||
|
|
0c394696ce | ||
|
|
62d1bc86e3 | ||
|
|
a4cadb5cc5 | ||
|
|
701736da5d | ||
|
|
9e5a425859 | ||
|
|
1ab17d941a | ||
|
|
53300be8d7 | ||
|
|
d5ba9dcada | ||
|
|
fa87c78edb | ||
|
|
f1e367f93d | ||
|
|
4d0627e6c0 | ||
|
|
3106f2be7b | ||
|
|
b3e5f09eb3 | ||
|
|
e1436c39f0 | ||
|
|
311235f39e | ||
|
|
fec988c82d | ||
|
|
17b434c1c1 | ||
|
|
b451739b5c | ||
|
|
0bb65411be | ||
|
|
d29c984881 | ||
|
|
cfb3bf38d8 | ||
|
|
151bcf3b0b | ||
|
|
1116241ee3 | ||
|
|
d87dc9ae57 | ||
|
|
ea1b3d819b | ||
|
|
2eb948d9b5 | ||
|
|
881ddf796a | ||
|
|
f2aef5168c | ||
|
|
ac556a45f9 | ||
|
|
c8731a8dc0 | ||
|
|
d62cce5bfb | ||
|
|
eca68b6cb3 | ||
|
|
3e60eeb74c | ||
|
|
21978cab22 | ||
|
|
2dd2863550 | ||
|
|
1fdfd45782 | ||
|
|
0dc1aa1126 | ||
|
|
3cc707621f | ||
|
|
f8ac095d48 | ||
|
|
d65625e399 | ||
|
|
18068c9099 | ||
|
|
a539f056f7 | ||
|
|
2b04177151 | ||
|
|
a4a6e9124c | ||
|
|
b21159f453 | ||
|
|
6f7c8cb352 | ||
|
|
5973a66bb1 | ||
|
|
3e3eeda560 | ||
|
|
cc6a005aa5 | ||
|
|
d4589c0fcb | ||
|
|
e2486a2590 | ||
|
|
dbf7f4cfe5 | ||
|
|
f27738c1f8 | ||
|
|
8d76ae0844 | ||
|
|
73b055baa9 | ||
|
|
5194826606 | ||
|
|
fc48088759 | ||
|
|
d528be38bb | ||
|
|
da0cd0bc68 | ||
|
|
410812c5bc | ||
|
|
329d9e2dfd | ||
|
|
dc8ed8b168 | ||
|
|
17933ddab3 | ||
|
|
deb6416c93 | ||
|
|
9323775c5f | ||
|
|
4cc5f543ab | ||
|
|
67bc1d8d4a | ||
|
|
17b5cdde55 | ||
|
|
e91b098c7c | ||
|
|
21bef947b0 | ||
|
|
6fcca39500 | ||
|
|
544f635e9b | ||
|
|
e4dcffae8a | ||
|
|
f52f097a4d | ||
|
|
1cd145d026 | ||
|
|
3c55f057b1 | ||
|
|
6d2a414022 | ||
|
|
58df50c3a3 | ||
|
|
79156b2387 | ||
|
|
4aa9ff99f5 | ||
|
|
9b978ae70b | ||
|
|
3abb69d5a9 | ||
|
|
6c2b2a7611 | ||
|
|
0fab34f359 | ||
|
|
73dff1f8a3 | ||
|
|
e5906d97ea | ||
|
|
928ad9600c | ||
|
|
c0da8b390b | ||
|
|
f9b2c86e1d | ||
|
|
08e5b375ac | ||
|
|
f9c32afb6f | ||
|
|
d77e48f9ef | ||
|
|
25da472d67 | ||
|
|
9d3e217b79 | ||
|
|
7bbfc09f49 | ||
|
|
85e2d9298b | ||
|
|
bc6ce0d346 | ||
|
|
3d61276a1a | ||
|
|
25aec8c5e0 | ||
|
|
6eb0af9912 | ||
|
|
7fdff6a907 | ||
|
|
117af3bc2b | ||
|
|
c7f781423f | ||
|
|
0d3a5d210a | ||
|
|
fb2f0d5c38 | ||
|
|
10b9cc8c2b | ||
|
|
5240878272 | ||
|
|
ba4bd61c5b | ||
|
|
c25ec70374 | ||
|
|
8e1e0ca9d2 | ||
|
|
705fa60a01 | ||
|
|
f2b7cb2de5 | ||
|
|
8652950fb2 | ||
|
|
07ba3e623f | ||
|
|
f91b5f33fc | ||
|
|
095cc3bf74 | ||
|
|
5418ab2081 | ||
|
|
e8e4110334 | ||
|
|
92fd945b02 | ||
|
|
d0b0b5a252 | ||
|
|
601dfb2764 | ||
|
|
b88ddc8d0d | ||
|
|
688b6ca733 | ||
|
|
17e368435d | ||
|
|
6b028cfe8e | ||
|
|
d912393280 | ||
|
|
ba8360671c | ||
|
|
bf7d86722f | ||
|
|
e37f83884b | ||
|
|
3071459fe4 | ||
|
|
03c081bb46 | ||
|
|
540fbdb189 | ||
|
|
cea004b555 | ||
|
|
4c011887bd | ||
|
|
938d1f38b9 | ||
|
|
54f294fe6e | ||
|
|
fa10e74d76 | ||
|
|
0a8cdc32d5 | ||
|
|
5a51d63419 | ||
|
|
ee7c579644 | ||
|
|
b92f4e7ed2 | ||
|
|
9dff826c9f | ||
|
|
ee2702254e | ||
|
|
f0ad037099 | ||
|
|
8d426bd28f | ||
|
|
a8a859ec0e | ||
|
|
d467da7717 | ||
|
|
55ef3ce477 | ||
|
|
bbb6f499c9 | ||
|
|
3386e077e6 | ||
|
|
10490a7b92 | ||
|
|
f1e742dfc5 | ||
|
|
8e9480545e | ||
|
|
0eb5d8f356 | ||
|
|
3e238af024 | ||
|
|
29ed4dd724 | ||
|
|
218b13884f | ||
|
|
fc2fd63793 | ||
|
|
199473fcb3 | ||
|
|
7903ad93c0 | ||
|
|
fe65ef2626 | ||
|
|
2af6e1cf92 | ||
|
|
e535803cc2 | ||
|
|
eeb080a191 | ||
|
|
b8c6b9fbff | ||
|
|
3cf0a1ccb7 | ||
|
|
c2f0f7b6ab | ||
|
|
8cd2f36e84 | ||
|
|
517bc7cb65 | ||
|
|
a2d407518c | ||
|
|
001d9df5ca | ||
|
|
818a7831dd | ||
|
|
0eba9de7d4 | ||
|
|
70fc8fef3a | ||
|
|
46027974dd | ||
|
|
338786bab9 | ||
|
|
d7ecb8fdcf | ||
|
|
a9f9eba6ca | ||
|
|
1a6f344196 | ||
|
|
e771ec04b7 | ||
|
|
f3656b4991 | ||
|
|
8f22fd4407 | ||
|
|
20493ef45f | ||
|
|
e029b3ac6f | ||
|
|
55ab498518 | ||
|
|
b0983e2f5e | ||
|
|
992d8ca79b | ||
|
|
4c012c59c9 | ||
|
|
2ee247f82e | ||
|
|
0496c02c30 | ||
|
|
93d8283e36 | ||
|
|
991b7d4dc2 | ||
|
|
64e863e7df | ||
|
|
4957c5a7e9 | ||
|
|
5b7c4ae8d8 | ||
|
|
8bafd94b1f | ||
|
|
d244bcf76e | ||
|
|
de23ade14b | ||
|
|
afa3e2311c | ||
|
|
2a2f13fbd3 | ||
|
|
db5310bee8 | ||
|
|
dfed528851 | ||
|
|
6a6c7a7a78 | ||
|
|
b591a0a757 | ||
|
|
c5632ccd83 | ||
|
|
a8b5c8fe02 | ||
|
|
054ff7421b | ||
|
|
6e30cd5417 | ||
|
|
c7d52242fb | ||
|
|
6f6dbd5728 | ||
|
|
99eb7b1e5c | ||
|
|
89467605ca | ||
|
|
9fa0a34b4c | ||
|
|
a23be5e625 | ||
|
|
c3240c4d2b | ||
|
|
3c0fd6d7ca | ||
|
|
d526bb460f | ||
|
|
30975df0a7 | ||
|
|
bd49ceb0ef | ||
|
|
1c8bbda7af | ||
|
|
fb19143c91 | ||
|
|
f906539fe4 | ||
|
|
18ab4dc2c8 | ||
|
|
b07cd701c7 | ||
|
|
ea8bd1a01d | ||
|
|
0a182f1f20 | ||
|
|
5e56877487 | ||
|
|
38356fda10 | ||
|
|
442d72ec12 | ||
|
|
7513c859bd | ||
|
|
1b3cf72fc9 | ||
|
|
d7fbf3673a | ||
|
|
ab3298e917 | ||
|
|
37b0813b26 | ||
|
|
0340e0e918 | ||
|
|
fc5194d78b | ||
|
|
e7203bf838 | ||
|
|
42e1e9fb67 | ||
|
|
91aee30906 | ||
|
|
8247d18122 | ||
|
|
f942ead2eb | ||
|
|
b970746a03 | ||
|
|
131d3741b2 | ||
|
|
e7aa15cb81 | ||
|
|
af73f85f66 | ||
|
|
39544e1b9e | ||
|
|
d07d3a13d1 | ||
|
|
bf6bed01af | ||
|
|
74c454a5c7 | ||
|
|
2206815ad9 | ||
|
|
6695505676 | ||
|
|
6b4649ad3e | ||
|
|
7ace59c411 | ||
|
|
1cfb3033e9 | ||
|
|
021f84b2df | ||
|
|
e5b934d1a5 | ||
|
|
e3f1690396 | ||
|
|
1fb335c3b1 | ||
|
|
cd2be2fc1c | ||
|
|
feb3e9c3cc | ||
|
|
95d31a3754 | ||
|
|
ef7bb7d334 | ||
|
|
9f8ac34c3b | ||
|
|
3f66d8b770 | ||
|
|
ea26031a4d | ||
|
|
b1d98491cf | ||
|
|
c64747ce5f | ||
|
|
cd4ad01742 | ||
|
|
0a035caa57 | ||
|
|
ab8b139278 | ||
|
|
e19c34771b | ||
|
|
318b4a785c | ||
|
|
c73696f129 | ||
|
|
35d103843b | ||
|
|
8746ef746c | ||
|
|
e72c39cabc | ||
|
|
a8ca5b7d42 | ||
|
|
afa5804170 | ||
|
|
15dd96bddb | ||
|
|
6b2e0444dd | ||
|
|
577d294fdc | ||
|
|
0993e5735e | ||
|
|
048b6bdd88 | ||
|
|
6e9b4f86a4 | ||
|
|
38b66e8407 | ||
|
|
9e5b3d9ea1 | ||
|
|
7563932106 | ||
|
|
48f958cbbf | ||
|
|
30d6b3a02b | ||
|
|
cfe13c7c76 | ||
|
|
3336f5f2ec | ||
|
|
565896404c | ||
|
|
91d8a04ec2 | ||
|
|
8254f589b8 | ||
|
|
3f773abf7c | ||
|
|
92b7c41f2f | ||
|
|
8692185de1 | ||
|
|
7ca0f7723e | ||
|
|
a612522ecd | ||
|
|
fe138d6434 | ||
|
|
93ae52aa58 | ||
|
|
43fe5f6b46 | ||
|
|
f47f81351e | ||
|
|
0d47870928 | ||
|
|
da4362111a | ||
|
|
1ddccd8a39 | ||
|
|
2825aa3ff1 | ||
|
|
ec06f08bb6 | ||
|
|
0a6883c586 | ||
|
|
c07a2e57bd | ||
|
|
5a7d93ee3b | ||
|
|
a3b57c470f | ||
|
|
d1a32b4b62 | ||
|
|
3833650d33 |
123
.github/dependabot.yml
vendored
123
.github/dependabot.yml
vendored
@ -1,12 +1,10 @@
|
|||||||
version: 2
|
version: 2
|
||||||
registries:
|
registries:
|
||||||
spring-milestones:
|
|
||||||
type: maven-repository
|
|
||||||
url: https://repo.spring.io/milestone
|
|
||||||
shibboleth:
|
shibboleth:
|
||||||
type: maven-repository
|
type: maven-repository
|
||||||
url: https://build.shibboleth.net/maven/releases
|
url: https://build.shibboleth.net/maven/releases
|
||||||
updates:
|
updates:
|
||||||
|
# 6.5.x
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: 6.5.x
|
target-branch: 6.5.x
|
||||||
directory: /
|
directory: /
|
||||||
@ -17,7 +15,6 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- spring-milestones
|
|
||||||
- shibboleth
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
@ -34,8 +31,28 @@ 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: 6.4.x
|
target-branch: 7.0.x
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
@ -44,10 +61,10 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- spring-milestones
|
|
||||||
- shibboleth
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
|
- dependency-name: io.spring.nullability:*
|
||||||
- dependency-name: org.python:jython
|
- dependency-name: org.python:jython
|
||||||
- dependency-name: org.apache.directory.server:*
|
- dependency-name: org.apache.directory.server:*
|
||||||
- dependency-name: org.apache.directory.shared:*
|
- dependency-name: org.apache.directory.shared:*
|
||||||
@ -57,11 +74,34 @@ 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: /
|
||||||
@ -72,7 +112,6 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- spring-milestones
|
|
||||||
- shibboleth
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
@ -92,17 +131,6 @@ updates:
|
|||||||
- dependency-name: '*'
|
- dependency-name: '*'
|
||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
- version-update:semver-minor
|
|
||||||
|
|
||||||
- package-ecosystem: npm
|
|
||||||
target-branch: docs-build
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'in: build'
|
|
||||||
|
|
||||||
- package-ecosystem: npm
|
- package-ecosystem: npm
|
||||||
target-branch: main
|
target-branch: main
|
||||||
directory: /docs
|
directory: /docs
|
||||||
@ -110,4 +138,63 @@ updates:
|
|||||||
interval: weekly
|
interval: weekly
|
||||||
labels:
|
labels:
|
||||||
- 'type: task'
|
- 'type: task'
|
||||||
|
- 'type: dependency-upgrade'
|
||||||
|
- '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
|
||||||
|
target-branch: docs-build
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
labels:
|
||||||
|
- '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
Normal file
16
.github/workflows/auto-merge-dependabot.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
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
|
||||||
10
.github/workflows/check-snapshots.yml
vendored
10
.github/workflows/check-snapshots.yml
vendored
@ -14,14 +14,12 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
snapshot-test:
|
snapshot-test:
|
||||||
name: Test Against Snapshots
|
name: Test Against Snapshots
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@v1
|
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- java-version: 21-ea
|
- java-version: 25
|
||||||
toolchain: 21
|
toolchain: 25
|
||||||
- java-version: 17
|
|
||||||
toolchain: 17
|
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
|
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
|
||||||
@ -33,6 +31,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Send Notification
|
- name: Send Notification
|
||||||
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||||
with:
|
with:
|
||||||
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
jdk: [ 17 ]
|
jdk: [ 25 ]
|
||||||
with:
|
with:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
java-version: ${{ matrix.jdk }}
|
java-version: ${{ matrix.jdk }}
|
||||||
@ -34,6 +34,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
default-publish-milestones-central: true
|
default-publish-milestones-central: true
|
||||||
|
java-version: 25
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
deploy-schema:
|
deploy-schema:
|
||||||
name: Deploy Schema
|
name: Deploy Schema
|
||||||
@ -41,6 +42,7 @@ jobs:
|
|||||||
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
|
||||||
@ -53,6 +55,7 @@ jobs:
|
|||||||
release-repo-url: https://repo1.maven.org/maven2
|
release-repo-url: https://repo1.maven.org/maven2
|
||||||
artifact-path: org/springframework/security/spring-security-core
|
artifact-path: org/springframework/security/spring-security-core
|
||||||
slack-announcing-id: spring-security-announcing
|
slack-announcing-id: spring-security-announcing
|
||||||
|
java-version: 25
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
send-notification:
|
send-notification:
|
||||||
name: Send Notification
|
name: Send Notification
|
||||||
|
|||||||
2
.github/workflows/finalize-release.yml
vendored
2
.github/workflows/finalize-release.yml
vendored
@ -16,7 +16,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
perform-release:
|
perform-release:
|
||||||
name: Perform Release
|
name: Perform Release
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@v1
|
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@729fed56d42122f88583aff1be35c0800b7d77e9 # v1.0.14
|
||||||
with:
|
with:
|
||||||
should-perform-release: true
|
should-perform-release: true
|
||||||
project-version: ${{ inputs.version }}
|
project-version: ${{ inputs.version }}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
upgrade_wrapper:
|
upgrade_wrapper:
|
||||||
name: Execution
|
name: Execution
|
||||||
|
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Git configuration
|
- name: Set up Git configuration
|
||||||
@ -20,10 +21,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 17
|
- name: Set up JDK 25
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '25'
|
||||||
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: '17'
|
java-version: '25'
|
||||||
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: '17'
|
java-version: '25'
|
||||||
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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.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, 6.5.x, 6.4.x, 6.3.x ]
|
branch: [ main, 7.0.x, 6.5.x, 6.4.x, 6.3.x ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@ -12,11 +12,12 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-antora-ui-spring:
|
update-antora-ui-spring:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Update on Supported Branches
|
name: Update on Supported Branches
|
||||||
|
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
branch: [ '6.4.x', '6.5.x', 'main' ]
|
branch: [ '6.5.x', '7.0.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
|
||||||
@ -25,8 +26,9 @@ 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:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Update on docs-build
|
name: Update on docs-build
|
||||||
|
if: ${{ github.repository == 'spring-projects/spring-security' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
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
|
||||||
|
|||||||
@ -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=17.0.3-tem
|
java=25-librca
|
||||||
|
|||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"java.import.gradle.enabled": false
|
"java.gradle.buildServer.enabled": "off"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ If you have a question, check Stack Overflow using
|
|||||||
https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags].
|
https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags].
|
||||||
Find an existing discussion, or start a new one if necessary.
|
Find an existing discussion, or start a new one if necessary.
|
||||||
|
|
||||||
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
|
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
|
||||||
Reading those discussions helps you to learn about the issue, and helps us to make a decision.
|
Reading those discussions helps you to learn about the issue, and helps us to make a decision.
|
||||||
|
|
||||||
[[find-an-issue]]
|
[[find-an-issue]]
|
||||||
@ -94,7 +94,7 @@ Don't worry if you don't get them all correct the first time, we will help you.
|
|||||||
|
|
||||||
1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
|
1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
|
||||||
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
|
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
|
||||||
2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier 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 to 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,6 +68,27 @@ 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,3 +1,8 @@
|
|||||||
|
plugins {
|
||||||
|
id 'compile-warnings-error'
|
||||||
|
id 'javadoc-warnings-error'
|
||||||
|
}
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import org.jspecify.annotations.Nullable;
|
|||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;
|
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sources method security metadata from major JSR 250 security annotations.
|
* Sources method security metadata from major JSR 250 security annotations.
|
||||||
@ -108,7 +109,7 @@ public class Jsr250MethodSecurityMetadataSource extends AbstractFallbackMethodSe
|
|||||||
if (role == null) {
|
if (role == null) {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
if (this.defaultRolePrefix == null || this.defaultRolePrefix.length() == 0) {
|
if (!StringUtils.hasLength(this.defaultRolePrefix)) {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
if (role.startsWith(this.defaultRolePrefix)) {
|
if (role.startsWith(this.defaultRolePrefix)) {
|
||||||
|
|||||||
@ -53,7 +53,9 @@ import org.springframework.util.CollectionUtils;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @deprecated Use {@link EnableMethodSecurity} or publish interceptors directly
|
* @deprecated Use
|
||||||
|
* <code>org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity</code>
|
||||||
|
* or publish interceptors directly
|
||||||
*/
|
*/
|
||||||
@NullUnmarked
|
@NullUnmarked
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
plugins {
|
||||||
|
id 'compile-warnings-error'
|
||||||
|
id 'javadoc-warnings-error'
|
||||||
|
id 'security-nullability'
|
||||||
|
}
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@ -23,6 +23,7 @@ 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;
|
||||||
@ -44,7 +45,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
|
||||||
* {@link org.springframework.security.acls.AclEntryVoter AclEntryVoter}.
|
* <code> org.springframework.security.acls.AclEntryVoter AclEntryVoter </code>
|
||||||
*
|
*
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
@ -73,7 +74,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, Object domainObject, Object permission) {
|
public boolean hasPermission(Authentication authentication, @Nullable Object domainObject, Object permission) {
|
||||||
if (domainObject == null) {
|
if (domainObject == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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,6 +18,8 @@ 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;
|
||||||
@ -36,7 +38,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
|
|||||||
|
|
||||||
private Permission permission;
|
private Permission permission;
|
||||||
|
|
||||||
private final Serializable id;
|
private final @Nullable Serializable id;
|
||||||
|
|
||||||
private final Sid sid;
|
private final Sid sid;
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
|
|||||||
|
|
||||||
private final boolean granting;
|
private final boolean granting;
|
||||||
|
|
||||||
public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
|
public AccessControlEntryImpl(@Nullable 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");
|
||||||
@ -133,7 +135,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializable getId() {
|
public @Nullable Serializable getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -99,7 +99,8 @@ 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);
|
||||||
if (currentUser.equals(acl.getOwner())
|
Sid owner = acl.getOwner();
|
||||||
|
if (owner != null && currentUser.equals(owner)
|
||||||
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,8 +109,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 (acl.getOwner() instanceof GrantedAuthoritySid
|
if (owner instanceof GrantedAuthoritySid
|
||||||
&& authorities.contains(((GrantedAuthoritySid) acl.getOwner()).getGrantedAuthority())) {
|
&& authorities.contains(((GrantedAuthoritySid) owner).getGrantedAuthority())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,8 @@ 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;
|
||||||
@ -41,7 +43,7 @@ import org.springframework.util.ObjectUtils;
|
|||||||
*/
|
*/
|
||||||
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
||||||
|
|
||||||
private Acl parentAcl;
|
private @Nullable Acl parentAcl;
|
||||||
|
|
||||||
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
|
||||||
|
|
||||||
@ -54,10 +56,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
private Serializable id;
|
private Serializable id;
|
||||||
|
|
||||||
// OwnershipAcl
|
// OwnershipAcl
|
||||||
private Sid owner;
|
private @Nullable 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 List<Sid> loadedSids = null;
|
private @Nullable List<Sid> loadedSids = null;
|
||||||
|
|
||||||
private boolean entriesInheriting = true;
|
private boolean entriesInheriting = true;
|
||||||
|
|
||||||
@ -97,8 +99,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, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting,
|
PermissionGrantingStrategy grantingStrategy, @Nullable Acl parentAcl, @Nullable List<Sid> loadedSids,
|
||||||
Sid owner) {
|
boolean entriesInheriting, 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");
|
||||||
@ -117,7 +119,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")
|
@SuppressWarnings({ "unused", "NullAway.Init" })
|
||||||
private AclImpl() {
|
private AclImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +201,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSidLoaded(List<Sid> sids) {
|
public boolean isSidLoaded(@Nullable 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()) {
|
||||||
@ -238,19 +240,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Sid getOwner() {
|
public @Nullable Sid getOwner() {
|
||||||
return this.owner;
|
return this.owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParent(Acl newParent) {
|
public void setParent(@Nullable 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 Acl getParentAcl() {
|
public @Nullable Acl getParentAcl() {
|
||||||
return this.parentAcl;
|
return this.parentAcl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@ 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;
|
||||||
@ -78,13 +80,13 @@ public class SpringCacheBasedAclCache implements AclCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
|
public @Nullable 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 MutableAcl getFromCache(Serializable pk) {
|
public @Nullable 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);
|
||||||
}
|
}
|
||||||
@ -101,12 +103,16 @@ public class SpringCacheBasedAclCache implements AclCache {
|
|||||||
this.cache.put(acl.getId(), acl);
|
this.cache.put(acl.getId(), acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableAcl getFromCache(Object key) {
|
private @Nullable 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;
|
||||||
}
|
}
|
||||||
return initializeTransientFields((MutableAcl) element.get());
|
Object value = element.get();
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return initializeTransientFields((MutableAcl) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableAcl initializeTransientFields(MutableAcl value) {
|
private MutableAcl initializeTransientFields(MutableAcl value) {
|
||||||
|
|||||||
@ -17,4 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* 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,6 +23,7 @@ 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;
|
||||||
@ -67,10 +68,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
|
||||||
*/
|
*/
|
||||||
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
@Nullable Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
|
||||||
if (isString(identifier) && hasValidClassIdType(resultSet)
|
Class<? extends Serializable> classIdType = classIdTypeFrom(resultSet);
|
||||||
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) {
|
if (isString(identifier) && classIdType != null && canConvertFromStringTo(classIdType)) {
|
||||||
return convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
|
return convertFromStringTo((String) identifier, classIdType);
|
||||||
}
|
}
|
||||||
// Assume it should be a Long type
|
// Assume it should be a Long type
|
||||||
return convertToLong(identifier);
|
return convertToLong(identifier);
|
||||||
@ -86,28 +87,38 @@ class AclClassIdUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
private @Nullable Class<? extends Serializable> classIdTypeFrom(ResultSet resultSet) throws SQLException {
|
||||||
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
|
try {
|
||||||
|
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 <T extends Serializable> Class<T> classIdTypeFrom(String className) {
|
private @Nullable Class<? extends Serializable> classIdTypeFrom(String className) {
|
||||||
if (className == null) {
|
if (className == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return (Class) Class.forName(className);
|
return Class.forName(className).asSubclass(Serializable.class);
|
||||||
}
|
}
|
||||||
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> T convertFromStringTo(String identifier, Class<T> targetType) {
|
private <T extends Serializable> @Nullable T convertFromStringTo(String identifier, Class<T> targetType) {
|
||||||
return this.conversionService.convert(identifier, targetType);
|
return this.conversionService.convert(identifier, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +132,7 @@ class AclClassIdUtils {
|
|||||||
* exception occurred
|
* exception occurred
|
||||||
* @throws IllegalArgumentException if targetType is null
|
* @throws IllegalArgumentException if targetType is null
|
||||||
*/
|
*/
|
||||||
private Long convertToLong(Serializable identifier) {
|
private @Nullable 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);
|
||||||
}
|
}
|
||||||
@ -140,10 +151,10 @@ class AclClassIdUtils {
|
|||||||
private static class StringToLongConverter implements Converter<String, Long> {
|
private static class StringToLongConverter implements Converter<String, Long> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long convert(String identifierAsString) {
|
public Long convert(@Nullable 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), null, null);
|
TypeDescriptor.valueOf(Long.class), identifierAsString, new NullPointerException());
|
||||||
|
|
||||||
}
|
}
|
||||||
return Long.parseLong(identifierAsString);
|
return Long.parseLong(identifierAsString);
|
||||||
@ -154,10 +165,10 @@ class AclClassIdUtils {
|
|||||||
private static class StringToUUIDConverter implements Converter<String, UUID> {
|
private static class StringToUUIDConverter implements Converter<String, UUID> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID convert(String identifierAsString) {
|
public UUID convert(@Nullable 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), null, null);
|
TypeDescriptor.valueOf(UUID.class), identifierAsString, new NullPointerException());
|
||||||
|
|
||||||
}
|
}
|
||||||
return UUID.fromString(identifierAsString);
|
return UUID.fromString(identifierAsString);
|
||||||
|
|||||||
@ -31,6 +31,8 @@ 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;
|
||||||
@ -224,7 +226,8 @@ 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, final List<Sid> sids) {
|
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow,
|
||||||
|
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());
|
||||||
@ -264,7 +267,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, List<Sid> sids) {
|
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable 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>
|
||||||
@ -323,7 +326,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,
|
||||||
List<Sid> sids) {
|
@Nullable 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
|
||||||
@ -399,8 +402,10 @@ 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(), inputAcl.getOwner());
|
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), owner);
|
||||||
|
|
||||||
// Copy the "aces" from the input to the destination
|
// Copy the "aces" from the input to the destination
|
||||||
|
|
||||||
@ -506,9 +511,9 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
|
|
||||||
private final Map<Serializable, Acl> acls;
|
private final Map<Serializable, Acl> acls;
|
||||||
|
|
||||||
private final List<Sid> sids;
|
private final @Nullable List<Sid> sids;
|
||||||
|
|
||||||
ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
|
ProcessResultSet(Map<Serializable, Acl> acls, @Nullable 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
|
||||||
@ -579,6 +584,9 @@ 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"));
|
||||||
|
|
||||||
@ -670,7 +678,7 @@ public class BasicLookupStrategy implements LookupStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSidLoaded(List<Sid> sids) {
|
public boolean isSidLoaded(@Nullable List<Sid> sids) {
|
||||||
throw new UnsupportedOperationException("Stub only");
|
throw new UnsupportedOperationException("Stub only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ 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;
|
||||||
@ -98,7 +99,7 @@ public class JdbcAclService implements AclService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
|
public @Nullable 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);
|
||||||
@ -109,11 +110,14 @@ 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, List<Sid> sids) throws NotFoundException {
|
public Acl readAclById(ObjectIdentity object, @Nullable 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);
|
||||||
@ -131,7 +135,7 @@ public class JdbcAclService implements AclService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
|
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable 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
|
||||||
|
|||||||
@ -22,6 +22,8 @@ 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;
|
||||||
@ -120,6 +122,7 @@ 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
|
||||||
@ -155,9 +158,12 @@ 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);
|
||||||
stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true));
|
Long sidPrimaryKey = 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());
|
||||||
@ -189,11 +195,14 @@ 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 Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
protected @Nullable Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
|
||||||
List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
|
List<@Nullable Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
|
||||||
|
|
||||||
if (!classIds.isEmpty()) {
|
if (!classIds.isEmpty()) {
|
||||||
return classIds.get(0);
|
Long result = classIds.get(0);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowCreate) {
|
if (allowCreate) {
|
||||||
@ -204,7 +213,9 @@ 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");
|
||||||
return this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
|
Long result = this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
|
||||||
|
Assert.state(result != null, "Failed to retrieve class primary key");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -219,7 +230,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 Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
protected @Nullable 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();
|
||||||
@ -240,16 +251,22 @@ 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 Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
|
protected @Nullable Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal,
|
||||||
List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class, sidIsPrincipal,
|
boolean allowCreate) {
|
||||||
sidName);
|
List<@Nullable Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class,
|
||||||
|
sidIsPrincipal, sidName);
|
||||||
if (!sidIds.isEmpty()) {
|
if (!sidIds.isEmpty()) {
|
||||||
return sidIds.get(0);
|
Long result = 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");
|
||||||
return this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
|
Long result = this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
|
||||||
|
Assert.state(result != null, "Failed to retrieve sid primary key");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -279,6 +296,9 @@ 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);
|
||||||
@ -319,10 +339,11 @@ 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 Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
protected @Nullable Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
|
||||||
try {
|
try {
|
||||||
return this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, oid.getType(),
|
Long result = this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class,
|
||||||
oid.getIdentifier().toString());
|
oid.getType(), oid.getIdentifier().toString());
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
catch (DataAccessException notFound) {
|
catch (DataAccessException notFound) {
|
||||||
return null;
|
return null;
|
||||||
@ -340,7 +361,11 @@ 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
|
||||||
deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()));
|
Long oidPrimaryKey = 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);
|
||||||
|
|||||||
@ -19,6 +19,8 @@ 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;
|
||||||
@ -42,6 +44,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, List<Sid> sids);
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,4 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* 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,6 +18,8 @@ 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}.
|
||||||
*
|
*
|
||||||
@ -36,7 +38,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
|
||||||
*/
|
*/
|
||||||
Serializable getId();
|
@Nullable Serializable getId();
|
||||||
|
|
||||||
Permission getPermission();
|
Permission getPermission();
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,8 @@ 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.
|
||||||
*
|
*
|
||||||
@ -82,7 +84,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)
|
||||||
*/
|
*/
|
||||||
Sid getOwner();
|
@Nullable 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
|
||||||
@ -103,7 +105,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)
|
||||||
*/
|
*/
|
||||||
Acl getParentAcl();
|
@Nullable 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
|
||||||
@ -189,6 +191,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(List<Sid> sids);
|
boolean isSidLoaded(@Nullable List<Sid> sids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,8 @@ 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,9 +33,9 @@ public interface AclCache {
|
|||||||
|
|
||||||
void evictFromCache(ObjectIdentity objectIdentity);
|
void evictFromCache(ObjectIdentity objectIdentity);
|
||||||
|
|
||||||
MutableAcl getFromCache(ObjectIdentity objectIdentity);
|
@Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity);
|
||||||
|
|
||||||
MutableAcl getFromCache(Serializable pk);
|
@Nullable MutableAcl getFromCache(Serializable pk);
|
||||||
|
|
||||||
void putInCache(MutableAcl acl);
|
void putInCache(MutableAcl acl);
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,8 @@ 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.
|
||||||
*
|
*
|
||||||
@ -32,7 +34,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)
|
||||||
*/
|
*/
|
||||||
List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
|
@Nullable 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.
|
||||||
@ -59,7 +61,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, List<Sid> sids) throws NotFoundException;
|
Acl readAclById(ObjectIdentity object, @Nullable 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.
|
||||||
@ -98,6 +100,7 @@ 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, List<Sid> sids) throws NotFoundException;
|
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids)
|
||||||
|
throws NotFoundException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,4 +18,7 @@
|
|||||||
* 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,4 +24,7 @@
|
|||||||
* 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;
|
||||||
|
|||||||
2
acl/src/main/resources/META-INF/spring/aot.factories
Normal file
2
acl/src/main/resources/META-INF/spring/aot.factories
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
org.springframework.aot.hint.RuntimeHintsRegistrar=\
|
||||||
|
org.springframework.security.acls.aot.hint.AclRuntimeHints
|
||||||
@ -478,6 +478,7 @@ 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,6 +29,7 @@ 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;
|
||||||
|
|
||||||
@ -46,7 +47,6 @@ 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,7 +109,8 @@ 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(), any(RowMapper.class), eq(args))).willReturn(result);
|
given(this.jdbcOperations.query(anyString(), ArgumentMatchers.<RowMapper<ObjectIdentity>>any(), eq(args)))
|
||||||
|
.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,11 +80,10 @@ 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"),
|
||||||
@ -116,11 +115,10 @@ 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,13 +1,16 @@
|
|||||||
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: 'compile-warnings-error'
|
||||||
|
|
||||||
compileAspectj {
|
compileAspectj {
|
||||||
sourceCompatibility = "17"
|
sourceCompatibility = "17"
|
||||||
targetCompatibility = "17"
|
targetCompatibility = "17"
|
||||||
|
ajcOptions.compilerArgs += ['-Xlint:ignore']
|
||||||
}
|
}
|
||||||
compileTestAspectj {
|
compileTestAspectj {
|
||||||
sourceCompatibility = "17"
|
sourceCompatibility = "17"
|
||||||
targetCompatibility = "17"
|
targetCompatibility = "17"
|
||||||
|
ajcOptions.compilerArgs += ['-Xlint:ignore']
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
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 {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
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 {
|
||||||
|
|||||||
11
buildSrc/src/main/groovy/compile-warnings-error.gradle
Normal file
11
buildSrc/src/main/groovy/compile-warnings-error.gradle
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
@ -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.9'
|
toolVersion = '0.8.14'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ def toolchainVersion() {
|
|||||||
if (project.hasProperty('testToolchain')) {
|
if (project.hasProperty('testToolchain')) {
|
||||||
return project.property('testToolchain').toString().toInteger()
|
return project.property('testToolchain').toString().toInteger()
|
||||||
}
|
}
|
||||||
return 17
|
return 25
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
|||||||
7
buildSrc/src/main/groovy/javadoc-warnings-error.gradle
Normal file
7
buildSrc/src/main/groovy/javadoc-warnings-error.gradle
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
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')
|
||||||
|
}
|
||||||
30
buildSrc/src/main/groovy/test-compile-target-jdk25.gradle
Normal file
30
buildSrc/src/main/groovy/test-compile-target-jdk25.gradle
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'security-nullability'
|
id 'security-nullability'
|
||||||
|
id 'javadoc-warnings-error'
|
||||||
|
id 'compile-warnings-error'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|||||||
@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.apereo.cas.client.validation.Assertion;
|
import org.apereo.cas.client.validation.Assertion;
|
||||||
import org.apereo.cas.client.validation.TicketValidationException;
|
import org.apereo.cas.client.validation.TicketValidationException;
|
||||||
import org.apereo.cas.client.validation.TicketValidator;
|
import org.apereo.cas.client.validation.TicketValidator;
|
||||||
import org.jspecify.annotations.NullUnmarked;
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
@ -166,7 +165,6 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
* @param authentication
|
* @param authentication
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@NullUnmarked
|
|
||||||
private @Nullable String getServiceUrl(Authentication authentication) {
|
private @Nullable String getServiceUrl(Authentication authentication) {
|
||||||
String serviceUrl;
|
String serviceUrl;
|
||||||
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
||||||
|
|||||||
@ -17,4 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* Jackson 3+ serialization support for CAS.
|
* Jackson 3+ serialization support for CAS.
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
package org.springframework.security.cas.jackson;
|
package org.springframework.security.cas.jackson;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@ -91,7 +91,8 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
|
|||||||
*/
|
*/
|
||||||
protected String createServiceUrl(HttpServletRequest request, HttpServletResponse response) {
|
protected String createServiceUrl(HttpServletRequest request, HttpServletResponse response) {
|
||||||
return WebUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null,
|
return WebUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null,
|
||||||
this.serviceProperties.getArtifactParameter(), this.encodeServiceUrlWithSessionId);
|
this.serviceProperties.getServiceParameter(), this.serviceProperties.getArtifactParameter(),
|
||||||
|
this.encodeServiceUrlWithSessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import org.springframework.util.Assert;
|
|||||||
* and using the current URL minus the artifact and the corresponding value.
|
* and using the current URL minus the artifact and the corresponding value.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author Ngoc Nhan
|
||||||
*/
|
*/
|
||||||
final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
||||||
implements ServiceAuthenticationDetails {
|
implements ServiceAuthenticationDetails {
|
||||||
@ -74,10 +75,9 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails)) {
|
if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails that)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ServiceAuthenticationDetails that = (ServiceAuthenticationDetails) obj;
|
|
||||||
return this.serviceUrl.equals(that.getServiceUrl());
|
return this.serviceUrl.equals(that.getServiceUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,11 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
/**
|
/**
|
||||||
* If present, removes the artifactParameterName and the corresponding value from the
|
* If present, removes the artifactParameterName and the corresponding value from the
|
||||||
* query String.
|
* query String.
|
||||||
* @param request
|
* @param request the current {@link HttpServletRequest} to obtain the
|
||||||
|
* {@link #getServiceUrl()} from.
|
||||||
|
* @param artifactPattern the {@link Pattern} that will be used to clean up the query
|
||||||
|
* string from containing the artifact name and value. This can be created using
|
||||||
|
* {@link #createArtifactPattern(String)}.
|
||||||
* @return the query String minus the artifactParameterName and the corresponding
|
* @return the query String minus the artifactParameterName and the corresponding
|
||||||
* value.
|
* value.
|
||||||
*/
|
*/
|
||||||
@ -111,7 +115,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String result = artifactPattern.matcher(query).replaceFirst("");
|
String result = artifactPattern.matcher(query).replaceFirst("");
|
||||||
if (result.length() == 0) {
|
if (result.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// strip off the trailing & only if the artifact was the first query param
|
// strip off the trailing & only if the artifact was the first query param
|
||||||
@ -122,8 +126,9 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
* Creates a {@link Pattern} that can be passed into the constructor. This allows the
|
* Creates a {@link Pattern} that can be passed into the constructor. This allows the
|
||||||
* {@link Pattern} to be reused for every instance of
|
* {@link Pattern} to be reused for every instance of
|
||||||
* {@link DefaultServiceAuthenticationDetails}.
|
* {@link DefaultServiceAuthenticationDetails}.
|
||||||
* @param artifactParameterName
|
* @param artifactParameterName the artifactParameterName that is removed from the
|
||||||
* @return
|
* current URL. The result becomes the service url. Cannot be null or an empty String.
|
||||||
|
* @return a {@link Pattern}
|
||||||
*/
|
*/
|
||||||
static Pattern createArtifactPattern(String artifactParameterName) {
|
static Pattern createArtifactPattern(String artifactParameterName) {
|
||||||
Assert.hasLength(artifactParameterName, "artifactParameterName is expected to have a length");
|
Assert.hasLength(artifactParameterName, "artifactParameterName is expected to have a length");
|
||||||
|
|||||||
@ -4,6 +4,9 @@ import trang.RncToXsd
|
|||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
apply plugin: 'trang'
|
apply plugin: 'trang'
|
||||||
apply plugin: 'security-kotlin'
|
apply plugin: 'security-kotlin'
|
||||||
|
apply plugin: 'test-compile-target-jdk25'
|
||||||
|
apply plugin: 'compile-warnings-error'
|
||||||
|
apply plugin: 'javadoc-warnings-error'
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
opensaml5 {
|
opensaml5 {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
@ -98,12 +99,14 @@ public class LdapBindAuthenticationManagerFactoryITests {
|
|||||||
public void authenticationManagerFactoryWhenCustomUserDetailsContextMapperThenUsed() throws Exception {
|
public void authenticationManagerFactoryWhenCustomUserDetailsContextMapperThenUsed() throws Exception {
|
||||||
CustomUserDetailsContextMapperConfig.CONTEXT_MAPPER = new UserDetailsContextMapper() {
|
CustomUserDetailsContextMapperConfig.CONTEXT_MAPPER = new UserDetailsContextMapper() {
|
||||||
@Override
|
@Override
|
||||||
|
@NullMarked
|
||||||
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
|
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
|
||||||
Collection<? extends GrantedAuthority> authorities) {
|
Collection<? extends GrantedAuthority> authorities) {
|
||||||
return User.withUsername("other").password("password").roles("USER").build();
|
return User.withUsername("other").password("password").roles("USER").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NullMarked
|
||||||
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
|
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -94,7 +94,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
public BeanDefinition parse(Element element, ParserContext pc) {
|
public BeanDefinition parse(Element element, ParserContext pc) {
|
||||||
if (!namespaceMatchesVersion(element)) {
|
if (!namespaceMatchesVersion(element)) {
|
||||||
pc.getReaderContext()
|
pc.getReaderContext()
|
||||||
.fatal("You cannot use any XSD older than spring-security-7.0.xsd. Either change to spring-security.xsd or spring-security-7.0.xsd",
|
.fatal("You cannot use any XSD older than spring-security-7.1.xsd. Either change to spring-security.xsd or spring-security-7.1.xsd",
|
||||||
element);
|
element);
|
||||||
}
|
}
|
||||||
String name = pc.getDelegate().getLocalName(element);
|
String name = pc.getDelegate().getLocalName(element);
|
||||||
@ -219,7 +219,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
|
|
||||||
private boolean matchesVersionInternal(Element element) {
|
private boolean matchesVersionInternal(Element element) {
|
||||||
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
|
||||||
return schemaLocation.matches("(?m).*spring-security-7\\.0.*.xsd.*")
|
return schemaLocation.matches("(?m).*spring-security-7\\.1.*.xsd.*")
|
||||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
|
import org.springframework.lang.Contract;
|
||||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||||
@ -302,6 +303,7 @@ public class AuthenticationConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Contract("!null -> !null; null -> null")
|
||||||
public String encode(CharSequence rawPassword) {
|
public String encode(CharSequence rawPassword) {
|
||||||
return getPasswordEncoder().encode(rawPassword);
|
return getPasswordEncoder().encode(rawPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1881,7 +1881,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatchers(Customizer)} will not override previous
|
* Invoking {@link #securityMatchers(Customizer)} will not override previous
|
||||||
* invocations of {@link #securityMatchers()}}, {@link #securityMatchers(Customizer)}
|
* invocations of {@link #securityMatchers(Customizer)}
|
||||||
* {@link #securityMatcher(String...)} and {@link #securityMatcher(RequestMatcher)}
|
* {@link #securityMatcher(String...)} and {@link #securityMatcher(RequestMatcher)}
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
@ -2004,8 +2004,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatcher(RequestMatcher)} will override previous
|
* Invoking {@link #securityMatcher(RequestMatcher)} will override previous
|
||||||
* invocations of {@link #securityMatcher(RequestMatcher)},
|
* invocations of {@link #securityMatcher(RequestMatcher)},
|
||||||
* {@link #securityMatcher(String...)}, {@link #securityMatchers(Customizer)} and
|
* {@link #securityMatcher(String...)} and {@link #securityMatchers(Customizer)}
|
||||||
* {@link #securityMatchers()}
|
|
||||||
* </p>
|
* </p>
|
||||||
* @param requestMatcher the {@link RequestMatcher} to use, for example,
|
* @param requestMatcher the {@link RequestMatcher} to use, for example,
|
||||||
* {@code PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/admin/**")}
|
* {@code PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/admin/**")}
|
||||||
@ -2024,9 +2023,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
||||||
* {@link #securityMatcher(String...)} (String)}},
|
* {@link #securityMatcher(String...)}, {@link #securityMatcher(RequestMatcher)} and
|
||||||
* {@link #securityMatcher(RequestMatcher)} ()}, {@link #securityMatchers(Customizer)}
|
* {@link #securityMatchers(Customizer)}.
|
||||||
* (String)} and {@link #securityMatchers()} (String)}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* @param patterns the pattern to match on (i.e. "/admin/**")
|
* @param patterns the pattern to match on (i.e. "/admin/**")
|
||||||
* @return the {@link HttpSecurity} for further customizations
|
* @return the {@link HttpSecurity} for further customizations
|
||||||
|
|||||||
@ -226,7 +226,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Typically this method is invoked automatically within the framework from
|
* Typically this method is invoked automatically within the framework from
|
||||||
* {@link WebSecurityConfiguration#springSecurityFilterChain()}
|
* {@link WebSecurityConfiguration#springSecurityFilterChain(ObjectProvider)}
|
||||||
* </p>
|
* </p>
|
||||||
* @param securityFilterChainBuilder the builder to use to create the
|
* @param securityFilterChainBuilder the builder to use to create the
|
||||||
* {@link SecurityFilterChain} instances
|
* {@link SecurityFilterChain} instances
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import org.springframework.context.annotation.Scope;
|
|||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
|
import org.springframework.lang.Contract;
|
||||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||||
@ -293,6 +294,7 @@ class HttpSecurityConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Contract("!null -> !null; null -> null")
|
||||||
public String encode(CharSequence rawPassword) {
|
public String encode(CharSequence rawPassword) {
|
||||||
return getPasswordEncoder().encode(rawPassword);
|
return getPasswordEncoder().encode(rawPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
|
|||||||
* other than applying this {@link SecurityConfigurer}.
|
* other than applying this {@link SecurityConfigurer}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
* @author DingHao
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
@ -158,7 +159,7 @@ public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
this.authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
this.authenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
||||||
this.authenticationFilter.afterPropertiesSet();
|
this.authenticationFilter.afterPropertiesSet();
|
||||||
http.addFilter(this.authenticationFilter);
|
http.addFilter(postProcess(this.authenticationFilter));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey() {
|
private String getKey() {
|
||||||
|
|||||||
@ -47,8 +47,8 @@ import org.springframework.util.Assert;
|
|||||||
* The following configuration options are available:
|
* The following configuration options are available:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #authorizationCodeGrant()} - support for the OAuth 2.0 Authorization Code
|
* <li>{@link #authorizationCodeGrant(Customizer)} - support for the OAuth 2.0
|
||||||
* Grant</li>
|
* Authorization Code Grant</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
@ -59,7 +59,8 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* <h2>Security Filters</h2>
|
* <h2>Security Filters</h2>
|
||||||
*
|
*
|
||||||
* The following {@code Filter}'s are populated for {@link #authorizationCodeGrant()}:
|
* The following {@code Filter}'s are populated for
|
||||||
|
* {@link #authorizationCodeGrant(Customizer)}:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link OAuth2AuthorizationRequestRedirectFilter}</li>
|
* <li>{@link OAuth2AuthorizationRequestRedirectFilter}</li>
|
||||||
|
|||||||
@ -521,8 +521,10 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||||||
public OpaqueTokenConfigurer introspectionUri(String introspectionUri) {
|
public OpaqueTokenConfigurer introspectionUri(String introspectionUri) {
|
||||||
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
Assert.notNull(introspectionUri, "introspectionUri cannot be null");
|
||||||
this.introspectionUri = introspectionUri;
|
this.introspectionUri = introspectionUri;
|
||||||
this.introspector = () -> new SpringOpaqueTokenIntrospector(this.introspectionUri, this.clientId,
|
this.introspector = () -> SpringOpaqueTokenIntrospector.withIntrospectionUri(this.introspectionUri)
|
||||||
this.clientSecret);
|
.clientId(this.clientId)
|
||||||
|
.clientSecret(this.clientSecret)
|
||||||
|
.build();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,8 +533,10 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
|
|||||||
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
Assert.notNull(clientSecret, "clientSecret cannot be null");
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
this.clientSecret = clientSecret;
|
this.clientSecret = clientSecret;
|
||||||
this.introspector = () -> new SpringOpaqueTokenIntrospector(this.introspectionUri, this.clientId,
|
this.introspector = () -> SpringOpaqueTokenIntrospector.withIntrospectionUri(this.introspectionUri)
|
||||||
this.clientSecret);
|
.clientId(this.clientId)
|
||||||
|
.clientSecret(this.clientSecret)
|
||||||
|
.build();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import java.util.function.Function;
|
|||||||
import org.opensaml.core.Version;
|
import org.opensaml.core.Version;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
@ -42,7 +43,8 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Defaults are provided for all configuration options with the only required
|
* Defaults are provided for all configuration options with the only required
|
||||||
* configuration being a {@link Saml2LoginConfigurer#relyingPartyRegistrationRepository}.
|
* configuration being a
|
||||||
|
* {@link Saml2LoginConfigurer#relyingPartyRegistrationRepository(HttpSecurityBuilder)}.
|
||||||
* Alternatively, a {@link RelyingPartyRegistrationRepository} {@code @Bean} may be
|
* Alternatively, a {@link RelyingPartyRegistrationRepository} {@code @Bean} may be
|
||||||
* registered instead.
|
* registered instead.
|
||||||
*
|
*
|
||||||
@ -67,7 +69,7 @@ import org.springframework.util.Assert;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
* @see HttpSecurity#saml2Metadata()
|
* @see HttpSecurity#saml2Metadata(Customizer)
|
||||||
* @see Saml2MetadataFilter
|
* @see Saml2MetadataFilter
|
||||||
* @see RelyingPartyRegistrationRepository
|
* @see RelyingPartyRegistrationRepository
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -124,6 +124,10 @@ class AuthorizationFilterParser implements BeanDefinitionParser {
|
|||||||
List<Element> interceptMessages = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
List<Element> interceptMessages = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
||||||
for (Element interceptMessage : interceptMessages) {
|
for (Element interceptMessage : interceptMessages) {
|
||||||
String accessExpression = interceptMessage.getAttribute(ATT_ACCESS);
|
String accessExpression = interceptMessage.getAttribute(ATT_ACCESS);
|
||||||
|
if (!StringUtils.hasText(accessExpression)) {
|
||||||
|
parserContext.getReaderContext().error("access attribute cannot be empty or null", interceptMessage);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
BeanDefinitionBuilder authorizationManager = BeanDefinitionBuilder
|
BeanDefinitionBuilder authorizationManager = BeanDefinitionBuilder
|
||||||
.rootBeanDefinition(WebExpressionAuthorizationManager.class);
|
.rootBeanDefinition(WebExpressionAuthorizationManager.class);
|
||||||
authorizationManager.addPropertyReference("expressionHandler", expressionHandlerRef);
|
authorizationManager.addPropertyReference("expressionHandler", expressionHandlerRef);
|
||||||
|
|||||||
@ -142,10 +142,11 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||||||
ManagedMap<BeanMetadataElement, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<>();
|
ManagedMap<BeanMetadataElement, BeanDefinition> filterInvocationDefinitionMap = new ManagedMap<>();
|
||||||
for (Element urlElt : urlElts) {
|
for (Element urlElt : urlElts) {
|
||||||
String access = urlElt.getAttribute(ATT_ACCESS);
|
String access = urlElt.getAttribute(ATT_ACCESS);
|
||||||
|
String path = urlElt.getAttribute(ATT_PATTERN);
|
||||||
if (!StringUtils.hasText(access)) {
|
if (!StringUtils.hasText(access)) {
|
||||||
|
parserContext.getReaderContext().error("access attribute cannot be empty or null", urlElt);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String path = urlElt.getAttribute(ATT_PATTERN);
|
|
||||||
String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF);
|
String matcherRef = urlElt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUEST_MATCHER_REF);
|
||||||
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
|
boolean hasMatcherRef = StringUtils.hasText(matcherRef);
|
||||||
if (!hasMatcherRef && !StringUtils.hasText(path)) {
|
if (!hasMatcherRef && !StringUtils.hasText(path)) {
|
||||||
|
|||||||
@ -2162,7 +2162,7 @@ public class ServerHttpSecurity {
|
|||||||
*
|
*
|
||||||
* @author Evgeniy Cheban
|
* @author Evgeniy Cheban
|
||||||
* @since 5.6
|
* @since 5.6
|
||||||
* @see #passwordManagement()
|
* @see #passwordManagement(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class PasswordManagementSpec {
|
public final class PasswordManagementSpec {
|
||||||
|
|
||||||
@ -2663,7 +2663,7 @@ public class ServerHttpSecurity {
|
|||||||
/**
|
/**
|
||||||
* Configures cache control headers
|
* Configures cache control headers
|
||||||
*
|
*
|
||||||
* @see #cache()
|
* @see HeaderSpec#cache(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class CacheSpec {
|
public final class CacheSpec {
|
||||||
|
|
||||||
@ -2684,7 +2684,7 @@ public class ServerHttpSecurity {
|
|||||||
/**
|
/**
|
||||||
* The content type headers
|
* The content type headers
|
||||||
*
|
*
|
||||||
* @see #contentTypeOptions()
|
* @see HeaderSpec#contentTypeOptions(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class ContentTypeOptionsSpec {
|
public final class ContentTypeOptionsSpec {
|
||||||
|
|
||||||
@ -2705,7 +2705,7 @@ public class ServerHttpSecurity {
|
|||||||
/**
|
/**
|
||||||
* Configures frame options response header
|
* Configures frame options response header
|
||||||
*
|
*
|
||||||
* @see #frameOptions()
|
* @see HeaderSpec#frameOptions(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class FrameOptionsSpec {
|
public final class FrameOptionsSpec {
|
||||||
|
|
||||||
@ -2737,7 +2737,7 @@ public class ServerHttpSecurity {
|
|||||||
/**
|
/**
|
||||||
* Configures Strict Transport Security response header
|
* Configures Strict Transport Security response header
|
||||||
*
|
*
|
||||||
* @see #hsts()
|
* @see HeaderSpec#hsts(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class HstsSpec {
|
public final class HstsSpec {
|
||||||
|
|
||||||
@ -2796,7 +2796,7 @@ public class ServerHttpSecurity {
|
|||||||
/**
|
/**
|
||||||
* Configures x-xss-protection response header
|
* Configures x-xss-protection response header
|
||||||
*
|
*
|
||||||
* @see #xssProtection()
|
* @see HeaderSpec#xssProtection(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class XssProtectionSpec {
|
public final class XssProtectionSpec {
|
||||||
|
|
||||||
@ -2830,7 +2830,7 @@ public class ServerHttpSecurity {
|
|||||||
* Configures {@code Content-Security-Policy} response header.
|
* Configures {@code Content-Security-Policy} response header.
|
||||||
*
|
*
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
* @see #contentSecurityPolicy(String)
|
* @see HeaderSpec#contentSecurityPolicy(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class ContentSecurityPolicySpec {
|
public final class ContentSecurityPolicySpec {
|
||||||
|
|
||||||
@ -2884,8 +2884,7 @@ public class ServerHttpSecurity {
|
|||||||
* Allows method chaining to continue configuring the
|
* Allows method chaining to continue configuring the
|
||||||
* {@link ServerHttpSecurity}.
|
* {@link ServerHttpSecurity}.
|
||||||
* @return the {@link HeaderSpec} to continue configuring
|
* @return the {@link HeaderSpec} to continue configuring
|
||||||
* @deprecated For removal in 7.0. Use {@link #featurePolicy(Customizer)}
|
* @deprecated For removal in 7.0. Use {@link #featurePolicy(String)} instead
|
||||||
* instead
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
@Deprecated(since = "6.1", forRemoval = true)
|
||||||
public HeaderSpec and() {
|
public HeaderSpec and() {
|
||||||
@ -2898,7 +2897,7 @@ public class ServerHttpSecurity {
|
|||||||
* Configures {@code Permissions-Policy} response header.
|
* Configures {@code Permissions-Policy} response header.
|
||||||
*
|
*
|
||||||
* @since 5.5
|
* @since 5.5
|
||||||
* @see #permissionsPolicy()
|
* @see HeaderSpec#permissionsPolicy(Customizer)
|
||||||
*/
|
*/
|
||||||
public final class PermissionsPolicySpec {
|
public final class PermissionsPolicySpec {
|
||||||
|
|
||||||
@ -2921,8 +2920,7 @@ public class ServerHttpSecurity {
|
|||||||
* Configures {@code Referrer-Policy} response header.
|
* Configures {@code Referrer-Policy} response header.
|
||||||
*
|
*
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
* @see #referrerPolicy()
|
* @see HeaderSpec#referrerPolicy(Customizer)
|
||||||
* @see #referrerPolicy(ReferrerPolicy)
|
|
||||||
*/
|
*/
|
||||||
public final class ReferrerPolicySpec {
|
public final class ReferrerPolicySpec {
|
||||||
|
|
||||||
|
|||||||
@ -23,9 +23,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@ -44,25 +42,18 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
|||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.beans.factory.xml.XmlReaderContext;
|
import org.springframework.beans.factory.xml.XmlReaderContext;
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
import org.springframework.messaging.simp.SimpMessageType;
|
import org.springframework.messaging.simp.SimpMessageType;
|
||||||
import org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler;
|
import org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler;
|
||||||
import org.springframework.security.access.expression.ExpressionUtils;
|
|
||||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
|
||||||
import org.springframework.security.access.vote.ConsensusBased;
|
import org.springframework.security.access.vote.ConsensusBased;
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
import org.springframework.security.authorization.AuthorizationResult;
|
|
||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
import org.springframework.security.config.http.MessageMatcherFactoryBean;
|
import org.springframework.security.config.http.MessageMatcherFactoryBean;
|
||||||
import org.springframework.security.config.web.messaging.PathPatternMessageMatcherBuilderFactoryBean;
|
import org.springframework.security.config.web.messaging.PathPatternMessageMatcherBuilderFactoryBean;
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory;
|
import org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory;
|
||||||
import org.springframework.security.messaging.access.expression.MessageAuthorizationContextSecurityExpressionHandler;
|
import org.springframework.security.messaging.access.expression.MessageExpressionAuthorizationManager;
|
||||||
import org.springframework.security.messaging.access.expression.MessageExpressionVoter;
|
import org.springframework.security.messaging.access.expression.MessageExpressionVoter;
|
||||||
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
|
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
|
||||||
import org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor;
|
import org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor;
|
||||||
@ -75,7 +66,6 @@ import org.springframework.security.messaging.util.matcher.SimpMessageTypeMatche
|
|||||||
import org.springframework.security.messaging.web.csrf.XorCsrfChannelInterceptor;
|
import org.springframework.security.messaging.web.csrf.XorCsrfChannelInterceptor;
|
||||||
import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor;
|
import org.springframework.security.messaging.web.socket.server.CsrfTokenHandshakeInterceptor;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.PathMatcher;
|
import org.springframework.util.PathMatcher;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
@ -219,9 +209,15 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
|
|||||||
String messageType = interceptMessage.getAttribute(TYPE_ATTR);
|
String messageType = interceptMessage.getAttribute(TYPE_ATTR);
|
||||||
BeanDefinition matcher = createMatcher(matcherPattern, messageType, parserContext, interceptMessage);
|
BeanDefinition matcher = createMatcher(matcherPattern, messageType, parserContext, interceptMessage);
|
||||||
BeanDefinitionBuilder authorizationManager = BeanDefinitionBuilder
|
BeanDefinitionBuilder authorizationManager = BeanDefinitionBuilder
|
||||||
.rootBeanDefinition(ExpressionBasedAuthorizationManager.class);
|
.rootBeanDefinition(MessageExpressionAuthorizationManager.class);
|
||||||
if (StringUtils.hasText(expressionHandlerRef)) {
|
if (StringUtils.hasText(expressionHandlerRef)) {
|
||||||
authorizationManager.addConstructorArgReference(expressionHandlerRef);
|
BeanDefinitionBuilder authorizationManagerBuilder = BeanDefinitionBuilder
|
||||||
|
.rootBeanDefinition(MessageExpressionAuthorizationManager.class);
|
||||||
|
authorizationManagerBuilder.setFactoryMethod("withSecurityExpressionHandler");
|
||||||
|
authorizationManagerBuilder.addConstructorArgReference(expressionHandlerRef);
|
||||||
|
String authorizationManagerBuilderRef = context
|
||||||
|
.registerWithGeneratedName(authorizationManagerBuilder.getBeanDefinition());
|
||||||
|
authorizationManager.setFactoryMethodOnBean("expression", authorizationManagerBuilderRef);
|
||||||
}
|
}
|
||||||
authorizationManager.addConstructorArgValue(accessExpression);
|
authorizationManager.addConstructorArgValue(accessExpression);
|
||||||
matcherToExpression.put(matcher, authorizationManager.getBeanDefinition());
|
matcherToExpression.put(matcher, authorizationManager.getBeanDefinition());
|
||||||
@ -439,35 +435,6 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ExpressionBasedAuthorizationManager
|
|
||||||
implements AuthorizationManager<MessageAuthorizationContext<?>> {
|
|
||||||
|
|
||||||
private final SecurityExpressionHandler<MessageAuthorizationContext<?>> expressionHandler;
|
|
||||||
|
|
||||||
private final Expression expression;
|
|
||||||
|
|
||||||
private ExpressionBasedAuthorizationManager(String expression) {
|
|
||||||
this(new MessageAuthorizationContextSecurityExpressionHandler(), expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExpressionBasedAuthorizationManager(
|
|
||||||
SecurityExpressionHandler<MessageAuthorizationContext<?>> expressionHandler, String expression) {
|
|
||||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
|
||||||
Assert.notNull(expression, "expression cannot be null");
|
|
||||||
this.expressionHandler = expressionHandler;
|
|
||||||
this.expression = this.expressionHandler.getExpressionParser().parseExpression(expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
|
|
||||||
MessageAuthorizationContext<?> object) {
|
|
||||||
EvaluationContext context = this.expressionHandler.createEvaluationContext(authentication, object);
|
|
||||||
boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, context);
|
|
||||||
return new AuthorizationDecision(granted);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MessageMatcherDelegatingAuthorizationManagerFactory {
|
private static class MessageMatcherDelegatingAuthorizationManagerFactory {
|
||||||
|
|
||||||
private static AuthorizationManager<Message<?>> createMessageMatcherDelegatingAuthorizationManager(
|
private static AuthorizationManager<Message<?>> createMessageMatcherDelegatingAuthorizationManager(
|
||||||
|
|||||||
@ -286,7 +286,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||||||
if (factoryOfRequestAuthorizationContext != null) {
|
if (factoryOfRequestAuthorizationContext != null) {
|
||||||
return factoryOfRequestAuthorizationContext
|
return factoryOfRequestAuthorizationContext
|
||||||
}
|
}
|
||||||
val factoryOfObjectType = ResolvableType.forClassWithGenerics(AuthorizationManagerFactory::class.java, Object::class.java)
|
val factoryOfObjectType = ResolvableType.forClassWithGenerics(AuthorizationManagerFactory::class.java, Any::class.java)
|
||||||
val factoryOfAny = context.getBeanProvider<AuthorizationManagerFactory<Any>>(factoryOfObjectType).getIfUnique()
|
val factoryOfAny = context.getBeanProvider<AuthorizationManagerFactory<Any>>(factoryOfObjectType).getIfUnique()
|
||||||
if (factoryOfAny != null) {
|
if (factoryOfAny != null) {
|
||||||
return factoryOfAny
|
return factoryOfAny
|
||||||
@ -303,20 +303,20 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||||||
return defaultFactory
|
return defaultFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveRolePrefix(context: ApplicationContext): String {
|
private fun resolveRolePrefix(context: ApplicationContext): String? {
|
||||||
val beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults::class.java)
|
val beanNames = context.getBeanNamesForType(GrantedAuthorityDefaults::class.java)
|
||||||
if (beanNames.isNotEmpty()) {
|
if (beanNames.isNotEmpty()) {
|
||||||
return context.getBean(GrantedAuthorityDefaults::class.java).rolePrefix
|
return context.getBean(GrantedAuthorityDefaults::class.java).rolePrefix
|
||||||
}
|
}
|
||||||
return "ROLE_";
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveRoleHierarchy(context: ApplicationContext): RoleHierarchy {
|
private fun resolveRoleHierarchy(context: ApplicationContext): RoleHierarchy? {
|
||||||
val beanNames = context.getBeanNamesForType(RoleHierarchy::class.java)
|
val beanNames = context.getBeanNamesForType(RoleHierarchy::class.java)
|
||||||
if (beanNames.isNotEmpty()) {
|
if (beanNames.isNotEmpty()) {
|
||||||
return context.getBean(RoleHierarchy::class.java)
|
return context.getBean(RoleHierarchy::class.java)
|
||||||
}
|
}
|
||||||
return NullRoleHierarchy()
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,9 +37,11 @@ class HeadersDsl {
|
|||||||
private var cacheControl: ((HeadersConfigurer<HttpSecurity>.CacheControlConfig) -> Unit)? = null
|
private var cacheControl: ((HeadersConfigurer<HttpSecurity>.CacheControlConfig) -> Unit)? = null
|
||||||
private var hsts: ((HeadersConfigurer<HttpSecurity>.HstsConfig) -> Unit)? = null
|
private var hsts: ((HeadersConfigurer<HttpSecurity>.HstsConfig) -> Unit)? = null
|
||||||
private var frameOptions: ((HeadersConfigurer<HttpSecurity>.FrameOptionsConfig) -> Unit)? = null
|
private var frameOptions: ((HeadersConfigurer<HttpSecurity>.FrameOptionsConfig) -> Unit)? = null
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private var hpkp: ((HeadersConfigurer<HttpSecurity>.HpkpConfig) -> Unit)? = null
|
private var hpkp: ((HeadersConfigurer<HttpSecurity>.HpkpConfig) -> Unit)? = null
|
||||||
private var contentSecurityPolicy: ((HeadersConfigurer<HttpSecurity>.ContentSecurityPolicyConfig) -> Unit)? = null
|
private var contentSecurityPolicy: ((HeadersConfigurer<HttpSecurity>.ContentSecurityPolicyConfig) -> Unit)? = null
|
||||||
private var referrerPolicy: ((HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit)? = null
|
private var referrerPolicy: ((HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit)? = null
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private var featurePolicyDirectives: String? = null
|
private var featurePolicyDirectives: String? = null
|
||||||
private var permissionsPolicy: ((HeadersConfigurer<HttpSecurity>.PermissionsPolicyConfig) -> Unit)? = null
|
private var permissionsPolicy: ((HeadersConfigurer<HttpSecurity>.PermissionsPolicyConfig) -> Unit)? = null
|
||||||
private var crossOriginOpenerPolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginOpenerPolicyConfig) -> Unit)? = null
|
private var crossOriginOpenerPolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginOpenerPolicyConfig) -> Unit)? = null
|
||||||
@ -120,6 +122,7 @@ class HeadersDsl {
|
|||||||
* @deprecated see <a href="https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning">Certificate and Public Key Pinning</a> for more context
|
* @deprecated see <a href="https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning">Certificate and Public Key Pinning</a> for more context
|
||||||
*/
|
*/
|
||||||
@Deprecated(message = "as of 5.8 with no replacement")
|
@Deprecated(message = "as of 5.8 with no replacement")
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
fun httpPublicKeyPinning(hpkpConfig: HttpPublicKeyPinningDsl.() -> Unit) {
|
fun httpPublicKeyPinning(hpkpConfig: HttpPublicKeyPinningDsl.() -> Unit) {
|
||||||
this.hpkp = HttpPublicKeyPinningDsl().apply(hpkpConfig).get()
|
this.hpkp = HttpPublicKeyPinningDsl().apply(hpkpConfig).get()
|
||||||
}
|
}
|
||||||
@ -167,6 +170,7 @@ class HeadersDsl {
|
|||||||
* @param policyDirectives policyDirectives the security policy directive(s)
|
* @param policyDirectives policyDirectives the security policy directive(s)
|
||||||
*/
|
*/
|
||||||
@Deprecated("Use 'permissionsPolicy { }' instead.")
|
@Deprecated("Use 'permissionsPolicy { }' instead.")
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
fun featurePolicy(policyDirectives: String) {
|
fun featurePolicy(policyDirectives: String) {
|
||||||
this.featurePolicyDirectives = policyDirectives
|
this.featurePolicyDirectives = policyDirectives
|
||||||
}
|
}
|
||||||
|
|||||||
@ -614,6 +614,7 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
|||||||
* @see [RequiresChannelDsl]
|
* @see [RequiresChannelDsl]
|
||||||
* @deprecated please use [redirectToHttps] instead
|
* @deprecated please use [redirectToHttps] instead
|
||||||
*/
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated(message="since 6.5 use redirectToHttps instead")
|
@Deprecated(message="since 6.5 use redirectToHttps instead")
|
||||||
fun requiresChannel(requiresChannelConfiguration: RequiresChannelDsl.() -> Unit) {
|
fun requiresChannel(requiresChannelConfiguration: RequiresChannelDsl.() -> Unit) {
|
||||||
val requiresChannelCustomizer = RequiresChannelDsl().apply(requiresChannelConfiguration).get()
|
val requiresChannelCustomizer = RequiresChannelDsl().apply(requiresChannelConfiguration).get()
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web
|
package org.springframework.security.config.annotation.web
|
||||||
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
|||||||
@ -62,6 +62,7 @@ class X509Dsl {
|
|||||||
authenticationDetailsSource?.also { x509.authenticationDetailsSource(authenticationDetailsSource) }
|
authenticationDetailsSource?.also { x509.authenticationDetailsSource(authenticationDetailsSource) }
|
||||||
userDetailsService?.also { x509.userDetailsService(userDetailsService) }
|
userDetailsService?.also { x509.userDetailsService(userDetailsService) }
|
||||||
authenticationUserDetailsService?.also { x509.authenticationUserDetailsService(authenticationUserDetailsService) }
|
authenticationUserDetailsService?.also { x509.authenticationUserDetailsService(authenticationUserDetailsService) }
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
subjectPrincipalRegex?.also { x509.subjectPrincipalRegex(subjectPrincipalRegex) }
|
subjectPrincipalRegex?.also { x509.subjectPrincipalRegex(subjectPrincipalRegex) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web.headers
|
package org.springframework.security.config.annotation.web.headers
|
||||||
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
|||||||
@ -68,12 +68,11 @@ class SessionFixationDsl {
|
|||||||
internal fun get(): (SessionManagementConfigurer<HttpSecurity>.SessionFixationConfigurer) -> Unit {
|
internal fun get(): (SessionManagementConfigurer<HttpSecurity>.SessionFixationConfigurer) -> Unit {
|
||||||
return { sessionFixation ->
|
return { sessionFixation ->
|
||||||
strategy?.also {
|
strategy?.also {
|
||||||
when (strategy) {
|
when (it) {
|
||||||
SessionFixationStrategy.NEW -> sessionFixation.newSession()
|
SessionFixationStrategy.NEW -> sessionFixation.newSession()
|
||||||
SessionFixationStrategy.MIGRATE -> sessionFixation.migrateSession()
|
SessionFixationStrategy.MIGRATE -> sessionFixation.migrateSession()
|
||||||
SessionFixationStrategy.CHANGE_ID -> sessionFixation.changeSessionId()
|
SessionFixationStrategy.CHANGE_ID -> sessionFixation.changeSessionId()
|
||||||
SessionFixationStrategy.NONE -> sessionFixation.none()
|
SessionFixationStrategy.NONE -> sessionFixation.none()
|
||||||
null -> null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-7.1.xsd
|
||||||
|
http\://www.springframework.org/schema/security/spring-security-7.0.xsd=org/springframework/security/config/spring-security-7.1.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-7.0.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
http\://www.springframework.org/schema/security/spring-security-7.0.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-6.5.xsd=org/springframework/security/config/spring-security-6.5.xsd
|
http\://www.springframework.org/schema/security/spring-security-6.5.xsd=org/springframework/security/config/spring-security-6.5.xsd
|
||||||
@ -42,7 +44,8 @@ http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/spri
|
|||||||
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
|
||||||
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
|
||||||
https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-7.1.xsd
|
||||||
|
https\://www.springframework.org/schema/security/spring-security-7.1.xsd=org/springframework/security/config/spring-security-7.1.xsd
|
||||||
https\://www.springframework.org/schema/security/spring-security-7.0.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
https\://www.springframework.org/schema/security/spring-security-7.0.xsd=org/springframework/security/config/spring-security-7.0.xsd
|
||||||
https\://www.springframework.org/schema/security/spring-security-6.5.xsd=org/springframework/security/config/spring-security-6.5.xsd
|
https\://www.springframework.org/schema/security/spring-security-6.5.xsd=org/springframework/security/config/spring-security-6.5.xsd
|
||||||
https\://www.springframework.org/schema/security/spring-security-6.4.xsd=org/springframework/security/config/spring-security-6.4.xsd
|
https\://www.springframework.org/schema/security/spring-security-6.4.xsd=org/springframework/security/config/spring-security-6.4.xsd
|
||||||
|
|||||||
@ -12,8 +12,8 @@ base64 =
|
|||||||
## Whether a string should be base64 encoded
|
## Whether a string should be base64 encoded
|
||||||
attribute base64 {xsd:boolean}
|
attribute base64 {xsd:boolean}
|
||||||
request-matcher =
|
request-matcher =
|
||||||
## Defines the strategy use for matching incoming requests. Currently the options are 'mvc' (for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular expressions.
|
## Defines the strategy use for matching incoming requests. Currently the options are 'path' (for PathPatternRequestMatcher), 'regex' for regular expressions and 'ciRegex' for case-insensitive regular expressions.
|
||||||
attribute request-matcher {"mvc" | "ant" | "regex" | "ciRegex"}
|
attribute request-matcher {"path" | "regex" | "ciRegex"}
|
||||||
port =
|
port =
|
||||||
## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
|
## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
|
||||||
attribute port { xsd:nonNegativeInteger }
|
attribute port { xsd:nonNegativeInteger }
|
||||||
|
|||||||
@ -27,15 +27,14 @@
|
|||||||
<xs:attributeGroup name="request-matcher">
|
<xs:attributeGroup name="request-matcher">
|
||||||
<xs:attribute name="request-matcher" use="required">
|
<xs:attribute name="request-matcher" use="required">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
|
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'path'
|
||||||
(for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
|
(for PathPatternRequestMatcher), 'regex' for regular expressions and 'ciRegex' for
|
||||||
and 'ciRegex' for case-insensitive regular expressions.
|
case-insensitive regular expressions.
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
<xs:enumeration value="mvc"/>
|
<xs:enumeration value="path"/>
|
||||||
<xs:enumeration value="ant"/>
|
|
||||||
<xs:enumeration value="regex"/>
|
<xs:enumeration value="regex"/>
|
||||||
<xs:enumeration value="ciRegex"/>
|
<xs:enumeration value="ciRegex"/>
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
@ -1306,15 +1305,14 @@
|
|||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
<xs:attribute name="request-matcher">
|
<xs:attribute name="request-matcher">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
|
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'path'
|
||||||
(for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
|
(for PathPatternRequestMatcher), 'regex' for regular expressions and 'ciRegex' for
|
||||||
and 'ciRegex' for case-insensitive regular expressions.
|
case-insensitive regular expressions.
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
<xs:enumeration value="mvc"/>
|
<xs:enumeration value="path"/>
|
||||||
<xs:enumeration value="ant"/>
|
|
||||||
<xs:enumeration value="regex"/>
|
<xs:enumeration value="regex"/>
|
||||||
<xs:enumeration value="ciRegex"/>
|
<xs:enumeration value="ciRegex"/>
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
@ -2474,15 +2472,14 @@
|
|||||||
<xs:attributeGroup name="filter-chain-map.attlist">
|
<xs:attributeGroup name="filter-chain-map.attlist">
|
||||||
<xs:attribute name="request-matcher">
|
<xs:attribute name="request-matcher">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
|
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'path'
|
||||||
(for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
|
(for PathPatternRequestMatcher), 'regex' for regular expressions and 'ciRegex' for
|
||||||
and 'ciRegex' for case-insensitive regular expressions.
|
case-insensitive regular expressions.
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
<xs:enumeration value="mvc"/>
|
<xs:enumeration value="path"/>
|
||||||
<xs:enumeration value="ant"/>
|
|
||||||
<xs:enumeration value="regex"/>
|
<xs:enumeration value="regex"/>
|
||||||
<xs:enumeration value="ciRegex"/>
|
<xs:enumeration value="ciRegex"/>
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
@ -2580,15 +2577,14 @@
|
|||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
<xs:attribute name="request-matcher">
|
<xs:attribute name="request-matcher">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'mvc'
|
<xs:documentation>Defines the strategy use for matching incoming requests. Currently the options are 'path'
|
||||||
(for Spring MVC matcher), 'ant' (for ant path patterns), 'regex' for regular expressions
|
(for PathPatternRequestMatcher), 'regex' for regular expressions and 'ciRegex' for
|
||||||
and 'ciRegex' for case-insensitive regular expressions.
|
case-insensitive regular expressions.
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
<xs:enumeration value="mvc"/>
|
<xs:enumeration value="path"/>
|
||||||
<xs:enumeration value="ant"/>
|
|
||||||
<xs:enumeration value="regex"/>
|
<xs:enumeration value="regex"/>
|
||||||
<xs:enumeration value="ciRegex"/>
|
<xs:enumeration value="ciRegex"/>
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@ import java.io.IOException;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -245,12 +246,15 @@ import org.springframework.security.web.savedrequest.SimpleSavedRequest;
|
|||||||
import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
|
import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
|
||||||
import org.springframework.security.web.session.HttpSessionCreatedEvent;
|
import org.springframework.security.web.session.HttpSessionCreatedEvent;
|
||||||
import org.springframework.security.web.session.HttpSessionIdChangedEvent;
|
import org.springframework.security.web.session.HttpSessionIdChangedEvent;
|
||||||
|
import org.springframework.security.web.webauthn.api.AttestationConveyancePreference;
|
||||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
|
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
|
||||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
|
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
|
||||||
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
|
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
|
||||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
|
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
|
||||||
|
import org.springframework.security.web.webauthn.api.AuthenticatorSelectionCriteria;
|
||||||
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
|
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
|
||||||
import org.springframework.security.web.webauthn.api.Bytes;
|
import org.springframework.security.web.webauthn.api.Bytes;
|
||||||
|
import org.springframework.security.web.webauthn.api.COSEAlgorithmIdentifier;
|
||||||
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
|
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
|
||||||
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
|
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
|
||||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput;
|
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput;
|
||||||
@ -258,12 +262,17 @@ import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExte
|
|||||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
|
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
|
||||||
import org.springframework.security.web.webauthn.api.ImmutablePublicKeyCredentialUserEntity;
|
import org.springframework.security.web.webauthn.api.ImmutablePublicKeyCredentialUserEntity;
|
||||||
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
|
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
|
||||||
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
|
||||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialDescriptor;
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialDescriptor;
|
||||||
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialParameters;
|
||||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
|
||||||
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRpEntity;
|
||||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
|
||||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||||
|
import org.springframework.security.web.webauthn.api.ResidentKeyRequirement;
|
||||||
import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses;
|
import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses;
|
||||||
import org.springframework.security.web.webauthn.api.TestBytes;
|
import org.springframework.security.web.webauthn.api.TestBytes;
|
||||||
|
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialCreationOptions;
|
||||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
|
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
|
||||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntities;
|
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntities;
|
||||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentials;
|
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentials;
|
||||||
@ -271,6 +280,7 @@ import org.springframework.security.web.webauthn.api.UserVerificationRequirement
|
|||||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthentication;
|
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthentication;
|
||||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken;
|
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken;
|
||||||
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
|
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
|
||||||
|
import org.springframework.security.web.webauthn.management.TestPublicKeyCredentialRpEntities;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
final class SerializationSamples {
|
final class SerializationSamples {
|
||||||
@ -284,6 +294,14 @@ final class SerializationSamples {
|
|||||||
Authentication authentication = TestAuthentication.authenticated(user);
|
Authentication authentication = TestAuthentication.authenticated(user);
|
||||||
SecurityContext securityContext = new SecurityContextImpl(authentication);
|
SecurityContext securityContext = new SecurityContextImpl(authentication);
|
||||||
|
|
||||||
|
instancioByClassName.put(OneTimeTokenAuthenticationToken.class, () -> {
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
InstancioOfClassApi<?> instancio = Instancio.of(OneTimeTokenAuthenticationToken.class);
|
||||||
|
instancio.supply(Select.all(OneTimeTokenAuthenticationToken.class),
|
||||||
|
(r) -> applyDetails(new OneTimeTokenAuthenticationToken("token")));
|
||||||
|
return instancio;
|
||||||
|
});
|
||||||
|
|
||||||
// oauth2-core
|
// oauth2-core
|
||||||
generatorByClassName.put(DefaultOAuth2User.class, (r) -> TestOAuth2Users.create());
|
generatorByClassName.put(DefaultOAuth2User.class, (r) -> TestOAuth2Users.create());
|
||||||
generatorByClassName.put(OAuth2AuthorizationRequest.class,
|
generatorByClassName.put(OAuth2AuthorizationRequest.class,
|
||||||
@ -597,8 +615,7 @@ final class SerializationSamples {
|
|||||||
token.setDetails(details);
|
token.setDetails(details);
|
||||||
return token;
|
return token;
|
||||||
});
|
});
|
||||||
generatorByClassName.put(OneTimeTokenAuthenticationToken.class,
|
|
||||||
(r) -> applyDetails(new OneTimeTokenAuthenticationToken("username", "token")));
|
|
||||||
generatorByClassName.put(OneTimeTokenAuthentication.class,
|
generatorByClassName.put(OneTimeTokenAuthentication.class,
|
||||||
(r) -> applyDetails(new OneTimeTokenAuthentication("username", authentication.getAuthorities())));
|
(r) -> applyDetails(new OneTimeTokenAuthentication("username", authentication.getAuthorities())));
|
||||||
generatorByClassName.put(AccessDeniedException.class,
|
generatorByClassName.put(AccessDeniedException.class,
|
||||||
@ -879,6 +896,36 @@ final class SerializationSamples {
|
|||||||
generatorByClassName.put(CredentialPropertiesOutput.ExtensionOutput.class,
|
generatorByClassName.put(CredentialPropertiesOutput.ExtensionOutput.class,
|
||||||
(r) -> new CredentialPropertiesOutput(true).getOutput());
|
(r) -> new CredentialPropertiesOutput(true).getOutput());
|
||||||
|
|
||||||
|
AttestationConveyancePreference attestationConveyancePreference = AttestationConveyancePreference.DIRECT;
|
||||||
|
ResidentKeyRequirement residentKeyRequirement = ResidentKeyRequirement.REQUIRED;
|
||||||
|
AuthenticatorSelectionCriteria authenticatorSelectionCriteria = AuthenticatorSelectionCriteria.builder()
|
||||||
|
.authenticatorAttachment(AuthenticatorAttachment.PLATFORM)
|
||||||
|
.residentKey(residentKeyRequirement)
|
||||||
|
.userVerification(UserVerificationRequirement.REQUIRED)
|
||||||
|
.build();
|
||||||
|
PublicKeyCredentialParameters publicKeyCredentialParameters = PublicKeyCredentialParameters.RS256;
|
||||||
|
PublicKeyCredentialRpEntity publicKeyCredentialRpEntity = TestPublicKeyCredentialRpEntities.createRpEntity()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
generatorByClassName.put(AttestationConveyancePreference.class, (r) -> attestationConveyancePreference);
|
||||||
|
generatorByClassName.put(ResidentKeyRequirement.class, (r) -> residentKeyRequirement);
|
||||||
|
generatorByClassName.put(AuthenticatorSelectionCriteria.class, (r) -> authenticatorSelectionCriteria);
|
||||||
|
generatorByClassName.put(COSEAlgorithmIdentifier.class, ((r) -> COSEAlgorithmIdentifier.RS256));
|
||||||
|
generatorByClassName.put(PublicKeyCredentialParameters.class, (r) -> publicKeyCredentialParameters);
|
||||||
|
generatorByClassName.put(PublicKeyCredentialRpEntity.class, (r) -> publicKeyCredentialRpEntity);
|
||||||
|
generatorByClassName.put(PublicKeyCredentialCreationOptions.class,
|
||||||
|
(o) -> TestPublicKeyCredentialCreationOptions.createPublicKeyCredentialCreationOptions()
|
||||||
|
.extensions(inputs)
|
||||||
|
.attestation(attestationConveyancePreference)
|
||||||
|
.authenticatorSelection(authenticatorSelectionCriteria)
|
||||||
|
.challenge(TestBytes.get())
|
||||||
|
.excludeCredentials(List.of(descriptor))
|
||||||
|
.rp(publicKeyCredentialRpEntity)
|
||||||
|
.pubKeyCredParams(publicKeyCredentialParameters)
|
||||||
|
.timeout(Duration.ofMinutes(5))
|
||||||
|
.user(TestPublicKeyCredentialUserEntities.userEntity().id(TestBytes.get()).build())
|
||||||
|
.build());
|
||||||
|
|
||||||
// One-Time Token
|
// One-Time Token
|
||||||
DefaultOneTimeToken oneTimeToken = new DefaultOneTimeToken(UUID.randomUUID().toString(), "user",
|
DefaultOneTimeToken oneTimeToken = new DefaultOneTimeToken(UUID.randomUUID().toString(), "user",
|
||||||
Instant.now().plusSeconds(300));
|
Instant.now().plusSeconds(300));
|
||||||
|
|||||||
@ -114,7 +114,7 @@ public class SecurityNamespaceHandlerTests {
|
|||||||
"<user-service id='us'><user name='bob' password='bobspassword' authorities='ROLE_A' /></user-service>",
|
"<user-service id='us'><user name='bob' password='bobspassword' authorities='ROLE_A' /></user-service>",
|
||||||
"3.0.3", null))
|
"3.0.3", null))
|
||||||
.withMessageContaining(
|
.withMessageContaining(
|
||||||
"You cannot use any XSD older than spring-security-7.0.xsd. Either change to spring-security.xsd or spring-security-7.0.xsd");
|
"You cannot use any XSD older than spring-security-7.1.xsd. Either change to spring-security.xsd or spring-security-7.1.xsd");
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEC-1868
|
// SEC-1868
|
||||||
|
|||||||
@ -222,7 +222,8 @@ public class WebSecurityConfigurationTests {
|
|||||||
// SEC-2773
|
// SEC-2773
|
||||||
@Test
|
@Test
|
||||||
public void getMethodDelegatingApplicationListenerWhenWebSecurityConfigurationThenIsStatic() {
|
public void getMethodDelegatingApplicationListenerWhenWebSecurityConfigurationThenIsStatic() {
|
||||||
Method method = ClassUtils.getMethod(WebSecurityConfiguration.class, "delegatingApplicationListener", null);
|
Method method = ClassUtils.getMethod(WebSecurityConfiguration.class, "delegatingApplicationListener",
|
||||||
|
(Class<?>[]) null);
|
||||||
assertThat(Modifier.isStatic(method.getModifiers())).isTrue();
|
assertThat(Modifier.isStatic(method.getModifiers())).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configurers;
|
package org.springframework.security.config.annotation.web.configurers;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
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;
|
||||||
|
|
||||||
@ -23,6 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
@ -34,11 +37,14 @@ import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
|||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
import static org.springframework.security.config.annotation.SecurityContextChangedListenerArgumentMatchers.setAuthentication;
|
import static org.springframework.security.config.annotation.SecurityContextChangedListenerArgumentMatchers.setAuthentication;
|
||||||
@ -101,6 +107,45 @@ public class AnonymousConfigurerTests {
|
|||||||
this.mockMvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("myAnonymousUser"));
|
this.mockMvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("myAnonymousUser"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void anonymousAuthenticationWhenUsingAuthenticationDetailsSourceRefThenMatchesNamespace() throws Exception {
|
||||||
|
this.spring.register(AuthenticationDetailsSourceAnonymousConfig.class).autowire();
|
||||||
|
AuthenticationDetailsSource<HttpServletRequest, ?> source = this.spring.getContext()
|
||||||
|
.getBean(AuthenticationDetailsSource.class);
|
||||||
|
this.mockMvc.perform(get("/"));
|
||||||
|
verify(source).buildDetails(any(HttpServletRequest.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
@EnableWebMvc
|
||||||
|
static class AuthenticationDetailsSourceAnonymousConfig {
|
||||||
|
|
||||||
|
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = mock(
|
||||||
|
AuthenticationDetailsSource.class);
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
return http.anonymous((anonymous) -> anonymous
|
||||||
|
.withObjectPostProcessor(new ObjectPostProcessor<AnonymousAuthenticationFilter>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <O extends AnonymousAuthenticationFilter> O postProcess(O object) {
|
||||||
|
object.setAuthenticationDetailsSource(
|
||||||
|
AuthenticationDetailsSourceAnonymousConfig.this.authenticationDetailsSource);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
})).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource() {
|
||||||
|
return this.authenticationDetailsSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
|
|||||||
@ -1201,6 +1201,7 @@ public class HeadersConfigurerTests {
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
@SuppressWarnings("removal")
|
||||||
static class PermissionsPolicyConfig {
|
static class PermissionsPolicyConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -1221,6 +1222,7 @@ public class HeadersConfigurerTests {
|
|||||||
static class PermissionsPolicyStringConfig {
|
static class PermissionsPolicyStringConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
@ -1235,6 +1237,7 @@ public class HeadersConfigurerTests {
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
@SuppressWarnings("removal")
|
||||||
static class PermissionsPolicyInvalidConfig {
|
static class PermissionsPolicyInvalidConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -1252,6 +1255,7 @@ public class HeadersConfigurerTests {
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
@SuppressWarnings("removal")
|
||||||
static class PermissionsPolicyInvalidStringConfig {
|
static class PermissionsPolicyInvalidStringConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@ -1257,6 +1257,7 @@ public class OAuth2AuthorizationCodeGrantTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
||||||
jdbcOperations);
|
jdbcOperations);
|
||||||
|
|||||||
@ -561,6 +561,7 @@ public class OAuth2ClientCredentialsGrantTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
||||||
jdbcOperations);
|
jdbcOperations);
|
||||||
|
|||||||
@ -647,6 +647,7 @@ public class OAuth2ClientRegistrationTests {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||||
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
|
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
|
||||||
|
|||||||
@ -469,6 +469,7 @@ public class OAuth2RefreshTokenGrantTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
||||||
jdbcOperations);
|
jdbcOperations);
|
||||||
|
|||||||
@ -515,6 +515,7 @@ public class OAuth2TokenIntrospectionTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
||||||
jdbcOperations);
|
jdbcOperations);
|
||||||
|
|||||||
@ -318,6 +318,7 @@ public class OAuth2TokenRevocationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
||||||
jdbcOperations);
|
jdbcOperations);
|
||||||
|
|||||||
@ -778,6 +778,7 @@ public class OidcClientRegistrationTests {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||||
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
|
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
|
||||||
|
|||||||
@ -633,6 +633,7 @@ public class OidcTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("removal")
|
||||||
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
|
||||||
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(
|
||||||
jdbcOperations);
|
jdbcOperations);
|
||||||
|
|||||||
@ -409,7 +409,9 @@ public class Saml2LogoutConfigurerTests {
|
|||||||
logoutRequest.setIssueInstant(Instant.now());
|
logoutRequest.setIssueInstant(Instant.now());
|
||||||
given(getBean(Saml2LogoutRequestValidator.class).validate(any()))
|
given(getBean(Saml2LogoutRequestValidator.class).validate(any()))
|
||||||
.willReturn(Saml2LogoutValidatorResult.success());
|
.willReturn(Saml2LogoutValidatorResult.success());
|
||||||
Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration).build();
|
Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration)
|
||||||
|
.samlResponse("samlResponse")
|
||||||
|
.build();
|
||||||
given(getBean(Saml2LogoutResponseResolver.class).resolve(any(), any())).willReturn(logoutResponse);
|
given(getBean(Saml2LogoutResponseResolver.class).resolve(any(), any())).willReturn(logoutResponse);
|
||||||
this.mvc.perform(post("/logout/saml2/slo").param("SAMLRequest", "samlRequest").with(authentication(this.user)))
|
this.mvc.perform(post("/logout/saml2/slo").param("SAMLRequest", "samlRequest").with(authentication(this.user)))
|
||||||
.andReturn();
|
.andReturn();
|
||||||
|
|||||||
@ -65,7 +65,7 @@ public class XsdDocumentedTests {
|
|||||||
|
|
||||||
String schema31xDocumentLocation = "org/springframework/security/config/spring-security-3.1.xsd";
|
String schema31xDocumentLocation = "org/springframework/security/config/spring-security-3.1.xsd";
|
||||||
|
|
||||||
String schemaDocumentLocation = "org/springframework/security/config/spring-security-7.0.xsd";
|
String schemaDocumentLocation = "org/springframework/security/config/spring-security-7.1.xsd";
|
||||||
|
|
||||||
XmlSupport xml = new XmlSupport();
|
XmlSupport xml = new XmlSupport();
|
||||||
|
|
||||||
@ -151,8 +151,8 @@ public class XsdDocumentedTests {
|
|||||||
.list((dir, name) -> name.endsWith(".xsd"));
|
.list((dir, name) -> name.endsWith(".xsd"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
assertThat(schemas.length)
|
assertThat(schemas.length)
|
||||||
.withFailMessage("the count is equal to 28, if not then schemaDocument needs updating")
|
.withFailMessage("the count is equal to 29, if not then schemaDocument needs updating")
|
||||||
.isEqualTo(28);
|
.isEqualTo(29);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -337,6 +337,54 @@ public class InterceptUrlConfigTests {
|
|||||||
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gh-18503
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void configWhenInterceptUrlMissingAccessThenException() {
|
||||||
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
|
.isThrownBy(() -> this.spring.configLocations(this.xml("MissingAccess")).autowire())
|
||||||
|
.withMessageContaining("access attribute cannot be empty or null");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gh-18503
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void configWhenInterceptUrlEmptyAccessThenException() {
|
||||||
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
|
.isThrownBy(() -> this.spring.configLocations(this.xml("EmptyAccess")).autowire())
|
||||||
|
.withMessageContaining("access attribute cannot be empty or null");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gh-18503
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void configWhenInterceptUrlValidAccessThenLoads() {
|
||||||
|
assertThatNoException().isThrownBy(() -> this.spring.configLocations(this.xml("ValidAccess")).autowire());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gh-18503
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void configWhenUseAuthorizationManagerFalseAndMissingAccessThenException() {
|
||||||
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
|
.isThrownBy(() -> this.spring.configLocations(this.xml("MissingAccessLegacy")).autowire())
|
||||||
|
.withMessageContaining("access attribute cannot be empty or null");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gh-18503
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void configWhenUseAuthorizationManagerFalseAndEmptyAccessThenException() {
|
||||||
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
|
.isThrownBy(() -> this.spring.configLocations(this.xml("EmptyAccessLegacy")).autowire())
|
||||||
|
.withMessageContaining("access attribute cannot be empty or null");
|
||||||
|
}
|
||||||
|
|
||||||
private static RequestPostProcessor adminCredentials() {
|
private static RequestPostProcessor adminCredentials() {
|
||||||
return httpBasic("admin", "password");
|
return httpBasic("admin", "password");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ package org.springframework.security.config.http;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -989,7 +988,7 @@ public class MiscHttpConfigTests {
|
|||||||
|
|
||||||
@GetMapping("/username")
|
@GetMapping("/username")
|
||||||
String username() {
|
String username() {
|
||||||
Subject subject = Subject.getSubject(AccessController.getContext());
|
Subject subject = Subject.current();
|
||||||
return subject.getPrincipals().iterator().next().getName();
|
return subject.getPrincipals().iterator().next().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -306,7 +306,9 @@ public class Saml2LogoutBeanDefinitionParserTests {
|
|||||||
logoutRequest.setIssueInstant(Instant.now());
|
logoutRequest.setIssueInstant(Instant.now());
|
||||||
given(getBean(Saml2LogoutRequestValidator.class).validate(any()))
|
given(getBean(Saml2LogoutRequestValidator.class).validate(any()))
|
||||||
.willReturn(Saml2LogoutValidatorResult.success());
|
.willReturn(Saml2LogoutValidatorResult.success());
|
||||||
Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration).build();
|
Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration)
|
||||||
|
.samlResponse("samlResponse")
|
||||||
|
.build();
|
||||||
given(getBean(Saml2LogoutResponseResolver.class).resolve(any(), any())).willReturn(logoutResponse);
|
given(getBean(Saml2LogoutResponseResolver.class).resolve(any(), any())).willReturn(logoutResponse);
|
||||||
this.mvc
|
this.mvc
|
||||||
.perform(post("/logout/saml2/slo").param("SAMLRequest", "samlRequest").with(authentication(this.saml2User)))
|
.perform(post("/logout/saml2/slo").param("SAMLRequest", "samlRequest").with(authentication(this.saml2User)))
|
||||||
|
|||||||
@ -278,7 +278,7 @@ public class LogoutSpecTests {
|
|||||||
|
|
||||||
private static class InMemorySecurityContextRepository implements ServerSecurityContextRepository {
|
private static class InMemorySecurityContextRepository implements ServerSecurityContextRepository {
|
||||||
|
|
||||||
@Nullable private SecurityContext savedContext;
|
private @Nullable SecurityContext savedContext;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
|
public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
|
||||||
@ -291,7 +291,7 @@ public class LogoutSpecTests {
|
|||||||
return Mono.justOrEmpty(this.savedContext);
|
return Mono.justOrEmpty(this.savedContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable private SecurityContext getSavedContext() {
|
private @Nullable SecurityContext getSavedContext() {
|
||||||
return this.savedContext;
|
return this.savedContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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