mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-09-08 20:51:41 +00:00
Compare commits
607 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a4f813ab29 | ||
|
686f8398dd | ||
|
653f22d4a1 | ||
|
f54c293078 | ||
|
34fccf45c2 | ||
|
f840ee06eb | ||
|
8429c23108 | ||
|
97f3567702 | ||
|
2cfdcb9d95 | ||
|
3c344ff491 | ||
|
f30cc9c5a9 | ||
|
c64b086878 | ||
|
de10e08348 | ||
|
bd119ac411 | ||
|
24ffda28d8 | ||
|
6a84f96930 | ||
|
194be8ffb6 | ||
|
47b4b155da | ||
|
0a991a91ce | ||
|
d2e934ca54 | ||
|
fee4d08de3 | ||
|
3dbcf266e9 | ||
|
eeb67650ee | ||
|
b4fc01194f | ||
|
3534b74945 | ||
|
dc0ab4c805 | ||
|
c982753d46 | ||
|
910df479be | ||
|
9866435946 | ||
|
5370f1190f | ||
|
f13d8d5c75 | ||
|
1216ee598f | ||
|
a4a4908d71 | ||
|
0ff9f10696 | ||
|
7e3bf9662c | ||
|
be64c67af5 | ||
|
a58f3282d9 | ||
|
c2ba662b91 | ||
|
49f308adb0 | ||
|
4cbe8de7ea | ||
|
559b73b39f | ||
|
3278f3a410 | ||
|
36f1de945f | ||
|
6663eea65f | ||
|
89b2f9cf54 | ||
|
0e39685b9c | ||
|
9d64880ea9 | ||
|
8b2a453301 | ||
|
d1962201b5 | ||
|
857ca9c412 | ||
|
894105aab5 | ||
|
f7f41ba6c4 | ||
|
f496ded4e5 | ||
|
583e668c6b | ||
|
d6a0e3bf78 | ||
|
312c2049f3 | ||
|
3dd4686feb | ||
|
29bb4919ca | ||
|
d9210c6596 | ||
|
b8b1a92ad4 | ||
|
bbcdb23698 | ||
|
9bbf837c7c | ||
|
8a1e2a22f9 | ||
|
0404996f87 | ||
|
0f63d98c84 | ||
|
fbfbb1e571 | ||
|
d002e68231 | ||
|
41162aa7e3 | ||
|
d86f2c957d | ||
|
62b5b1a77c | ||
|
523222c24d | ||
|
69f38d4933 | ||
|
0179a811c7 | ||
|
7ce2bdd701 | ||
|
de4ceffc4f | ||
|
8c920a7ee7 | ||
|
b9653346a1 | ||
|
9e6bcbd1d0 | ||
|
8d888edc71 | ||
|
f82fe9c8c6 | ||
|
a8f045eb50 | ||
|
5c5efc9092 | ||
|
5453224377 | ||
|
a14ad770ab | ||
|
806297da23 | ||
|
8846b44b81 | ||
|
7f103b2d0a | ||
|
c06ff59747 | ||
|
f1194de45e | ||
|
1f16009c8d | ||
|
3e13437b1a | ||
|
20a6863e07 | ||
|
e145c07d5b | ||
|
68a7f1702f | ||
|
3e8b606aac | ||
|
ef5c703010 | ||
|
47be93e694 | ||
|
9310153d16 | ||
|
a933089ec2 | ||
|
a8da9ec7f7 | ||
|
3396890d8b | ||
|
c45bc384da | ||
|
4da98dde2b | ||
|
7575e4ef1c | ||
|
70626fe3d9 | ||
|
acaed1ad96 | ||
|
0549bf566b | ||
|
01c8cea00f | ||
|
d2b70230f5 | ||
|
34aac5d45f | ||
|
319c7a4937 | ||
|
714781df78 | ||
|
a04b026000 | ||
|
aeb2dbc2b6 | ||
|
006f638c0a | ||
|
890c11d428 | ||
|
01401f1c67 | ||
|
6765ac0afa | ||
|
19c41054eb | ||
|
cbd51e8b36 | ||
|
bc7c72d6a3 | ||
|
39301574fa | ||
|
4ae782cdd6 | ||
|
f6f7cc6180 | ||
|
d3b143dab6 | ||
|
60c42e3f24 | ||
|
5506c487de | ||
|
2258699f5d | ||
|
7aaead5b02 | ||
|
e1341b22e0 | ||
|
40898775ec | ||
|
057b7c68fb | ||
|
7b1c917593 | ||
|
62ca6aaf21 | ||
|
dcd7490ddd | ||
|
08fa272749 | ||
|
164cc4611c | ||
|
4751d18761 | ||
|
4b3a0d28fe | ||
|
70d0422de2 | ||
|
bdcca0da52 | ||
|
df3080b0e2 | ||
|
a5c38bdc94 | ||
|
35b508adbf | ||
|
b4123a4570 | ||
|
4d1c5f20f8 | ||
|
fb41227c86 | ||
|
eee388adc6 | ||
|
989638d8d0 | ||
|
f334ee9128 | ||
|
1d2d268268 | ||
|
93204e81d5 | ||
|
cfe11bd15d | ||
|
57a9897840 | ||
|
acc9f84e67 | ||
|
eeb383ac46 | ||
|
6d1a886f92 | ||
|
6f1232ce79 | ||
|
93cb01612b | ||
|
dfc8be0d48 | ||
|
371bee685f | ||
|
5887f755a3 | ||
|
d0f5538f21 | ||
|
f61a8deccc | ||
|
d6e378e9bb | ||
|
bd98db4fe8 | ||
|
c9bf821402 | ||
|
ca557a9880 | ||
|
2fbe8dd8f6 | ||
|
1af665d6c8 | ||
|
1a56023f7f | ||
|
6873685fd0 | ||
|
0956846905 | ||
|
c84fd8a04b | ||
|
2866fa67ad | ||
|
b6ab504c64 | ||
|
9baee6fb14 | ||
|
99f689eb52 | ||
|
7bd7ff6b42 | ||
|
6c19a355b5 | ||
|
ae514b320f | ||
|
5e783abbe7 | ||
|
517a2b185f | ||
|
a2e85dd187 | ||
|
f6cb0bd610 | ||
|
4775fe41db | ||
|
116bee1303 | ||
|
bf877a9864 | ||
|
34742c9743 | ||
|
4ffec6dcdd | ||
|
c85aa61118 | ||
|
4503947faa | ||
|
d58b068098 | ||
|
6bdab77302 | ||
|
7f25f67dd0 | ||
|
9489ab48ab | ||
|
fe411896af | ||
|
176c3b8457 | ||
|
7e1a92b091 | ||
|
48533ede45 | ||
|
614763041e | ||
|
b672aae640 | ||
|
79cd982341 | ||
|
7c887d2da1 | ||
|
9db1ffbd79 | ||
|
bc4ec39fa5 | ||
|
fca30e3d25 | ||
|
84d54b94c9 | ||
|
02b922ce5a | ||
|
ef77d3f0cf | ||
|
85dc06bbdf | ||
|
4fa2d323fd | ||
|
f2886f0ffc | ||
|
23cf29ba17 | ||
|
63e0a56bee | ||
|
6fa82bc0e3 | ||
|
15fc898804 | ||
|
55a2100d1a | ||
|
2e75929856 | ||
|
ce6e8f9109 | ||
|
66ddfb43a0 | ||
|
b8741759ce | ||
|
eaaadefa18 | ||
|
a1f5b343ab | ||
|
25f69e92c7 | ||
|
a2d687f78b | ||
|
ecad58310a | ||
|
84dd6376a5 | ||
|
ad5ccf2a39 | ||
|
563163aab0 | ||
|
644c7ac821 | ||
|
aaa34af4f7 | ||
|
f96b9bb5cc | ||
|
b8796d84b7 | ||
|
f0c5a85d9a | ||
|
dadf4c0b8a | ||
|
5fefdd5bb3 | ||
|
0c42b61cc1 | ||
|
9df668151b | ||
|
4d3024cb49 | ||
|
686cc5fc1f | ||
|
684775b46a | ||
|
ff7359b54a | ||
|
ec16322000 | ||
|
b7ae9910b5 | ||
|
ee2b826362 | ||
|
7f8b9c895f | ||
|
728b5224cb | ||
|
f1725b25a0 | ||
|
2c87270dbc | ||
|
dadf10899c | ||
|
c312d18191 | ||
|
901b386ca6 | ||
|
da182a2d7c | ||
|
571b6fe4a8 | ||
|
9dea1c2eb5 | ||
|
c06b1f4916 | ||
|
e48fdd5ed4 | ||
|
dbb3b7e1f5 | ||
|
bfa2a3613c | ||
|
02d69ec864 | ||
|
a439bc65d6 | ||
|
19e88f5e35 | ||
|
242956a63c | ||
|
ca5e307bf4 | ||
|
8e94157971 | ||
|
e4155e8540 | ||
|
7aecd78920 | ||
|
e52987d03c | ||
|
62252c1232 | ||
|
a9636c72d1 | ||
|
74771a3d42 | ||
|
fdf52f021d | ||
|
6dc77bd98b | ||
|
42283a5c1d | ||
|
5ae1b73bae | ||
|
d8043dc8a7 | ||
|
21036c94b4 | ||
|
519ae241f4 | ||
|
596d44757a | ||
|
639a9afaea | ||
|
9312fb7004 | ||
|
448283b30c | ||
|
ce107795d8 | ||
|
af2985a269 | ||
|
d3e9e3138d | ||
|
b71a66bdaa | ||
|
e9506776f1 | ||
|
b6d61b2f10 | ||
|
919ae1d636 | ||
|
7da352129c | ||
|
558b7e0b47 | ||
|
e8ed0f1b03 | ||
|
3e53cc2c4a | ||
|
f709a9efef | ||
|
98686a5139 | ||
|
d869686d09 | ||
|
d5f986f733 | ||
|
f0d523b0ab | ||
|
1583c90433 | ||
|
a9e28a2ae9 | ||
|
8c100c5c27 | ||
|
4d524b1fe1 | ||
|
081c92a9e5 | ||
|
a22b2ffc94 | ||
|
06bd81b1da | ||
|
526f8a6200 | ||
|
edb7a642c7 | ||
|
dff5780e09 | ||
|
465d46caa1 | ||
|
f8cb1b77fa | ||
|
e869bcdfa3 | ||
|
cfe38957d7 | ||
|
ee171a1c17 | ||
|
eb468316fc | ||
|
eb3f32772f | ||
|
890049c6f7 | ||
|
75efb17c49 | ||
|
2e4259f359 | ||
|
7153d7930b | ||
|
d1aecb1ade | ||
|
4d9c81e3d1 | ||
|
eed4ae751e | ||
|
c43b128f1a | ||
|
f22f41ba19 | ||
|
3d9069ac4d | ||
|
a5b7bf989e | ||
|
3c5e6a32c2 | ||
|
725745defd | ||
|
25a5105b86 | ||
|
7704b4e986 | ||
|
1c6fb12dde | ||
|
f54c75f0f3 | ||
|
ff59dc35e9 | ||
|
2cccfe88a1 | ||
|
0cc49b8788 | ||
|
4ca80cdd28 | ||
|
a979094a48 | ||
|
3f9bb81164 | ||
|
0137d0254c | ||
|
f79c0bc734 | ||
|
d4c580ad49 | ||
|
418dc793ac | ||
|
a2f756264a | ||
|
20a486c83d | ||
|
08cdf7d53b | ||
|
8f0f3343fa | ||
|
91a5a97c50 | ||
|
a373ebd009 | ||
|
f34337a4e0 | ||
|
e37424c637 | ||
|
7587048f95 | ||
|
7de4217469 | ||
|
2f53a2edb3 | ||
|
e4a2ac27d6 | ||
|
401f836051 | ||
|
6798a0c2c4 | ||
|
a4012d60df | ||
|
7bf0cba45d | ||
|
f812a847df | ||
|
4f602cb1a5 | ||
|
4e6e25d3a5 | ||
|
feffe23a0e | ||
|
5dce2ab500 | ||
|
586340b2ae | ||
|
123ba5a81a | ||
|
00ead7f24d | ||
|
8fd2401a2e | ||
|
302d9a879f | ||
|
71cd14a165 | ||
|
f7d5390e74 | ||
|
f6f8417c11 | ||
|
cd14e3d161 | ||
|
e686ac6b11 | ||
|
a74ce06dae | ||
|
edfae34178 | ||
|
a8bd1d0143 | ||
|
054909694b | ||
|
fb6d29759c | ||
|
3fb987ed17 | ||
|
afb3d5d571 | ||
|
6ccadbd880 | ||
|
b4a447a99e | ||
|
8a0d746008 | ||
|
f04d5b9f05 | ||
|
14d9de2793 | ||
|
d26d76ecb3 | ||
|
3fd697f9a6 | ||
|
90ddb00c00 | ||
|
08cbdb4640 | ||
|
396809bf01 | ||
|
3e9d585410 | ||
|
a4c338f8a5 | ||
|
da6c7b8759 | ||
|
777447e1d9 | ||
|
cf6b52d6f7 | ||
|
5dd40a7f10 | ||
|
f789abc87f | ||
|
461f00ed38 | ||
|
9fcfacf283 | ||
|
1a7b1fcc7c | ||
|
45a1447e9b | ||
|
1435e0f3d3 | ||
|
13e738e733 | ||
|
c43afbf5e1 | ||
|
20a2213e11 | ||
|
09983e2349 | ||
|
6ddb964c61 | ||
|
349451c8a5 | ||
|
e17c256fce | ||
|
42e24aa53c | ||
|
06ed6ef342 | ||
|
676b44ebb0 | ||
|
ee09215f89 | ||
|
709f5db0e5 | ||
|
18010f9914 | ||
|
9cf5638914 | ||
|
c2c84c4243 | ||
|
b2325e4176 | ||
|
502b0b7f95 | ||
|
87bb5d4e2d | ||
|
df676b3089 | ||
|
fc587913a7 | ||
|
fce40bc3ed | ||
|
c2ecc8b538 | ||
|
bd31a40824 | ||
|
6036e1ceb5 | ||
|
f33b7b5479 | ||
|
32d0be9364 | ||
|
468a07b1a0 | ||
|
7da4712056 | ||
|
1f57df6caa | ||
|
5130cbb99f | ||
|
043464fd3d | ||
|
e1d8033ee3 | ||
|
8e57014c50 | ||
|
025995ef97 | ||
|
040ffe17e5 | ||
|
092bbfc8e7 | ||
|
b0cecb37d2 | ||
|
e3add59550 | ||
|
7bf2730a53 | ||
|
88ed4a5ccf | ||
|
2b740b7f1f | ||
|
f690a7f3df | ||
|
5f2efbea6a | ||
|
aba437d469 | ||
|
e8f920e0ee | ||
|
2bd05128ec | ||
|
e2e42a5580 | ||
|
16fd24c002 | ||
|
60f729156b | ||
|
220f49d86e | ||
|
9b724377ce | ||
|
02a8c416aa | ||
|
36c7b91fb9 | ||
|
ffd6e3c0f7 | ||
|
2c5bd4c916 | ||
|
dc954875f3 | ||
|
a060f7b462 | ||
|
d0db5e3ea3 | ||
|
aa3135169d | ||
|
3ddf201d66 | ||
|
edfd7b9b43 | ||
|
358f6c96b5 | ||
|
eaf8184142 | ||
|
097640b72a | ||
|
35e8aa6435 | ||
|
8e1db3fe2b | ||
|
28174a6d3e | ||
|
3948440ee4 | ||
|
72b5e96a0d | ||
|
a47022799e | ||
|
98c3453aa4 | ||
|
adca1b31be | ||
|
2e913d2af9 | ||
|
c8b843c4c5 | ||
|
eaab42a73c | ||
|
30577bd291 | ||
|
4967f3feee | ||
|
3f0326d3f1 | ||
|
0ec7a7a305 | ||
|
492444c588 | ||
|
f73f253beb | ||
|
32c7e8a6ee | ||
|
3de7312658 | ||
|
4ed131f6ab | ||
|
8953f464fb | ||
|
b20cfceabb | ||
|
9654e51bd4 | ||
|
d52e0b6a05 | ||
|
195f933438 | ||
|
ada75e76a6 | ||
|
227a2cc0c7 | ||
|
5517d8fe3a | ||
|
fd4f06a66e | ||
|
6d3b54df21 | ||
|
37a814bc29 | ||
|
215547f8c8 | ||
|
da2d9aa868 | ||
|
42790403da | ||
|
ec05e65668 | ||
|
bf05b8b430 | ||
|
91b21663db | ||
|
596449d882 | ||
|
1a4de49977 | ||
|
52394c1f07 | ||
|
fae61b9426 | ||
|
8612e952fe | ||
|
f4b8e2421a | ||
|
9ba5c7b2ce | ||
|
8e2067bb3e | ||
|
88369cd252 | ||
|
c9bbf3787b | ||
|
50f8ad55a8 | ||
|
64d3397a9c | ||
|
ff22866c6d | ||
|
cd27290260 | ||
|
e686621e92 | ||
|
d9c894fae8 | ||
|
47338f7e56 | ||
|
97923ebfaf | ||
|
c46f263483 | ||
|
b3340536dc | ||
|
07575d2e2e | ||
|
7e4c72806c | ||
|
0ee3fe2a58 | ||
|
45e81c2d0a | ||
|
b7909a56c5 | ||
|
a339dbc893 | ||
|
e772025646 | ||
|
e19c9995ae | ||
|
cc0faeaa9c | ||
|
33a0a12a20 | ||
|
2041757607 | ||
|
9004897e2d | ||
|
1cde8ca2c3 | ||
|
665a34da3a | ||
|
07a50b460a | ||
|
b5db32994f | ||
|
4fb3dca953 | ||
|
e30dc42d1e | ||
|
0722c2dc41 | ||
|
817938fa49 | ||
|
3b492a9628 | ||
|
c22091d8be | ||
|
aa4db57b89 | ||
|
903cefceb3 | ||
|
a8edcca961 | ||
|
a511171309 | ||
|
86550fb84b | ||
|
44303d2c80 | ||
|
462e38c0e3 | ||
|
8b925dc4fc | ||
|
3f91c3effc | ||
|
cb511f501a | ||
|
87434a7b05 | ||
|
f1e3f2a8d3 | ||
|
f511d0a345 | ||
|
64b26cbd1f | ||
|
99330bfc60 | ||
|
21c56554c9 | ||
|
c8339184a9 | ||
|
40a18fe63c | ||
|
0698d3527d | ||
|
93a7583aa4 | ||
|
a90ce5142c | ||
|
ba7be9c8b9 | ||
|
ff8b77df29 | ||
|
48eb243012 | ||
|
1e4dd713c5 | ||
|
6118587ff8 | ||
|
241c3cd35a | ||
|
693a5beb24 | ||
|
f13836c9c8 | ||
|
23e7c9eeaa | ||
|
d52289bd7a | ||
|
5eb232cd3d | ||
|
2b22cf2877 | ||
|
5f833fa236 | ||
|
7fda87aecd | ||
|
de622d1082 | ||
|
47f7d83ee4 | ||
|
69c52cc4f7 | ||
|
46ee6eda76 | ||
|
9c357984d7 | ||
|
e61544c397 | ||
|
506a801f29 | ||
|
866d8d0eab | ||
|
e599a17303 | ||
|
276bb82e7e | ||
|
a80592a707 | ||
|
b453840c0a | ||
|
e5e962ef90 | ||
|
0e2d864b09 | ||
|
607705347c | ||
|
66319fc3bc | ||
|
2dbf3a2d18 | ||
|
5704582c52 | ||
|
3976e7d456 | ||
|
b467c47ed5 | ||
|
11105a5c51 | ||
|
38a9aa1da9 | ||
|
222faae1cb | ||
|
cb0fdef236 | ||
|
5abbcecccc | ||
|
c385a59b68 |
78
.github/dependabot.yml
vendored
78
.github/dependabot.yml
vendored
@ -3,7 +3,37 @@ registries:
|
|||||||
spring-milestones:
|
spring-milestones:
|
||||||
type: maven-repository
|
type: maven-repository
|
||||||
url: https://repo.spring.io/milestone
|
url: https://repo.spring.io/milestone
|
||||||
|
shibboleth:
|
||||||
|
type: maven-repository
|
||||||
|
url: https://build.shibboleth.net/maven/releases
|
||||||
updates:
|
updates:
|
||||||
|
- package-ecosystem: gradle
|
||||||
|
target-branch: 6.5.x
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
time: '03:00'
|
||||||
|
timezone: Etc/UTC
|
||||||
|
labels:
|
||||||
|
- 'type: dependency-upgrade'
|
||||||
|
registries:
|
||||||
|
- spring-milestones
|
||||||
|
- 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: '*'
|
||||||
|
update-types:
|
||||||
|
- version-update:semver-major
|
||||||
|
- version-update:semver-minor
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: 6.4.x
|
target-branch: 6.4.x
|
||||||
directory: /
|
directory: /
|
||||||
@ -15,6 +45,7 @@ updates:
|
|||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- spring-milestones
|
- spring-milestones
|
||||||
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
- dependency-name: org.python:jython
|
- dependency-name: org.python:jython
|
||||||
@ -30,32 +61,7 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
- version-update:semver-minor
|
- version-update:semver-minor
|
||||||
- package-ecosystem: gradle
|
|
||||||
target-branch: 6.3.x
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
time: '03:00'
|
|
||||||
timezone: Etc/UTC
|
|
||||||
labels:
|
|
||||||
- 'type: dependency-upgrade'
|
|
||||||
registries:
|
|
||||||
- spring-milestones
|
|
||||||
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: '*'
|
|
||||||
update-types:
|
|
||||||
- version-update:semver-major
|
|
||||||
- version-update:semver-minor
|
|
||||||
- package-ecosystem: gradle
|
- package-ecosystem: gradle
|
||||||
target-branch: main
|
target-branch: main
|
||||||
directory: /
|
directory: /
|
||||||
@ -67,6 +73,7 @@ updates:
|
|||||||
- 'type: dependency-upgrade'
|
- 'type: dependency-upgrade'
|
||||||
registries:
|
registries:
|
||||||
- spring-milestones
|
- spring-milestones
|
||||||
|
- shibboleth
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
- dependency-name: com.nimbusds:nimbus-jose-jwt
|
||||||
- dependency-name: org.python:jython
|
- dependency-name: org.python:jython
|
||||||
@ -87,25 +94,6 @@ updates:
|
|||||||
- version-update:semver-major
|
- version-update:semver-major
|
||||||
- version-update:semver-minor
|
- version-update:semver-minor
|
||||||
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
target-branch: 6.3.x
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'in: build'
|
|
||||||
ignore:
|
|
||||||
- dependency-name: sjohnr/*
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
target-branch: docs-build
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
labels:
|
|
||||||
- 'type: task'
|
|
||||||
- 'in: build'
|
|
||||||
|
|
||||||
- package-ecosystem: npm
|
- package-ecosystem: npm
|
||||||
target-branch: docs-build
|
target-branch: docs-build
|
||||||
directory: /
|
directory: /
|
||||||
|
38
.github/workflows/check-snapshots.yml
vendored
Normal file
38
.github/workflows/check-snapshots.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 10 * * *' # Once per day at 10am UTC
|
||||||
|
workflow_dispatch: # Manual trigger
|
||||||
|
|
||||||
|
env:
|
||||||
|
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
snapshot-test:
|
||||||
|
name: Test Against Snapshots
|
||||||
|
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@v1
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- java-version: 21-ea
|
||||||
|
toolchain: 21
|
||||||
|
- java-version: 17
|
||||||
|
toolchain: 17
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.java-version }}
|
||||||
|
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
|
||||||
|
secrets: inherit
|
||||||
|
send-notification:
|
||||||
|
name: Send Notification
|
||||||
|
needs: [ snapshot-test ]
|
||||||
|
if: ${{ !success() }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Send Notification
|
||||||
|
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
|
||||||
|
with:
|
||||||
|
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
|
@ -27,60 +27,24 @@ jobs:
|
|||||||
java-version: ${{ matrix.jdk }}
|
java-version: ${{ matrix.jdk }}
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
test:
|
|
||||||
name: Test Against Snapshots
|
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@v1
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- java-version: 21-ea
|
|
||||||
toolchain: 21
|
|
||||||
- java-version: 17
|
|
||||||
toolchain: 17
|
|
||||||
with:
|
|
||||||
java-version: ${{ matrix.java-version }}
|
|
||||||
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=6.2.+ -PreactorVersion=2023.0.+ -PspringDataVersion=2024.0.+ --stacktrace
|
|
||||||
secrets: inherit
|
|
||||||
check-samples:
|
|
||||||
name: Check Samples
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.repository_owner == 'spring-projects' }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Set up gradle
|
|
||||||
uses: spring-io/spring-gradle-build-action@v2
|
|
||||||
with:
|
|
||||||
java-version: 17
|
|
||||||
distribution: temurin
|
|
||||||
- name: Check samples project
|
|
||||||
env:
|
|
||||||
LOCAL_REPOSITORY_PATH: ${{ github.workspace }}/build/publications/repos
|
|
||||||
SAMPLES_DIR: ../spring-security-samples
|
|
||||||
run: |
|
|
||||||
# Extract version from gradle.properties
|
|
||||||
version=$(cat gradle.properties | grep "version=" | awk -F'=' '{print $2}')
|
|
||||||
# Extract samplesBranch from gradle.properties
|
|
||||||
samples_branch=$(cat gradle.properties | grep "samplesBranch=" | awk -F'=' '{print $2}')
|
|
||||||
./gradlew publishMavenJavaPublicationToLocalRepository
|
|
||||||
./gradlew cloneRepository -PrepositoryName="spring-projects/spring-security-samples" -Pref="$samples_branch" -PcloneOutputDirectory="$SAMPLES_DIR"
|
|
||||||
./gradlew --refresh-dependencies --project-dir "$SAMPLES_DIR" --init-script spring-security-ci.gradle -PlocalRepositoryPath="$LOCAL_REPOSITORY_PATH" -PspringSecurityVersion="$version" test integrationTest
|
|
||||||
deploy-artifacts:
|
deploy-artifacts:
|
||||||
name: Deploy Artifacts
|
name: Deploy Artifacts
|
||||||
needs: [ build, test, check-samples ]
|
needs: [ build]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@v1
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@v1
|
||||||
with:
|
with:
|
||||||
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
|
default-publish-milestones-central: true
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
deploy-docs:
|
deploy-docs:
|
||||||
name: Deploy Docs
|
name: Deploy Docs
|
||||||
needs: [ build, test, check-samples ]
|
needs: [ build ]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-docs.yml@v1
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-docs.yml@v1
|
||||||
with:
|
with:
|
||||||
should-deploy-docs: ${{ needs.build.outputs.should-deploy-artifacts }}
|
should-deploy-docs: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
deploy-schema:
|
deploy-schema:
|
||||||
name: Deploy Schema
|
name: Deploy Schema
|
||||||
needs: [ build, test, check-samples ]
|
needs: [ build ]
|
||||||
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@v1
|
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@v1
|
||||||
with:
|
with:
|
||||||
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
|
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
|
||||||
@ -92,7 +56,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
|
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
|
||||||
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
|
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
|
||||||
milestone-repo-url: https://repo.spring.io/artifactory/milestone
|
milestone-repo-url: https://repo1.maven.org/maven2
|
||||||
release-repo-url: https://repo1.maven.org/maven2
|
release-repo-url: https://repo1.maven.org/maven2
|
||||||
artifact-path: org/springframework/security/spring-security-core
|
artifact-path: org/springframework/security/spring-security-core
|
||||||
slack-announcing-id: spring-security-announcing
|
slack-announcing-id: spring-security-announcing
|
||||||
|
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.4.x, 6.3.x ]
|
branch: [ main, 6.5.x, 6.4.x, 6.3.x ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
@ -79,6 +79,9 @@ See https://github.com/spring-projects/spring-security/tree/main#building-from-s
|
|||||||
|
|
||||||
The wiki pages https://github.com/spring-projects/spring-framework/wiki/Code-Style[Code Style] and https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings[IntelliJ IDEA Editor Settings] define the source file coding standards we use along with some IDEA editor settings we customize.
|
The wiki pages https://github.com/spring-projects/spring-framework/wiki/Code-Style[Code Style] and https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings[IntelliJ IDEA Editor Settings] define the source file coding standards we use along with some IDEA editor settings we customize.
|
||||||
|
|
||||||
|
Additionally, since Streams are https://github.com/spring-projects/spring-security/issues/7154[much slower] than `for` loops, please use them judiciously.
|
||||||
|
The team may ask you to change to a `for` loop if the given code is along a hot path.
|
||||||
|
|
||||||
To format the code as well as check the style, run `./gradlew format && ./gradlew check`.
|
To format the code as well as check the style, run `./gradlew format && ./gradlew check`.
|
||||||
|
|
||||||
[[submit-a-pull-request]]
|
[[submit-a-pull-request]]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java-gradle-plugin"
|
id "java-gradle-plugin"
|
||||||
|
id "groovy-gradle-plugin"
|
||||||
id "java"
|
id "java"
|
||||||
id "groovy"
|
id "groovy"
|
||||||
}
|
}
|
||||||
@ -63,6 +64,7 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation platform(libs.io.projectreactor.reactor.bom)
|
implementation platform(libs.io.projectreactor.reactor.bom)
|
||||||
|
|
||||||
|
implementation libs.spring.nullability
|
||||||
implementation libs.com.google.code.gson.gson
|
implementation libs.com.google.code.gson.gson
|
||||||
implementation libs.com.thaiopensource.trag
|
implementation libs.com.thaiopensource.trag
|
||||||
implementation libs.net.sourceforge.saxon.saxon
|
implementation libs.net.sourceforge.saxon.saxon
|
||||||
@ -76,6 +78,7 @@ dependencies {
|
|||||||
implementation libs.com.github.spullara.mustache.java.compiler
|
implementation libs.com.github.spullara.mustache.java.compiler
|
||||||
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
|
implementation libs.io.spring.javaformat.spring.javaformat.gradle.plugin
|
||||||
implementation libs.io.spring.nohttp.nohttp.gradle
|
implementation libs.io.spring.nohttp.nohttp.gradle
|
||||||
|
implementation libs.org.jetbrains.kotlin.kotlin.gradle.plugin
|
||||||
implementation (libs.net.sourceforge.htmlunit) {
|
implementation (libs.net.sourceforge.htmlunit) {
|
||||||
exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client'
|
exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client'
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public class ManagementConfigurationPlugin implements Plugin<Project> {
|
|||||||
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
|
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
|
||||||
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
|
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
|
||||||
mavenPublication.versionMapping((versions) ->
|
mavenPublication.versionMapping((versions) ->
|
||||||
versions.allVariants(versionMapping -> versionMapping.fromResolutionResult())
|
versions.allVariants((versionMapping) -> versionMapping.fromResolutionResult())
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -80,6 +80,11 @@ class RepositoryConventionPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
url = 'https://repo.spring.io/release/'
|
url = 'https://repo.spring.io/release/'
|
||||||
}
|
}
|
||||||
|
forceMavenRepositories.findAll { it.startsWith('https://') || it.startsWith('file://') }.each { mavenUrl ->
|
||||||
|
maven {
|
||||||
|
url mavenUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,10 +32,13 @@ public class SchemaZipPlugin implements Plugin<Project> {
|
|||||||
for (def key : schemas.keySet()) {
|
for (def key : schemas.keySet()) {
|
||||||
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
||||||
assert shortName != key
|
assert shortName != key
|
||||||
|
def schemaResourceName = schemas.get(key)
|
||||||
File xsdFile = module.sourceSets.main.resources.find {
|
File xsdFile = module.sourceSets.main.resources.find {
|
||||||
it.path.endsWith(schemas.get(key))
|
it.path.endsWith(schemaResourceName)
|
||||||
|
}
|
||||||
|
if (xsdFile == null) {
|
||||||
|
throw new IllegalStateException("Could not find schema file for resource name " + schemaResourceName + " in src/main/resources")
|
||||||
}
|
}
|
||||||
assert xsdFile != null
|
|
||||||
schemaZip.into (shortName) {
|
schemaZip.into (shortName) {
|
||||||
duplicatesStrategy 'exclude'
|
duplicatesStrategy 'exclude'
|
||||||
from xsdFile.path
|
from xsdFile.path
|
||||||
|
17
buildSrc/src/main/groovy/security-kotlin.gradle
Normal file
17
buildSrc/src/main/groovy/security-kotlin.gradle
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'kotlin'
|
||||||
|
}
|
||||||
|
|
||||||
|
project.plugins.withId("org.jetbrains.kotlin.jvm", (kotlinProject) -> {
|
||||||
|
project.tasks.withType(KotlinCompile).configureEach {
|
||||||
|
kotlinOptions {
|
||||||
|
languageVersion = '2.2'
|
||||||
|
apiVersion = '2.2'
|
||||||
|
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings"]
|
||||||
|
jvmTarget = '17'
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
3
buildSrc/src/main/groovy/security-nullability.gradle
Normal file
3
buildSrc/src/main/groovy/security-nullability.gradle
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
plugins {
|
||||||
|
id 'io.spring.nullability'
|
||||||
|
}
|
@ -81,9 +81,6 @@ public class CheckClasspathForProhibitedDependencies extends DefaultTask {
|
|||||||
if (group.startsWith("javax")) {
|
if (group.startsWith("javax")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (group.equals("commons-logging")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (group.equals("org.slf4j") && id.getName().equals("jcl-over-slf4j")) {
|
if (group.equals("org.slf4j") && id.getName().equals("jcl-over-slf4j")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class CheckExpectedBranchVersionPlugin implements Plugin<Project> {
|
|||||||
task.setDescription("Check if the project version matches the branch version");
|
task.setDescription("Check if the project version matches the branch version");
|
||||||
task.onlyIf("skipCheckExpectedBranchVersion property is false or not present", CheckExpectedBranchVersionPlugin::skipPropertyFalseOrNotPresent);
|
task.onlyIf("skipCheckExpectedBranchVersion property is false or not present", CheckExpectedBranchVersionPlugin::skipPropertyFalseOrNotPresent);
|
||||||
task.getVersion().convention(project.provider(() -> project.getVersion().toString()));
|
task.getVersion().convention(project.provider(() -> project.getVersion().toString()));
|
||||||
task.getBranchName().convention(project.getProviders().exec(execSpec -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
|
task.getBranchName().convention(project.getProviders().exec((execSpec) -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
|
||||||
task.getOutputFile().convention(project.getLayout().getBuildDirectory().file("check-expected-branch-version"));
|
task.getOutputFile().convention(project.getLayout().getBuildDirectory().file("check-expected-branch-version"));
|
||||||
});
|
});
|
||||||
project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, checkTask -> checkTask.dependsOn(checkExpectedBranchVersionTask));
|
project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, checkTask -> checkTask.dependsOn(checkExpectedBranchVersionTask));
|
||||||
|
@ -17,8 +17,6 @@ package io.spring.gradle;
|
|||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.gradle.testkit.runner.GradleRunner;
|
import org.gradle.testkit.runner.GradleRunner;
|
||||||
import org.junit.runner.Description;
|
|
||||||
import org.junit.runners.model.Statement;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -23,8 +23,6 @@ import org.gradle.testfixtures.ProjectBuilder;
|
|||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,6 @@ import org.apache.commons.io.FileUtils;
|
|||||||
import org.gradle.testkit.runner.BuildResult;
|
import org.gradle.testkit.runner.BuildResult;
|
||||||
import org.gradle.testkit.runner.TaskOutcome;
|
import org.gradle.testkit.runner.TaskOutcome;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
id 'security-nullability'
|
||||||
|
}
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -14,6 +18,7 @@ dependencies {
|
|||||||
|
|
||||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||||
|
|
||||||
|
testImplementation project(path : ':spring-security-web', configuration : 'tests')
|
||||||
testImplementation "org.assertj:assertj-core"
|
testImplementation "org.assertj:assertj-core"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas;
|
package org.springframework.security.cas;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
|
|
||||||
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
|
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
|
||||||
|
|
||||||
private String service;
|
private @Nullable String service;
|
||||||
|
|
||||||
private boolean authenticateAllArtifacts;
|
private boolean authenticateAllArtifacts;
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ public class ServiceProperties implements InitializingBean {
|
|||||||
* </pre>
|
* </pre>
|
||||||
* @return the URL of the service the user is authenticating to
|
* @return the URL of the service the user is authenticating to
|
||||||
*/
|
*/
|
||||||
public final String getService() {
|
public final @Nullable String getService() {
|
||||||
return this.service;
|
return this.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ import java.util.ArrayList;
|
|||||||
import org.apereo.cas.client.validation.Assertion;
|
import org.apereo.cas.client.validation.Assertion;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporary authentication object needed to load the user details service.
|
* Temporary authentication object needed to load the user details service.
|
||||||
@ -31,7 +30,7 @@ import org.springframework.security.core.SpringSecurityCoreVersion;
|
|||||||
*/
|
*/
|
||||||
public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
|
public final class CasAssertionAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
|
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
private final Assertion assertion;
|
private final Assertion assertion;
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ 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.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
@ -62,6 +64,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("NullAway.Init")
|
||||||
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
||||||
|
|
||||||
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
||||||
@ -70,11 +73,13 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
|
|
||||||
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
|
||||||
|
|
||||||
|
@SuppressWarnings("NullAway.Init")
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
@SuppressWarnings("NullAway.Init")
|
||||||
private TicketValidator ticketValidator;
|
private TicketValidator ticketValidator;
|
||||||
|
|
||||||
private ServiceProperties serviceProperties;
|
private @Nullable ServiceProperties serviceProperties;
|
||||||
|
|
||||||
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
||||||
|
|
||||||
@ -89,7 +94,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
if (!supports(authentication.getClass())) {
|
if (!supports(authentication.getClass())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -129,11 +134,14 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
|
|
||||||
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
|
private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
|
||||||
try {
|
try {
|
||||||
Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(),
|
Object credentials = authentication.getCredentials();
|
||||||
getServiceUrl(authentication));
|
if (credentials == null) {
|
||||||
|
throw new BadCredentialsException("Authentication.getCredentials() cannot be null");
|
||||||
|
}
|
||||||
|
Assertion assertion = this.ticketValidator.validate(credentials.toString(), getServiceUrl(authentication));
|
||||||
UserDetails userDetails = loadUserByAssertion(assertion);
|
UserDetails userDetails = loadUserByAssertion(assertion);
|
||||||
this.userDetailsChecker.check(userDetails);
|
this.userDetailsChecker.check(userDetails);
|
||||||
return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
|
return new CasAuthenticationToken(this.key, userDetails, credentials,
|
||||||
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
|
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
|
||||||
}
|
}
|
||||||
catch (TicketValidationException ex) {
|
catch (TicketValidationException ex) {
|
||||||
@ -149,7 +157,8 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
* @param authentication
|
* @param authentication
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private String getServiceUrl(Authentication authentication) {
|
@NullUnmarked
|
||||||
|
private @Nullable String getServiceUrl(Authentication authentication) {
|
||||||
String serviceUrl;
|
String serviceUrl;
|
||||||
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
|
||||||
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
|
return ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
|
||||||
@ -215,7 +224,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
|||||||
return this.statelessTicketCache;
|
return this.statelessTicketCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TicketValidator getTicketValidator() {
|
protected @Nullable TicketValidator getTicketValidator() {
|
||||||
return this.ticketValidator;
|
return this.ticketValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import org.apereo.cas.client.validation.Assertion;
|
|||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
@ -36,7 +35,7 @@ import org.springframework.util.ObjectUtils;
|
|||||||
*/
|
*/
|
||||||
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
private final Object credentials;
|
private final Object credentials;
|
||||||
|
|
||||||
|
@ -19,9 +19,10 @@ package org.springframework.security.cas.authentication;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,11 +39,11 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
|
static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_";
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
private final String identifier;
|
private final String identifier;
|
||||||
|
|
||||||
private Object credentials;
|
private @Nullable Object credentials;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor can be safely used by any code that wishes to create a
|
* This constructor can be safely used by any code that wishes to create a
|
||||||
@ -87,7 +88,7 @@ public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getCredentials() {
|
public @Nullable Object getCredentials() {
|
||||||
return this.credentials;
|
return this.credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
|
* Implementation of @link {@link StatelessTicketCache} that has no backing cache. Useful
|
||||||
* in instances where storing of tickets for stateless session management is not required.
|
* in instances where storing of tickets for stateless session management is not required.
|
||||||
@ -33,7 +35,7 @@ public final class NullStatelessTicketCache implements StatelessTicketCache {
|
|||||||
* @return null since we are not storing any tickets.
|
* @return null since we are not storing any tickets.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package org.springframework.security.cas.authentication;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
@ -42,7 +43,7 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
public @Nullable CasAuthenticationToken getByTicketId(final String serviceTicket) {
|
||||||
final Cache.ValueWrapper element = (serviceTicket != null) ? this.cache.get(serviceTicket) : null;
|
final Cache.ValueWrapper element = (serviceTicket != null) ? this.cache.get(serviceTicket) : null;
|
||||||
logger.debug(LogMessage.of(() -> "Cache hit: " + (element != null) + "; service ticket: " + serviceTicket));
|
logger.debug(LogMessage.of(() -> "Cache hit: " + (element != null) + "; service ticket: " + serviceTicket));
|
||||||
return (element != null) ? (CasAuthenticationToken) element.get() : null;
|
return (element != null) ? (CasAuthenticationToken) element.get() : null;
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches CAS service tickets and CAS proxy tickets for stateless connections.
|
* Caches CAS service tickets and CAS proxy tickets for stateless connections.
|
||||||
*
|
*
|
||||||
@ -69,7 +71,7 @@ public interface StatelessTicketCache {
|
|||||||
* </p>
|
* </p>
|
||||||
* @return the fully populated authentication token
|
* @return the fully populated authentication token
|
||||||
*/
|
*/
|
||||||
CasAuthenticationToken getByTicketId(String serviceTicket);
|
@Nullable CasAuthenticationToken getByTicketId(String serviceTicket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the specified <code>CasAuthenticationToken</code> to the cache.
|
* Adds the specified <code>CasAuthenticationToken</code> to the cache.
|
||||||
|
@ -18,4 +18,7 @@
|
|||||||
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
|
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
|
||||||
* tickets.
|
* tickets.
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jackson support for CAS.
|
||||||
|
*/
|
||||||
|
@NullMarked
|
||||||
|
package org.springframework.security.cas.jackson2;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
@ -18,4 +18,7 @@
|
|||||||
* Spring Security support for Apereo's Central Authentication Service
|
* Spring Security support for Apereo's Central Authentication Service
|
||||||
* (<a href="https://github.com/apereo/cas">CAS</a>).
|
* (<a href="https://github.com/apereo/cas">CAS</a>).
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
package org.springframework.security.cas;
|
package org.springframework.security.cas;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link org.springframework.security.core.userdetails.UserDetails} abstractions for CAS.
|
||||||
|
*/
|
||||||
|
@NullMarked
|
||||||
|
package org.springframework.security.cas.userdetails;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
@ -22,6 +22,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apereo.cas.client.util.CommonUtils;
|
import org.apereo.cas.client.util.CommonUtils;
|
||||||
import org.apereo.cas.client.util.WebUtils;
|
import org.apereo.cas.client.util.WebUtils;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
@ -47,9 +48,10 @@ import org.springframework.util.Assert;
|
|||||||
*/
|
*/
|
||||||
public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
|
public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
|
||||||
|
|
||||||
|
@SuppressWarnings("NullAway.Init")
|
||||||
private ServiceProperties serviceProperties;
|
private ServiceProperties serviceProperties;
|
||||||
|
|
||||||
private String loginUrl;
|
private @Nullable String loginUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the Service URL should include the session id for the specific
|
* Determines whether the Service URL should include the session id for the specific
|
||||||
@ -117,7 +119,7 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
|
|||||||
* <code>https://www.mycompany.com/cas/login</code>.
|
* <code>https://www.mycompany.com/cas/login</code>.
|
||||||
* @return the enterprise-wide CAS login URL
|
* @return the enterprise-wide CAS login URL
|
||||||
*/
|
*/
|
||||||
public final String getLoginUrl() {
|
public final @Nullable String getLoginUrl() {
|
||||||
return this.loginUrl;
|
return this.loginUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import jakarta.servlet.http.HttpSession;
|
|||||||
import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
|
import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||||
import org.apereo.cas.client.util.WebUtils;
|
import org.apereo.cas.client.util.WebUtils;
|
||||||
import org.apereo.cas.client.validation.TicketValidator;
|
import org.apereo.cas.client.validation.TicketValidator;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
@ -34,7 +35,7 @@ import org.springframework.security.authentication.AuthenticationTrustResolverIm
|
|||||||
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
import org.springframework.security.cas.authentication.CasServiceTicketAuthenticationToken;
|
import org.springframework.security.cas.authentication.CasServiceTicketAuthenticationToken;
|
||||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
|
import org.springframework.security.cas.authentication.ServiceAuthenticationDetails;
|
||||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource;
|
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
@ -51,12 +52,12 @@ import org.springframework.security.web.context.SecurityContextRepository;
|
|||||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||||
import org.springframework.security.web.savedrequest.RequestCache;
|
import org.springframework.security.web.savedrequest.RequestCache;
|
||||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy
|
* Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy
|
||||||
* tickets.
|
* tickets.
|
||||||
@ -190,12 +191,12 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
/**
|
/**
|
||||||
* The last portion of the receptor url, i.e. /proxy/receptor
|
* The last portion of the receptor url, i.e. /proxy/receptor
|
||||||
*/
|
*/
|
||||||
private RequestMatcher proxyReceptorMatcher;
|
private @Nullable RequestMatcher proxyReceptorMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The backing storage to store ProxyGrantingTicket requests.
|
* The backing storage to store ProxyGrantingTicket requests.
|
||||||
*/
|
*/
|
||||||
private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
|
private @Nullable ProxyGrantingTicketStorage proxyGrantingTicketStorage;
|
||||||
|
|
||||||
private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
|
private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
|
||||||
|
|
||||||
@ -216,7 +217,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
|
|
||||||
public CasAuthenticationFilter() {
|
public CasAuthenticationFilter() {
|
||||||
super("/login/cas");
|
super("/login/cas");
|
||||||
RequestMatcher processUri = PathPatternRequestMatcher.withDefaults().matcher("/login/cas");
|
RequestMatcher processUri = pathPattern("/login/cas");
|
||||||
setRequiresAuthenticationRequestMatcher(processUri);
|
setRequiresAuthenticationRequestMatcher(processUri);
|
||||||
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
|
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
|
||||||
setSecurityContextRepository(this.securityContextRepository);
|
setSecurityContextRepository(this.securityContextRepository);
|
||||||
@ -244,7 +245,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
public @Nullable Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws AuthenticationException, IOException {
|
throws AuthenticationException, IOException {
|
||||||
// if the request is a proxy request process it and return null to indicate the
|
// if the request is a proxy request process it and return null to indicate the
|
||||||
// request has been processed
|
// request has been processed
|
||||||
@ -335,7 +336,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
|
public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
|
||||||
this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl);
|
this.proxyReceptorMatcher = pathPattern(proxyReceptorUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
|
public final void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
|
||||||
@ -422,6 +423,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||||||
* @param request
|
* @param request
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("NullAway") // Dataflow analysis limitation
|
||||||
private boolean proxyReceptorRequest(HttpServletRequest request) {
|
private boolean proxyReceptorRequest(HttpServletRequest request) {
|
||||||
final boolean result = proxyReceptorConfigured() && this.proxyReceptorMatcher.matches(request);
|
final boolean result = proxyReceptorConfigured() && this.proxyReceptorMatcher.matches(request);
|
||||||
this.logger.debug(LogMessage.format("proxyReceptorRequest = %s", result));
|
this.logger.debug(LogMessage.format("proxyReceptorRequest = %s", result));
|
||||||
|
@ -21,7 +21,9 @@ import java.net.URL;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.security.cas.authentication.ServiceAuthenticationDetails;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||||
import org.springframework.security.web.util.UrlUtils;
|
import org.springframework.security.web.util.UrlUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -48,8 +50,8 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
* string from containing the artifact name and value. This can be created using
|
* string from containing the artifact name and value. This can be created using
|
||||||
* {@link #createArtifactPattern(String)}.
|
* {@link #createArtifactPattern(String)}.
|
||||||
*/
|
*/
|
||||||
DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, Pattern artifactPattern)
|
DefaultServiceAuthenticationDetails(@Nullable String casService, HttpServletRequest request,
|
||||||
throws MalformedURLException {
|
Pattern artifactPattern) throws MalformedURLException {
|
||||||
super(request);
|
super(request);
|
||||||
URL casServiceUrl = new URL(casService);
|
URL casServiceUrl = new URL(casService);
|
||||||
int port = getServicePort(casServiceUrl);
|
int port = getServicePort(casServiceUrl);
|
||||||
@ -60,7 +62,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current URL minus the artifact parameter and its value, if present.
|
* Returns the current URL minus the artifact parameter and its value, if present.
|
||||||
* @see org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails#getServiceUrl()
|
* @see org.springframework.security.cas.authentication.ServiceAuthenticationDetails#getServiceUrl()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getServiceUrl() {
|
public String getServiceUrl() {
|
||||||
@ -103,7 +105,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
|
|||||||
* @return the query String minus the artifactParameterName and the corresponding
|
* @return the query String minus the artifactParameterName and the corresponding
|
||||||
* value.
|
* value.
|
||||||
*/
|
*/
|
||||||
private String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
|
private @Nullable String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
|
||||||
final String query = request.getQueryString();
|
final String query = request.getQueryString();
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.cas.web.authentication;
|
|
||||||
|
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In order for the
|
|
||||||
* {@link org.springframework.security.cas.authentication.CasAuthenticationProvider} to
|
|
||||||
* provide the correct service url to authenticate the ticket, the returned value of
|
|
||||||
* {@link Authentication#getDetails()} should implement this interface when tickets can be
|
|
||||||
* sent to any URL rather than only {@link ServiceProperties#getService()}.
|
|
||||||
*
|
|
||||||
* @author Rob Winch
|
|
||||||
* @see ServiceAuthenticationDetailsSource
|
|
||||||
* @deprecated Please use
|
|
||||||
* org.springframework.security.cas.authentication.ServiceAuthenticationDetails
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface ServiceAuthenticationDetails
|
|
||||||
extends org.springframework.security.cas.authentication.ServiceAuthenticationDetails {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the absolute service url (i.e. https://example.com/service/).
|
|
||||||
* @return the service url. Cannot be <code>null</code>.
|
|
||||||
*/
|
|
||||||
String getServiceUrl();
|
|
||||||
|
|
||||||
}
|
|
@ -23,6 +23,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
|
import org.springframework.security.cas.authentication.ServiceAuthenticationDetails;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,4 +18,7 @@
|
|||||||
* Authentication processing mechanisms which respond to the submission of authentication
|
* Authentication processing mechanisms which respond to the submission of authentication
|
||||||
* credentials using CAS.
|
* credentials using CAS.
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
package org.springframework.security.cas.web.authentication;
|
package org.springframework.security.cas.web.authentication;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
@ -17,4 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* Authenticates standard web browser users via CAS.
|
* Authenticates standard web browser users via CAS.
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
package org.springframework.security.cas.web;
|
package org.springframework.security.cas.web;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
@ -30,7 +30,6 @@ import org.springframework.security.authentication.BadCredentialsException;
|
|||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
@ -43,7 +43,6 @@ import org.springframework.security.core.context.SecurityContextImpl;
|
|||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -55,6 +54,9 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.get;
|
||||||
|
import static org.springframework.security.web.servlet.TestMockHttpServletRequests.post;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link CasAuthenticationFilter}.
|
* Tests {@link CasAuthenticationFilter}.
|
||||||
@ -79,9 +81,7 @@ public class CasAuthenticationFilterTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNormalOperation() throws Exception {
|
public void testNormalOperation() throws Exception {
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/login/cas");
|
MockHttpServletRequest request = post("/login/cas").param("ticket", "ST-0-ER94xMJmn6pha35CQRoZ").build();
|
||||||
request.setServletPath("/login/cas");
|
|
||||||
request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ");
|
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
filter.setAuthenticationManager((a) -> a);
|
filter.setAuthenticationManager((a) -> a);
|
||||||
assertThat(filter.requiresAuthentication(request, new MockHttpServletResponse())).isTrue();
|
assertThat(filter.requiresAuthentication(request, new MockHttpServletResponse())).isTrue();
|
||||||
@ -104,24 +104,22 @@ public class CasAuthenticationFilterTests {
|
|||||||
String url = "/login/cas";
|
String url = "/login/cas";
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
filter.setFilterProcessesUrl(url);
|
filter.setFilterProcessesUrl(url);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", url);
|
MockHttpServletRequest request = post(url).build();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
request.setServletPath(url);
|
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRequiresAuthenticationProxyRequest() {
|
public void testRequiresAuthenticationProxyRequest() {
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = get("/pgtCallback").build();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
request.setServletPath("/pgtCallback");
|
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
filter.setProxyReceptorUrl(request.getServletPath());
|
filter.setProxyReceptorUrl(request.getServletPath());
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||||
request.setServletPath("/other");
|
request = get("/other").build();
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,12 +131,10 @@ public class CasAuthenticationFilterTests {
|
|||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
filter.setFilterProcessesUrl(url);
|
filter.setFilterProcessesUrl(url);
|
||||||
filter.setServiceProperties(properties);
|
filter.setServiceProperties(properties);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", url);
|
MockHttpServletRequest request = post(url).build();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
request.setServletPath(url);
|
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||||
request = new MockHttpServletRequest("POST", "/other");
|
request = post("/other").build();
|
||||||
request.setServletPath("/other");
|
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
request.setParameter(properties.getArtifactParameter(), "value");
|
request.setParameter(properties.getArtifactParameter(), "value");
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||||
@ -156,9 +152,8 @@ public class CasAuthenticationFilterTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testAuthenticateProxyUrl() throws Exception {
|
public void testAuthenticateProxyUrl() throws Exception {
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = get("/pgtCallback").build();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
request.setServletPath("/pgtCallback");
|
|
||||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||||
filter.setProxyReceptorUrl(request.getServletPath());
|
filter.setProxyReceptorUrl(request.getServletPath());
|
||||||
assertThat(filter.attemptAuthentication(request, response)).isNull();
|
assertThat(filter.attemptAuthentication(request, response)).isNull();
|
||||||
@ -172,9 +167,7 @@ public class CasAuthenticationFilterTests {
|
|||||||
given(manager.authenticate(any(Authentication.class))).willReturn(authentication);
|
given(manager.authenticate(any(Authentication.class))).willReturn(authentication);
|
||||||
ServiceProperties serviceProperties = new ServiceProperties();
|
ServiceProperties serviceProperties = new ServiceProperties();
|
||||||
serviceProperties.setAuthenticateAllArtifacts(true);
|
serviceProperties.setAuthenticateAllArtifacts(true);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/authenticate");
|
MockHttpServletRequest request = post("/authenticate").param("ticket", "ST-1-123").build();
|
||||||
request.setParameter("ticket", "ST-1-123");
|
|
||||||
request.setServletPath("/authenticate");
|
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
FilterChain chain = mock(FilterChain.class);
|
FilterChain chain = mock(FilterChain.class);
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
@ -200,10 +193,9 @@ public class CasAuthenticationFilterTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testChainNotInvokedForProxyReceptor() throws Exception {
|
public void testChainNotInvokedForProxyReceptor() throws Exception {
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = get("/pgtCallback").build();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
FilterChain chain = mock(FilterChain.class);
|
FilterChain chain = mock(FilterChain.class);
|
||||||
request.setServletPath("/pgtCallback");
|
|
||||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||||
filter.setProxyReceptorUrl(request.getServletPath());
|
filter.setProxyReceptorUrl(request.getServletPath());
|
||||||
filter.doFilter(request, response, chain);
|
filter.doFilter(request, response, chain);
|
||||||
@ -271,16 +263,14 @@ public class CasAuthenticationFilterTests {
|
|||||||
@Test
|
@Test
|
||||||
public void requiresAuthenticationWhenProxyRequestMatcherThenMatches() {
|
public void requiresAuthenticationWhenProxyRequestMatcherThenMatches() {
|
||||||
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
CasAuthenticationFilter filter = new CasAuthenticationFilter();
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/pgtCallback");
|
MockHttpServletRequest request = get("/pgtCallback").build();
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
request.setServletPath("/pgtCallback");
|
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
filter.setProxyReceptorMatcher(PathPatternRequestMatcher.withDefaults().matcher(request.getServletPath()));
|
filter.setProxyReceptorMatcher(pathPattern(request.getServletPath()));
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
assertThat(filter.requiresAuthentication(request, response)).isTrue();
|
||||||
request.setRequestURI("/other");
|
request = get("/other").build();
|
||||||
request.setServletPath("/other");
|
|
||||||
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
assertThat(filter.requiresAuthentication(request, response)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
|||||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
|
import org.springframework.security.cas.authentication.ServiceAuthenticationDetails;
|
||||||
import org.springframework.security.web.util.UrlUtils;
|
import org.springframework.security.web.util.UrlUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -4,7 +4,7 @@ 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: 'kotlin'
|
apply plugin: 'security-kotlin'
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
opensaml5 {
|
opensaml5 {
|
||||||
@ -25,12 +25,12 @@ dependencies {
|
|||||||
optional project(':spring-security-ldap')
|
optional project(':spring-security-ldap')
|
||||||
optional project(':spring-security-messaging')
|
optional project(':spring-security-messaging')
|
||||||
optional project(path: ':spring-security-saml2-service-provider')
|
optional project(path: ':spring-security-saml2-service-provider')
|
||||||
opensaml5 project(path: ':spring-security-saml2-service-provider', configuration: 'opensamlFiveMain')
|
|
||||||
optional project(':spring-security-oauth2-client')
|
optional project(':spring-security-oauth2-client')
|
||||||
optional project(':spring-security-oauth2-jose')
|
optional project(':spring-security-oauth2-jose')
|
||||||
optional project(':spring-security-oauth2-resource-server')
|
optional project(':spring-security-oauth2-resource-server')
|
||||||
optional project(':spring-security-rsocket')
|
optional project(':spring-security-rsocket')
|
||||||
optional project(':spring-security-web')
|
optional project(':spring-security-web')
|
||||||
|
optional project(':spring-security-webauthn')
|
||||||
optional 'io.projectreactor:reactor-core'
|
optional 'io.projectreactor:reactor-core'
|
||||||
optional 'org.aspectj:aspectjweaver'
|
optional 'org.aspectj:aspectjweaver'
|
||||||
optional 'org.springframework:spring-jdbc'
|
optional 'org.springframework:spring-jdbc'
|
||||||
@ -43,7 +43,6 @@ dependencies {
|
|||||||
optional 'org.jetbrains.kotlin:kotlin-reflect'
|
optional 'org.jetbrains.kotlin:kotlin-reflect'
|
||||||
optional 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
optional 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||||
optional 'jakarta.annotation:jakarta.annotation-api'
|
optional 'jakarta.annotation:jakarta.annotation-api'
|
||||||
optional libs.webauthn4j.core
|
|
||||||
|
|
||||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||||
|
|
||||||
@ -57,6 +56,7 @@ dependencies {
|
|||||||
testImplementation project(':spring-security-saml2-service-provider')
|
testImplementation project(':spring-security-saml2-service-provider')
|
||||||
testImplementation project(path : ':spring-security-saml2-service-provider', configuration : 'tests')
|
testImplementation project(path : ':spring-security-saml2-service-provider', configuration : 'tests')
|
||||||
testImplementation project(path : ':spring-security-web', configuration : 'tests')
|
testImplementation project(path : ':spring-security-web', configuration : 'tests')
|
||||||
|
testImplementation project(path : ':spring-security-webauthn', configuration : 'tests')
|
||||||
testImplementation "jakarta.inject:jakarta.inject-api"
|
testImplementation "jakarta.inject:jakarta.inject-api"
|
||||||
testImplementation "org.assertj:assertj-core"
|
testImplementation "org.assertj:assertj-core"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||||
@ -78,12 +78,6 @@ dependencies {
|
|||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
exclude group: 'xml-apis', module: 'xml-apis'
|
exclude group: 'xml-apis', module: 'xml-apis'
|
||||||
}
|
}
|
||||||
testImplementation "org.apache.directory.server:apacheds-core"
|
|
||||||
testImplementation "org.apache.directory.server:apacheds-core-entry"
|
|
||||||
testImplementation "org.apache.directory.server:apacheds-protocol-shared"
|
|
||||||
testImplementation "org.apache.directory.server:apacheds-protocol-ldap"
|
|
||||||
testImplementation "org.apache.directory.server:apacheds-server-jndi"
|
|
||||||
testImplementation 'org.apache.directory.shared:shared-ldap'
|
|
||||||
testImplementation "com.unboundid:unboundid-ldapsdk"
|
testImplementation "com.unboundid:unboundid-ldapsdk"
|
||||||
testImplementation 'jakarta.persistence:jakarta.persistence-api'
|
testImplementation 'jakarta.persistence:jakarta.persistence-api'
|
||||||
testImplementation "org.hibernate.orm:hibernate-core"
|
testImplementation "org.hibernate.orm:hibernate-core"
|
||||||
@ -127,6 +121,7 @@ dependencies {
|
|||||||
|
|
||||||
testRuntimeOnly 'org.hsqldb:hsqldb'
|
testRuntimeOnly 'org.hsqldb:hsqldb'
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
|
||||||
}
|
}
|
||||||
|
|
||||||
def rncToXsd = tasks.named('rncToXsd', RncToXsd)
|
def rncToXsd = tasks.named('rncToXsd', RncToXsd)
|
||||||
@ -158,15 +153,6 @@ tasks.named('sourcesJar', Jar).configure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(KotlinCompile).configureEach {
|
|
||||||
kotlinOptions {
|
|
||||||
languageVersion = "1.7"
|
|
||||||
apiVersion = "1.7"
|
|
||||||
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings"]
|
|
||||||
jvmTarget = "17"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configure(project.tasks.withType(Test)) {
|
configure(project.tasks.withType(Test)) {
|
||||||
doFirst {
|
doFirst {
|
||||||
systemProperties['springSecurityVersion'] = version
|
systemProperties['springSecurityVersion'] = version
|
||||||
@ -183,15 +169,3 @@ test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("opensaml5Test", Test) {
|
|
||||||
filter {
|
|
||||||
includeTestsMatching "org.springframework.security.config.annotation.web.configurers.saml2.*"
|
|
||||||
}
|
|
||||||
useJUnitPlatform()
|
|
||||||
classpath = sourceSets.main.output + sourceSets.test.output + configurations.opensaml5
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named("check") {
|
|
||||||
dependsOn opensaml5Test
|
|
||||||
}
|
|
||||||
|
@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.authentication.ldap;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.naming.directory.SearchControls;
|
import javax.naming.directory.SearchControls;
|
||||||
@ -39,12 +38,11 @@ import org.springframework.security.config.annotation.configuration.ObjectPostPr
|
|||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
|
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
|
||||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
@ -120,8 +118,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
|||||||
this.spring.register(BindAuthenticationConfig.class).autowire();
|
this.spring.register(BindAuthenticationConfig.class).autowire();
|
||||||
|
|
||||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||||
.andExpect(authenticated().withUsername("bob")
|
.andExpect(authenticated().withUsername("bob").withRoles("DEVELOPERS"));
|
||||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEC-2472
|
// SEC-2472
|
||||||
@ -130,8 +127,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
|||||||
this.spring.register(PasswordEncoderConfig.class).autowire();
|
this.spring.register(PasswordEncoderConfig.class).autowire();
|
||||||
|
|
||||||
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
|
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
|
||||||
.andExpect(authenticated().withUsername("bcrypt")
|
.andExpect(authenticated().withUsername("bcrypt").withRoles("DEVELOPERS"));
|
||||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LdapAuthenticationProvider ldapProvider() {
|
private LdapAuthenticationProvider ldapProvider() {
|
||||||
@ -326,11 +322,11 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests {
|
|||||||
abstract static class BaseLdapServerConfig extends BaseLdapProviderConfig {
|
abstract static class BaseLdapServerConfig extends BaseLdapProviderConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ApacheDSContainer ldapServer() throws Exception {
|
UnboundIdContainer ldapServer() throws Exception {
|
||||||
ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org",
|
UnboundIdContainer unboundIdContainer = new UnboundIdContainer("dc=springframework,dc=org",
|
||||||
"classpath:/test-server.ldif");
|
"classpath:/test-server.ldif");
|
||||||
apacheDSContainer.setPort(getPort());
|
unboundIdContainer.setPort(getPort());
|
||||||
return apacheDSContainer;
|
return unboundIdContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.authentication.ldap;
|
package org.springframework.security.config.annotation.authentication.ldap;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -28,8 +26,6 @@ import org.springframework.security.config.annotation.authentication.ldap.LdapAu
|
|||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
@ -64,7 +60,7 @@ public class LdapAuthenticationProviderConfigurerTests {
|
|||||||
.password("bobspassword");
|
.password("bobspassword");
|
||||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||||
.withUsername("bob")
|
.withUsername("bob")
|
||||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")));
|
.withRoles("DEVELOPERS");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||||
}
|
}
|
||||||
@ -79,7 +75,7 @@ public class LdapAuthenticationProviderConfigurerTests {
|
|||||||
.password("bobspassword");
|
.password("bobspassword");
|
||||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||||
.withUsername("bob")
|
.withUsername("bob")
|
||||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")));
|
.withRoles("ROL_", new String[] { "DEVELOPERS" });
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||||
}
|
}
|
||||||
@ -108,8 +104,7 @@ public class LdapAuthenticationProviderConfigurerTests {
|
|||||||
.password("otherbenspassword");
|
.password("otherbenspassword");
|
||||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated()
|
||||||
.withUsername("otherben")
|
.withUsername("otherben")
|
||||||
.withAuthorities(
|
.withRoles("SUBMANAGERS", "MANAGERS", "DEVELOPERS");
|
||||||
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS"));
|
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.authentication.ldap;
|
package org.springframework.security.config.annotation.authentication.ldap;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -34,7 +33,6 @@ import org.springframework.security.config.test.SpringTestContext;
|
|||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||||
@ -79,7 +77,7 @@ public class NamespaceLdapAuthenticationProviderTests {
|
|||||||
.user("bob")
|
.user("bob")
|
||||||
.password("bobspassword");
|
.password("bobspassword");
|
||||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
||||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")));
|
.withRoles("PREFIX_", new String[] { "DEVELOPERS" });
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
this.mockMvc.perform(request).andExpect(user);
|
this.mockMvc.perform(request).andExpect(user);
|
||||||
}
|
}
|
||||||
@ -103,7 +101,7 @@ public class NamespaceLdapAuthenticationProviderTests {
|
|||||||
.user("bob")
|
.user("bob")
|
||||||
.password("bobspassword");
|
.password("bobspassword");
|
||||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
||||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")));
|
.withRoles("EXTRA");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
this.mockMvc.perform(request).andExpect(user);
|
this.mockMvc.perform(request).andExpect(user);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.config.annotation.rsocket;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.rsocket.core.RSocketServer;
|
||||||
|
import io.rsocket.exceptions.RejectedSetupException;
|
||||||
|
import io.rsocket.frame.decoder.PayloadDecoder;
|
||||||
|
import io.rsocket.transport.netty.server.CloseableChannel;
|
||||||
|
import io.rsocket.transport.netty.server.TcpServerTransport;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||||
|
import org.springframework.messaging.rsocket.RSocketRequester;
|
||||||
|
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
|
||||||
|
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||||
|
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||||
|
import org.springframework.security.authorization.AuthorizationDecision;
|
||||||
|
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||||
|
import org.springframework.security.rsocket.core.PayloadSocketAcceptorInterceptor;
|
||||||
|
import org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor;
|
||||||
|
import org.springframework.security.rsocket.util.matcher.PayloadExchangeAuthorizationContext;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrey Litvitski
|
||||||
|
*/
|
||||||
|
@ContextConfiguration
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
public class AnonymousAuthenticationITests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RSocketMessageHandler handler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
SecuritySocketAcceptorInterceptor interceptor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ServerController controller;
|
||||||
|
|
||||||
|
private CloseableChannel server;
|
||||||
|
|
||||||
|
private RSocketRequester requester;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
// @formatter:off
|
||||||
|
this.server = RSocketServer.create()
|
||||||
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
|
)
|
||||||
|
.acceptor(this.handler.responder())
|
||||||
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
.block();
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void dispose() {
|
||||||
|
this.requester.rsocket().dispose();
|
||||||
|
this.server.dispose();
|
||||||
|
this.controller.payloads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestWhenAnonymousDisabledThenRespondsWithForbidden() {
|
||||||
|
this.requester = RSocketRequester.builder()
|
||||||
|
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||||
|
.connectTcp("localhost", this.server.address().getPort())
|
||||||
|
.block();
|
||||||
|
String data = "andrew";
|
||||||
|
assertThatExceptionOfType(RejectedSetupException.class).isThrownBy(
|
||||||
|
() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block());
|
||||||
|
assertThat(this.controller.payloads).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableRSocketSecurity
|
||||||
|
static class Config {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ServerController controller() {
|
||||||
|
return new ServerController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
RSocketMessageHandler messageHandler() {
|
||||||
|
return new RSocketMessageHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||||
|
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||||
|
ReactiveAuthorizationManager<PayloadExchangeAuthorizationContext> anonymous = (authentication,
|
||||||
|
exchange) -> authentication.map(trustResolver::isAnonymous).map(AuthorizationDecision::new);
|
||||||
|
rsocket.authorizePayload((authorize) -> authorize.anyExchange().access(anonymous));
|
||||||
|
rsocket.anonymous((anonymousAuthentication) -> anonymousAuthentication.disable());
|
||||||
|
return rsocket.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
static class ServerController {
|
||||||
|
|
||||||
|
private List<String> payloads = new ArrayList<>();
|
||||||
|
|
||||||
|
@MessageMapping("**")
|
||||||
|
String retrieveMono(String payload) {
|
||||||
|
add(payload);
|
||||||
|
return "Hi " + payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add(String p) {
|
||||||
|
this.payloads.add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -74,8 +74,7 @@ public class HelloRSocketITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -87,8 +87,7 @@ public class HelloRSocketObservationITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -74,8 +74,7 @@ public class HelloRSocketWithWebFluxITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -86,8 +86,7 @@ public class JwtITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -81,8 +81,7 @@ public class RSocketMessageHandlerConnectionITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -79,8 +79,7 @@ public class RSocketMessageHandlerITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -79,8 +79,7 @@ public class SimpleAuthenticationITests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.server = RSocketServer.create()
|
this.server = RSocketServer.create()
|
||||||
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
.payloadDecoder(PayloadDecoder.ZERO_COPY)
|
||||||
.interceptors((registry) ->
|
.interceptors((registry) -> registry.forSocketAcceptor(this.interceptor)
|
||||||
registry.forSocketAcceptor(this.interceptor)
|
|
||||||
)
|
)
|
||||||
.acceptor(this.handler.responder())
|
.acceptor(this.handler.responder())
|
||||||
.bind(TcpServerTransport.create("localhost", 0))
|
.bind(TcpServerTransport.create("localhost", 0))
|
||||||
|
@ -43,7 +43,7 @@ import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMap
|
|||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||||
@ -226,18 +226,18 @@ public class LdapBindAuthenticationManagerFactoryITests {
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
abstract static class BaseLdapServerConfig implements DisposableBean {
|
abstract static class BaseLdapServerConfig implements DisposableBean {
|
||||||
|
|
||||||
private ApacheDSContainer container;
|
private UnboundIdContainer container;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ApacheDSContainer ldapServer() throws Exception {
|
UnboundIdContainer ldapServer() {
|
||||||
this.container = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
this.container = new UnboundIdContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
||||||
this.container.setPort(0);
|
this.container.setPort(0);
|
||||||
return this.container;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
BaseLdapPathContextSource contextSource(ApacheDSContainer container) {
|
BaseLdapPathContextSource contextSource(UnboundIdContainer container) {
|
||||||
int port = container.getLocalPort();
|
int port = container.getPort();
|
||||||
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import org.springframework.security.config.test.SpringTestContextExtension;
|
|||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||||
@ -93,18 +93,18 @@ public class LdapPasswordComparisonAuthenticationManagerFactoryITests {
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
abstract static class BaseLdapServerConfig implements DisposableBean {
|
abstract static class BaseLdapServerConfig implements DisposableBean {
|
||||||
|
|
||||||
private ApacheDSContainer container;
|
private UnboundIdContainer container;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ApacheDSContainer ldapServer() throws Exception {
|
UnboundIdContainer ldapServer() {
|
||||||
this.container = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
this.container = new UnboundIdContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
|
||||||
this.container.setPort(0);
|
this.container.setPort(0);
|
||||||
return this.container;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
BaseLdapPathContextSource contextSource(ApacheDSContainer container) {
|
BaseLdapPathContextSource contextSource(UnboundIdContainer container) {
|
||||||
int port = container.getLocalPort();
|
int port = container.getPort();
|
||||||
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
return new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public class LdapProviderBeanDefinitionParserTests {
|
|||||||
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||||
AuthenticationManager.class);
|
AuthenticationManager.class);
|
||||||
Authentication auth = authenticationManager
|
Authentication auth = authenticationManager
|
||||||
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("ben", "benspassword"));
|
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("otherben", "otherbenspassword"));
|
||||||
UserDetails ben = (UserDetails) auth.getPrincipal();
|
UserDetails ben = (UserDetails) auth.getPrincipal();
|
||||||
assertThat(ben.getAuthorities()).hasSize(3);
|
assertThat(ben.getAuthorities()).hasSize(3);
|
||||||
}
|
}
|
||||||
@ -127,6 +127,27 @@ public class LdapProviderBeanDefinitionParserTests {
|
|||||||
assertThat(auth).isNotNull();
|
assertThat(auth).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void supportsShaPasswordEncoder() {
|
||||||
|
this.appCtx = new InMemoryXmlApplicationContext("""
|
||||||
|
<ldap-server ldif='classpath:test-server.ldif' port='0'/>
|
||||||
|
<authentication-manager>
|
||||||
|
<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>
|
||||||
|
<password-compare>
|
||||||
|
<password-encoder ref='pe' />
|
||||||
|
</password-compare>
|
||||||
|
</ldap-authentication-provider>
|
||||||
|
</authentication-manager>
|
||||||
|
<b:bean id='pe' class='org.springframework.security.crypto.password.LdapShaPasswordEncoder' />
|
||||||
|
""");
|
||||||
|
AuthenticationManager authenticationManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER,
|
||||||
|
AuthenticationManager.class);
|
||||||
|
Authentication auth = authenticationManager
|
||||||
|
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated("ben", "benspassword"));
|
||||||
|
|
||||||
|
assertThat(auth).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void inetOrgContextMapperIsSupported() {
|
public void inetOrgContextMapperIsSupported() {
|
||||||
this.appCtx = new InMemoryXmlApplicationContext(
|
this.appCtx = new InMemoryXmlApplicationContext(
|
||||||
@ -148,7 +169,7 @@ public class LdapProviderBeanDefinitionParserTests {
|
|||||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server />" + "<authentication-manager>"
|
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server />" + "<authentication-manager>"
|
||||||
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=${udp}' group-search-filter='${gsf}={0}' />"
|
+ " <ldap-authentication-provider user-dn-pattern='uid={0},ou=${udp}' group-search-filter='${gsf}={0}' />"
|
||||||
+ "</authentication-manager>"
|
+ "</authentication-manager>"
|
||||||
+ "<b:bean id='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' />");
|
+ "<b:bean id='org.springframework.context.support.PropertySourcesPlaceholderConfigurer' class='org.springframework.context.support.PropertySourcesPlaceholderConfigurer' />");
|
||||||
|
|
||||||
ProviderManager providerManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
ProviderManager providerManager = this.appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class);
|
||||||
assertThat(providerManager.getProviders()).hasSize(1);
|
assertThat(providerManager.getProviders()).hasSize(1);
|
||||||
|
@ -26,7 +26,7 @@ import org.springframework.ldap.core.LdapTemplate;
|
|||||||
import org.springframework.security.config.BeanIds;
|
import org.springframework.security.config.BeanIds;
|
||||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -92,9 +92,9 @@ public class LdapServerBeanDefinitionParserTests {
|
|||||||
@Test
|
@Test
|
||||||
public void defaultLdifFileIsSuccessful() {
|
public void defaultLdifFileIsSuccessful() {
|
||||||
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server/>");
|
this.appCtx = new InMemoryXmlApplicationContext("<ldap-server/>");
|
||||||
ApacheDSContainer dsContainer = this.appCtx.getBean(ApacheDSContainer.class);
|
UnboundIdContainer dsContainer = this.appCtx.getBean(UnboundIdContainer.class);
|
||||||
|
|
||||||
assertThat(ReflectionTestUtils.getField(dsContainer, "ldifResources")).isEqualTo("classpath*:*.ldif");
|
assertThat(ReflectionTestUtils.getField(dsContainer, "ldif")).isEqualTo("classpath*:*.ldif");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getDefaultPort() throws IOException {
|
private int getDefaultPort() throws IOException {
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
||||||
|
|
||||||
<logger name="org.apache.directory" level="ERROR"/>
|
|
||||||
<logger name="JdbmTable" level="INFO"/>
|
<logger name="JdbmTable" level="INFO"/>
|
||||||
<logger name="JdbmIndex" level="INFO"/>
|
<logger name="JdbmIndex" level="INFO"/>
|
||||||
<logger name="org.apache.mina" level="WARN"/>
|
<logger name="org.apache.mina" level="WARN"/>
|
||||||
|
@ -54,8 +54,6 @@ public abstract class BeanIds {
|
|||||||
|
|
||||||
public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor";
|
public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor";
|
||||||
|
|
||||||
public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer";
|
|
||||||
|
|
||||||
public static final String EMBEDDED_UNBOUNDID = PREFIX + "unboundidServerContainer";
|
public static final String EMBEDDED_UNBOUNDID = PREFIX + "unboundidServerContainer";
|
||||||
|
|
||||||
public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource";
|
public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource";
|
||||||
|
@ -18,6 +18,7 @@ package org.springframework.security.config;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@ -77,26 +78,23 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
|
|||||||
|
|
||||||
public SecurityNamespaceHandler() {
|
public SecurityNamespaceHandler() {
|
||||||
String coreVersion = SpringSecurityCoreVersion.getVersion();
|
String coreVersion = SpringSecurityCoreVersion.getVersion();
|
||||||
|
String configVersion = configVersion();
|
||||||
|
if (!Objects.equals(coreVersion, configVersion)) {
|
||||||
|
String message = "You are attempting to run spring-security-core:%s with spring-security-config:%s";
|
||||||
|
this.logger.error(String.format(message, coreVersion, configVersion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String configVersion() {
|
||||||
Package pkg = SpringSecurityCoreVersion.class.getPackage();
|
Package pkg = SpringSecurityCoreVersion.class.getPackage();
|
||||||
if (pkg == null || coreVersion == null) {
|
return (pkg != null) ? pkg.getImplementationVersion() : null;
|
||||||
this.logger.info("Couldn't determine package version information.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String version = pkg.getImplementationVersion();
|
|
||||||
this.logger.info("Spring Security 'config' module version is " + version);
|
|
||||||
if (version.compareTo(coreVersion) != 0) {
|
|
||||||
this.logger
|
|
||||||
.error("You are running with different versions of the Spring Security 'core' and 'config' modules");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
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 a spring-security-2.0.xsd or spring-security-3.0.xsd or "
|
.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",
|
||||||
+ "spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
|
|
||||||
+ "with Spring Security 6.5. Please update your schema declarations to the 6.5 schema.",
|
|
||||||
element);
|
element);
|
||||||
}
|
}
|
||||||
String name = pc.getDelegate().getLocalName(element);
|
String name = pc.getDelegate().getLocalName(element);
|
||||||
@ -221,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-6\\.5.*.xsd.*")
|
return schemaLocation.matches("(?m).*spring-security-7\\.0.*.xsd.*")
|
||||||
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
|| schemaLocation.matches("(?m).*spring-security.xsd.*")
|
||||||
|| !schemaLocation.matches("(?m).*spring-security.*");
|
|| !schemaLocation.matches("(?m).*spring-security.*");
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Customizer} that allows invocation of code that throws a checked exception.
|
||||||
|
*
|
||||||
|
* @param <T> The type of input.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ThrowingCustomizer<T> extends Customizer<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default {@link Customizer#customize(Object)} that wraps any thrown checked
|
||||||
|
* exceptions (by default in a {@link RuntimeException}).
|
||||||
|
* @param t the object to customize
|
||||||
|
*/
|
||||||
|
default void customize(T t) {
|
||||||
|
try {
|
||||||
|
customizeWithException(t);
|
||||||
|
}
|
||||||
|
catch (RuntimeException ex) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the customization on the given object, possibly throwing a checked
|
||||||
|
* exception.
|
||||||
|
* @param t the object to customize
|
||||||
|
* @throws Exception on error
|
||||||
|
*/
|
||||||
|
void customizeWithException(T t) throws Exception;
|
||||||
|
|
||||||
|
}
|
@ -80,15 +80,6 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||||||
this(objectPostProcessor, false);
|
this(objectPostProcessor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
protected AbstractConfiguredSecurityBuilder(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<Object> objectPostProcessor) {
|
|
||||||
this(objectPostProcessor, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Creates a new instance with the provided {@link ObjectPostProcessor}. This post
|
* Creates a new instance with the provided {@link ObjectPostProcessor}. This post
|
||||||
* processor must support Object since there are many types of objects that may be
|
* processor must support Object since there are many types of objects that may be
|
||||||
@ -104,18 +95,6 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||||||
this.allowConfigurersOfSameType = allowConfigurersOfSameType;
|
this.allowConfigurersOfSameType = allowConfigurersOfSameType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
protected AbstractConfiguredSecurityBuilder(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<Object> objectPostProcessor,
|
|
||||||
boolean allowConfigurersOfSameType) {
|
|
||||||
Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null");
|
|
||||||
this.objectPostProcessor = objectPostProcessor;
|
|
||||||
this.allowConfigurersOfSameType = allowConfigurersOfSameType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link #build()} and {@link #getObject()} but checks the state to
|
* Similar to {@link #build()} and {@link #getObject()} but checks the state to
|
||||||
* determine if {@link #build()} needs to be called first.
|
* determine if {@link #build()} needs to be called first.
|
||||||
@ -135,24 +114,6 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies a {@link SecurityConfigurerAdapter} to this {@link SecurityBuilder} and
|
|
||||||
* invokes {@link SecurityConfigurerAdapter#setBuilder(SecurityBuilder)}.
|
|
||||||
* @param configurer
|
|
||||||
* @return the {@link SecurityConfigurerAdapter} for further customizations
|
|
||||||
* @throws Exception
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link #with(SecurityConfigurerAdapter, Customizer)} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.2", forRemoval = true)
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception {
|
|
||||||
configurer.addObjectPostProcessor(this.objectPostProcessor);
|
|
||||||
configurer.setBuilder((B) this);
|
|
||||||
add(configurer);
|
|
||||||
return configurer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a {@link SecurityConfigurer} to this {@link SecurityBuilder} overriding any
|
* Applies a {@link SecurityConfigurer} to this {@link SecurityBuilder} overriding any
|
||||||
* {@link SecurityConfigurer} of the exact same class. Note that object hierarchies
|
* {@link SecurityConfigurer} of the exact same class. Note that object hierarchies
|
||||||
@ -166,6 +127,28 @@ public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBui
|
|||||||
return configurer;
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a {@link SecurityConfigurerAdapter} to this {@link SecurityBuilder} and
|
||||||
|
* invokes {@link SecurityConfigurerAdapter#setBuilder(SecurityBuilder)}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* A shortcut for applying a configurer as-is, or in other words: <code>
|
||||||
|
* .with(new MyConfigurer())
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Is identical to: <code>
|
||||||
|
* .with(new MyConfigurer(), Customizer.withDefaults())
|
||||||
|
* </code>
|
||||||
|
* @param configurer
|
||||||
|
* @return the {@link SecurityBuilder} for further customizations
|
||||||
|
* @throws Exception
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
public <C extends SecurityConfigurerAdapter<O, B>> B with(C configurer) throws Exception {
|
||||||
|
return with(configurer, Customizer.withDefaults());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a {@link SecurityConfigurerAdapter} to this {@link SecurityBuilder} and
|
* Applies a {@link SecurityConfigurerAdapter} to this {@link SecurityBuilder} and
|
||||||
* invokes {@link SecurityConfigurerAdapter#setBuilder(SecurityBuilder)}.
|
* invokes {@link SecurityConfigurerAdapter#setBuilder(SecurityBuilder)}.
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.config.annotation;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.Aware;
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows initialization of Objects. Typically this is used to call the {@link Aware}
|
|
||||||
* methods, {@link InitializingBean#afterPropertiesSet()}, and ensure that
|
|
||||||
* {@link DisposableBean#destroy()} has been invoked.
|
|
||||||
*
|
|
||||||
* @param <T> the bound of the types of Objects this {@link ObjectPostProcessor} supports.
|
|
||||||
* @author Rob Winch
|
|
||||||
* @since 3.2
|
|
||||||
* @deprecated please use {@link org.springframework.security.config.ObjectPostProcessor}
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface ObjectPostProcessor<T> extends org.springframework.security.config.ObjectPostProcessor<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the object possibly returning a modified instance that should be used
|
|
||||||
* instead.
|
|
||||||
* @param object the object to initialize
|
|
||||||
* @return the initialized version of the object
|
|
||||||
*/
|
|
||||||
<O extends T> O postProcess(O object);
|
|
||||||
|
|
||||||
}
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -50,17 +51,6 @@ public abstract class SecurityConfigurerAdapter<O, B extends SecurityBuilder<O>>
|
|||||||
public void configure(B builder) throws Exception {
|
public void configure(B builder) throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the {@link SecurityBuilder} when done using the {@link SecurityConfigurer}.
|
|
||||||
* This is useful for method chaining.
|
|
||||||
* @return the {@link SecurityBuilder} for further customizations
|
|
||||||
* @deprecated For removal in 7.0. Use the lambda based configuration instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public B and() {
|
|
||||||
return getBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link SecurityBuilder}. Cannot be null.
|
* Gets the {@link SecurityBuilder}. Cannot be null.
|
||||||
* @return the {@link SecurityBuilder}
|
* @return the {@link SecurityBuilder}
|
||||||
@ -92,18 +82,9 @@ public abstract class SecurityConfigurerAdapter<O, B extends SecurityBuilder<O>>
|
|||||||
this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);
|
this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public void addObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link SecurityBuilder} to be used. This is automatically set when using
|
* Sets the {@link SecurityBuilder} to be used. This is automatically set when using
|
||||||
* {@link AbstractConfiguredSecurityBuilder#apply(SecurityConfigurerAdapter)}
|
* {@link AbstractConfiguredSecurityBuilder#with(SecurityConfigurerAdapter, Customizer)}
|
||||||
* @param builder the {@link SecurityBuilder} to set
|
* @param builder the {@link SecurityBuilder} to set
|
||||||
*/
|
*/
|
||||||
public void setBuilder(B builder) {
|
public void setBuilder(B builder) {
|
||||||
|
@ -73,15 +73,6 @@ public class AuthenticationManagerBuilder
|
|||||||
super(objectPostProcessor, true);
|
super(objectPostProcessor, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public AuthenticationManagerBuilder(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<Object> objectPostProcessor) {
|
|
||||||
super(objectPostProcessor, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows providing a parent {@link AuthenticationManager} that will be tried if this
|
* Allows providing a parent {@link AuthenticationManager} that will be tried if this
|
||||||
* {@link AuthenticationManager} was unable to attempt to authenticate the provided
|
* {@link AuthenticationManager} was unable to attempt to authenticate the provided
|
||||||
@ -204,7 +195,9 @@ public class AuthenticationManagerBuilder
|
|||||||
* @throws Exception if an error occurs when adding the LDAP authentication
|
* @throws Exception if an error occurs when adding the LDAP authentication
|
||||||
*/
|
*/
|
||||||
public LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthentication() throws Exception {
|
public LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthentication() throws Exception {
|
||||||
return apply(new LdapAuthenticationProviderConfigurer<>());
|
LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldap = new LdapAuthenticationProviderConfigurer<>();
|
||||||
|
with(ldap);
|
||||||
|
return ldap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -286,7 +279,8 @@ public class AuthenticationManagerBuilder
|
|||||||
private <C extends UserDetailsAwareConfigurer<AuthenticationManagerBuilder, ? extends UserDetailsService>> C apply(
|
private <C extends UserDetailsAwareConfigurer<AuthenticationManagerBuilder, ? extends UserDetailsService>> C apply(
|
||||||
C configurer) throws Exception {
|
C configurer) throws Exception {
|
||||||
this.defaultUserDetailsService = configurer.getUserDetailsService();
|
this.defaultUserDetailsService = configurer.getUserDetailsService();
|
||||||
return super.apply(configurer);
|
with(configurer);
|
||||||
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ import org.springframework.context.annotation.Import;
|
|||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link EnableGlobalAuthentication} annotation signals that the annotated class can
|
* The {@link EnableGlobalAuthentication} annotation signals that the annotated class can
|
||||||
@ -87,14 +86,12 @@ import org.springframework.security.config.annotation.web.servlet.configuration.
|
|||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link EnableWebSecurity}</li>
|
* <li>{@link EnableWebSecurity}</li>
|
||||||
* <li>{@link EnableWebMvcSecurity}</li>
|
|
||||||
* <li>{@link EnableGlobalMethodSecurity}</li>
|
* <li>{@link EnableGlobalMethodSecurity}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* Configuring {@link AuthenticationManagerBuilder} in a class without the
|
* Configuring {@link AuthenticationManagerBuilder} in a class without the
|
||||||
* {@link EnableGlobalAuthentication} annotation has unpredictable results.
|
* {@link EnableGlobalAuthentication} annotation has unpredictable results.
|
||||||
*
|
*
|
||||||
* @see EnableWebMvcSecurity
|
|
||||||
* @see EnableWebSecurity
|
* @see EnableWebSecurity
|
||||||
* @see EnableGlobalMethodSecurity
|
* @see EnableGlobalMethodSecurity
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
@ -37,7 +37,6 @@ import org.springframework.security.ldap.authentication.LdapAuthenticator;
|
|||||||
import org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator;
|
import org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator;
|
||||||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||||
import org.springframework.security.ldap.search.LdapUserSearch;
|
import org.springframework.security.ldap.search.LdapUserSearch;
|
||||||
import org.springframework.security.ldap.server.ApacheDSContainer;
|
|
||||||
import org.springframework.security.ldap.server.UnboundIdContainer;
|
import org.springframework.security.ldap.server.UnboundIdContainer;
|
||||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||||
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper;
|
import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper;
|
||||||
@ -60,12 +59,8 @@ import org.springframework.util.ClassUtils;
|
|||||||
public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuilder<B>>
|
public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuilder<B>>
|
||||||
extends SecurityConfigurerAdapter<AuthenticationManager, B> {
|
extends SecurityConfigurerAdapter<AuthenticationManager, B> {
|
||||||
|
|
||||||
private static final String APACHEDS_CLASSNAME = "org.apache.directory.server.core.DefaultDirectoryService";
|
|
||||||
|
|
||||||
private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
|
private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
|
||||||
|
|
||||||
private static final boolean apacheDsPresent;
|
|
||||||
|
|
||||||
private static final boolean unboundIdPresent;
|
private static final boolean unboundIdPresent;
|
||||||
|
|
||||||
private String groupRoleAttribute = "cn";
|
private String groupRoleAttribute = "cn";
|
||||||
@ -100,7 +95,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
ClassLoader classLoader = LdapAuthenticationProviderConfigurer.class.getClassLoader();
|
ClassLoader classLoader = LdapAuthenticationProviderConfigurer.class.getClassLoader();
|
||||||
apacheDsPresent = ClassUtils.isPresent(APACHEDS_CLASSNAME, classLoader);
|
|
||||||
unboundIdPresent = ClassUtils.isPresent(UNBOUNDID_CLASSNAME, classLoader);
|
unboundIdPresent = ClassUtils.isPresent(UNBOUNDID_CLASSNAME, classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,16 +133,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public LdapAuthenticationProviderConfigurer<B> withObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link LdapAuthoritiesPopulator} and defaults to
|
* Gets the {@link LdapAuthoritiesPopulator} and defaults to
|
||||||
* {@link DefaultLdapAuthoritiesPopulator}
|
* {@link DefaultLdapAuthoritiesPopulator}
|
||||||
@ -392,6 +376,10 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public B and() {
|
||||||
|
return getBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(B builder) throws Exception {
|
public void configure(B builder) throws Exception {
|
||||||
LdapAuthenticationProvider provider = postProcess(build());
|
LdapAuthenticationProvider provider = postProcess(build());
|
||||||
@ -467,8 +455,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||||||
*/
|
*/
|
||||||
public final class ContextSourceBuilder {
|
public final class ContextSourceBuilder {
|
||||||
|
|
||||||
private static final String APACHEDS_CLASSNAME = "org.apache.directory.server.core.DefaultDirectoryService";
|
|
||||||
|
|
||||||
private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
|
private static final String UNBOUNDID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
|
||||||
|
|
||||||
private static final int DEFAULT_PORT = 33389;
|
private static final int DEFAULT_PORT = 33389;
|
||||||
@ -584,14 +570,8 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
|
|||||||
return contextSource;
|
return contextSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startEmbeddedLdapServer() throws Exception {
|
private void startEmbeddedLdapServer() {
|
||||||
if (apacheDsPresent) {
|
if (unboundIdPresent) {
|
||||||
ApacheDSContainer apacheDsContainer = new ApacheDSContainer(this.root, this.ldif);
|
|
||||||
apacheDsContainer.setPort(getPort());
|
|
||||||
postProcess(apacheDsContainer);
|
|
||||||
this.port = apacheDsContainer.getLocalPort();
|
|
||||||
}
|
|
||||||
else if (unboundIdPresent) {
|
|
||||||
UnboundIdContainer unboundIdContainer = new UnboundIdContainer(this.root, this.ldif);
|
UnboundIdContainer unboundIdContainer = new UnboundIdContainer(this.root, this.ldif);
|
||||||
unboundIdContainer.setPort(getPort());
|
unboundIdContainer.setPort(getPort());
|
||||||
postProcess(unboundIdContainer);
|
postProcess(unboundIdContainer);
|
||||||
|
@ -41,4 +41,8 @@ public class InMemoryUserDetailsManagerConfigurer<B extends ProviderManagerBuild
|
|||||||
super(new InMemoryUserDetailsManager(new ArrayList<>()));
|
super(new InMemoryUserDetailsManager(new ArrayList<>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public B and() {
|
||||||
|
return getBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -63,17 +63,6 @@ public abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderMana
|
|||||||
return (C) this;
|
return (C) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public C withObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return (C) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows specifying the {@link PasswordEncoder} to use with the
|
* Allows specifying the {@link PasswordEncoder} to use with the
|
||||||
* {@link DaoAuthenticationProvider}. The default is to use plain text.
|
* {@link DaoAuthenticationProvider}. The default is to use plain text.
|
||||||
|
@ -16,13 +16,22 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
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.context.annotation.Role;
|
import org.springframework.context.annotation.Role;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.data.domain.PageImpl;
|
||||||
|
import org.springframework.data.domain.SliceImpl;
|
||||||
|
import org.springframework.data.geo.GeoPage;
|
||||||
|
import org.springframework.data.geo.GeoResult;
|
||||||
|
import org.springframework.data.geo.GeoResults;
|
||||||
import org.springframework.security.aot.hint.SecurityHintsRegistrar;
|
import org.springframework.security.aot.hint.SecurityHintsRegistrar;
|
||||||
import org.springframework.security.authorization.AuthorizationProxyFactory;
|
import org.springframework.security.authorization.AuthorizationProxyFactory;
|
||||||
|
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
|
||||||
import org.springframework.security.data.aot.hint.AuthorizeReturnObjectDataHintsRegistrar;
|
import org.springframework.security.data.aot.hint.AuthorizeReturnObjectDataHintsRegistrar;
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ -34,4 +43,45 @@ final class AuthorizationProxyDataConfiguration implements AopInfrastructureBean
|
|||||||
return new AuthorizeReturnObjectDataHintsRegistrar(proxyFactory);
|
return new AuthorizeReturnObjectDataHintsRegistrar(proxyFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
|
DataTargetVisitor dataTargetVisitor() {
|
||||||
|
return new DataTargetVisitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class DataTargetVisitor implements AuthorizationAdvisorProxyFactory.TargetVisitor, Ordered {
|
||||||
|
|
||||||
|
private static final int DEFAULT_ORDER = 200;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visit(AuthorizationAdvisorProxyFactory proxyFactory, Object target) {
|
||||||
|
if (target instanceof GeoResults<?> geoResults) {
|
||||||
|
return new GeoResults<>(proxyFactory.proxy(geoResults.getContent()), geoResults.getAverageDistance());
|
||||||
|
}
|
||||||
|
if (target instanceof GeoResult<?> geoResult) {
|
||||||
|
return new GeoResult<>(proxyFactory.proxy(geoResult.getContent()), geoResult.getDistance());
|
||||||
|
}
|
||||||
|
if (target instanceof GeoPage<?> geoPage) {
|
||||||
|
GeoResults<?> results = new GeoResults<>(proxyFactory.proxy(geoPage.getContent()),
|
||||||
|
geoPage.getAverageDistance());
|
||||||
|
return new GeoPage<>(results, geoPage.getPageable(), geoPage.getTotalElements());
|
||||||
|
}
|
||||||
|
if (target instanceof PageImpl<?> page) {
|
||||||
|
List<?> content = proxyFactory.proxy(page.getContent());
|
||||||
|
return new PageImpl<>(content, page.getPageable(), page.getTotalElements());
|
||||||
|
}
|
||||||
|
if (target instanceof SliceImpl<?> slice) {
|
||||||
|
List<?> content = proxyFactory.proxy(slice.getContent());
|
||||||
|
return new SliceImpl<>(content, slice.getPageable(), slice.hasNext());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return DEFAULT_ORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,12 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.method.configuration;
|
package org.springframework.security.config.annotation.method.configuration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -25,12 +29,17 @@ import org.springframework.context.annotation.Role;
|
|||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
|
import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
|
||||||
|
import org.springframework.security.web.util.ThrowableAnalyzer;
|
||||||
|
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.View;
|
import org.springframework.web.servlet.View;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
class AuthorizationProxyWebConfiguration {
|
class AuthorizationProxyWebConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
@ -38,6 +47,18 @@ class AuthorizationProxyWebConfiguration {
|
|||||||
return new WebTargetVisitor();
|
return new WebTargetVisitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
|
||||||
|
for (int i = 0; i < resolvers.size(); i++) {
|
||||||
|
HandlerExceptionResolver resolver = resolvers.get(i);
|
||||||
|
if (resolver instanceof DefaultHandlerExceptionResolver) {
|
||||||
|
resolvers.add(i, new AccessDeniedExceptionResolver());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolvers.add(new AccessDeniedExceptionResolver());
|
||||||
|
}
|
||||||
|
|
||||||
static class WebTargetVisitor implements AuthorizationAdvisorProxyFactory.TargetVisitor, Ordered {
|
static class WebTargetVisitor implements AuthorizationAdvisorProxyFactory.TargetVisitor, Ordered {
|
||||||
|
|
||||||
private static final int DEFAULT_ORDER = 100;
|
private static final int DEFAULT_ORDER = 100;
|
||||||
@ -54,7 +75,7 @@ class AuthorizationProxyWebConfiguration {
|
|||||||
if (target instanceof ModelAndView mav) {
|
if (target instanceof ModelAndView mav) {
|
||||||
View view = mav.getView();
|
View view = mav.getView();
|
||||||
String viewName = mav.getViewName();
|
String viewName = mav.getViewName();
|
||||||
Map<String, Object> model = (Map<String, Object>) proxyFactory.proxy(mav.getModel());
|
Map<String, Object> model = proxyFactory.proxy(mav.getModel());
|
||||||
ModelAndView proxied = (view != null) ? new ModelAndView(view, model)
|
ModelAndView proxied = (view != null) ? new ModelAndView(view, model)
|
||||||
: new ModelAndView(viewName, model);
|
: new ModelAndView(viewName, model);
|
||||||
proxied.setStatus(mav.getStatus());
|
proxied.setStatus(mav.getStatus());
|
||||||
@ -70,4 +91,22 @@ class AuthorizationProxyWebConfiguration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class AccessDeniedExceptionResolver implements HandlerExceptionResolver {
|
||||||
|
|
||||||
|
final ThrowableAnalyzer throwableAnalyzer = new ThrowableAnalyzer();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||||
|
Exception ex) {
|
||||||
|
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
|
||||||
|
Throwable accessDeniedException = this.throwableAnalyzer
|
||||||
|
.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
|
||||||
|
if (accessDeniedException != null) {
|
||||||
|
throw (AccessDeniedException) accessDeniedException;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,10 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
import org.aopalliance.aop.Advice;
|
import org.aopalliance.aop.Advice;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.aop.Pointcut;
|
import org.springframework.aop.Pointcut;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
||||||
import org.springframework.util.function.SingletonSupplier;
|
import org.springframework.util.function.SingletonSupplier;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ final class DeferringMethodInterceptor<M extends AuthorizationAdvisor> implement
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
|
public Object invoke(@NonNull MethodInvocation invocation) throws Throwable {
|
||||||
return this.delegate.get().invoke(invocation);
|
return this.delegate.get().invoke(invocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,16 +407,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInit
|
|||||||
this.objectPostProcessor = objectPostProcessor;
|
this.objectPostProcessor = objectPostProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
@Autowired(required = false)
|
|
||||||
public void setObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<Object> objectPostProcessor) {
|
|
||||||
this.objectPostProcessor = objectPostProcessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
public void setMethodSecurityExpressionHandler(List<MethodSecurityExpressionHandler> handlers) {
|
public void setMethodSecurityExpressionHandler(List<MethodSecurityExpressionHandler> handlers) {
|
||||||
if (handlers.size() != 1) {
|
if (handlers.size() != 1) {
|
||||||
|
@ -19,8 +19,6 @@ package org.springframework.security.config.annotation.method.configuration;
|
|||||||
import org.aopalliance.aop.Advice;
|
import org.aopalliance.aop.Advice;
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.aop.Advisor;
|
||||||
import org.springframework.aop.Pointcut;
|
import org.springframework.aop.Pointcut;
|
||||||
@ -33,6 +31,8 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
|||||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
||||||
|
|
||||||
class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
|
class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
|
||||||
@ -100,7 +100,7 @@ class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
|
public Object invoke(@NonNull MethodInvocation invocation) throws Throwable {
|
||||||
return this.advisor.invoke(invocation);
|
return this.advisor.invoke(invocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ import org.springframework.security.authorization.method.PostAuthorizeAuthorizat
|
|||||||
import org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor;
|
import org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
|
import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
|
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
|
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||||
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
||||||
@ -130,14 +129,6 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, Applicati
|
|||||||
this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
void setTemplateDefaults(PrePostTemplateDefaults templateDefaults) {
|
|
||||||
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
|
||||||
this.preAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
|
||||||
this.postAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
|
||||||
this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||||
this.preFilterMethodInterceptor.setExpressionHandler(expressionHandler);
|
this.preFilterMethodInterceptor.setExpressionHandler(expressionHandler);
|
||||||
|
@ -42,7 +42,6 @@ import org.springframework.security.authorization.method.PostAuthorizeReactiveAu
|
|||||||
import org.springframework.security.authorization.method.PostFilterAuthorizationReactiveMethodInterceptor;
|
import org.springframework.security.authorization.method.PostFilterAuthorizationReactiveMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.PreAuthorizeReactiveAuthorizationManager;
|
import org.springframework.security.authorization.method.PreAuthorizeReactiveAuthorizationManager;
|
||||||
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
|
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
|
||||||
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
|
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||||
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
|
||||||
@ -112,14 +111,6 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration
|
|||||||
this.postAuthorizeAuthorizationManager.setApplicationContext(context);
|
this.postAuthorizeAuthorizationManager.setApplicationContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
void setTemplateDefaults(PrePostTemplateDefaults templateDefaults) {
|
|
||||||
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
|
||||||
this.preAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
|
||||||
this.postAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
|
||||||
this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
|
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
|
||||||
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
||||||
|
@ -109,6 +109,7 @@ import org.springframework.security.rsocket.util.matcher.RoutePayloadExchangeMat
|
|||||||
* @author Manuel Tejeda
|
* @author Manuel Tejeda
|
||||||
* @author Ebert Toribio
|
* @author Ebert Toribio
|
||||||
* @author Ngoc Nhan
|
* @author Ngoc Nhan
|
||||||
|
* @author Andrey Litvitski
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
*/
|
*/
|
||||||
public class RSocketSecurity {
|
public class RSocketSecurity {
|
||||||
@ -119,6 +120,8 @@ public class RSocketSecurity {
|
|||||||
|
|
||||||
private SimpleAuthenticationSpec simpleAuthSpec;
|
private SimpleAuthenticationSpec simpleAuthSpec;
|
||||||
|
|
||||||
|
private AnonymousAuthenticationSpec anonymousAuthSpec = new AnonymousAuthenticationSpec(this);
|
||||||
|
|
||||||
private JwtSpec jwtSpec;
|
private JwtSpec jwtSpec;
|
||||||
|
|
||||||
private AuthorizePayloadsSpec authorizePayload;
|
private AuthorizePayloadsSpec authorizePayload;
|
||||||
@ -164,6 +167,20 @@ public class RSocketSecurity {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds anonymous authentication
|
||||||
|
* @param anonymous a customizer
|
||||||
|
* @return this instance
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
public RSocketSecurity anonymous(Customizer<AnonymousAuthenticationSpec> anonymous) {
|
||||||
|
if (this.anonymousAuthSpec == null) {
|
||||||
|
this.anonymousAuthSpec = new AnonymousAuthenticationSpec(this);
|
||||||
|
}
|
||||||
|
anonymous.customize(this.anonymousAuthSpec);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds authentication with BasicAuthenticationPayloadExchangeConverter.
|
* Adds authentication with BasicAuthenticationPayloadExchangeConverter.
|
||||||
* @param basic
|
* @param basic
|
||||||
@ -214,7 +231,9 @@ public class RSocketSecurity {
|
|||||||
if (this.jwtSpec != null) {
|
if (this.jwtSpec != null) {
|
||||||
result.addAll(this.jwtSpec.build());
|
result.addAll(this.jwtSpec.build());
|
||||||
}
|
}
|
||||||
result.add(anonymous());
|
if (this.anonymousAuthSpec != null) {
|
||||||
|
result.add(this.anonymousAuthSpec.build());
|
||||||
|
}
|
||||||
if (this.authorizePayload != null) {
|
if (this.authorizePayload != null) {
|
||||||
result.add(this.authorizePayload.build());
|
result.add(this.authorizePayload.build());
|
||||||
}
|
}
|
||||||
@ -222,12 +241,6 @@ public class RSocketSecurity {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnonymousPayloadInterceptor anonymous() {
|
|
||||||
AnonymousPayloadInterceptor result = new AnonymousPayloadInterceptor("anonymousUser");
|
|
||||||
result.setOrder(PayloadInterceptorOrder.ANONYMOUS.getOrder());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T getBean(Class<T> beanClass) {
|
private <T> T getBean(Class<T> beanClass) {
|
||||||
if (this.context == null) {
|
if (this.context == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -283,6 +296,26 @@ public class RSocketSecurity {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class AnonymousAuthenticationSpec {
|
||||||
|
|
||||||
|
private RSocketSecurity parent;
|
||||||
|
|
||||||
|
private AnonymousAuthenticationSpec(RSocketSecurity parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AnonymousPayloadInterceptor build() {
|
||||||
|
AnonymousPayloadInterceptor result = new AnonymousPayloadInterceptor("anonymousUser");
|
||||||
|
result.setOrder(PayloadInterceptorOrder.ANONYMOUS.getOrder());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
this.parent.anonymousAuthSpec = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public final class BasicAuthenticationSpec {
|
public final class BasicAuthenticationSpec {
|
||||||
|
|
||||||
private ReactiveAuthenticationManager authenticationManager;
|
private ReactiveAuthenticationManager authenticationManager;
|
||||||
|
@ -18,41 +18,22 @@ package org.springframework.security.config.annotation.web;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import jakarta.servlet.DispatcherType;
|
import jakarta.servlet.DispatcherType;
|
||||||
import jakarta.servlet.ServletContext;
|
|
||||||
import jakarta.servlet.ServletRegistration;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
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.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.ResolvableType;
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||||
import org.springframework.security.config.annotation.web.ServletRegistrationsSupport.RegistrationMapping;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.function.ThrowingSupplier;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for
|
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for
|
||||||
@ -65,25 +46,16 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractRequestMatcherRegistry<C> {
|
public abstract class AbstractRequestMatcherRegistry<C> {
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
|
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
|
||||||
|
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
private boolean anyRequestConfigured = false;
|
private boolean anyRequestConfigured = false;
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
AbstractRequestMatcherRegistry.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private PathPatternRequestMatcher.Builder requestMatcherBuilder;
|
||||||
|
|
||||||
protected final void setApplicationContext(ApplicationContext context) {
|
protected final void setApplicationContext(ApplicationContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
@ -107,36 +79,6 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
return configurer;
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link MvcRequestMatcher} instances for the method and patterns passed in
|
|
||||||
* @param method the HTTP method to use or null if any should be used
|
|
||||||
* @param mvcPatterns the Spring MVC patterns to match on
|
|
||||||
* @return a List of {@link MvcRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
protected final List<MvcRequestMatcher> createMvcMatchers(HttpMethod method, String... mvcPatterns) {
|
|
||||||
Assert.state(!this.anyRequestConfigured, "Can't configure mvcMatchers after anyRequest");
|
|
||||||
ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class, Object.class);
|
|
||||||
ObjectProvider<ObjectPostProcessor<Object>> postProcessors = this.context.getBeanProvider(type);
|
|
||||||
ObjectPostProcessor<Object> opp = postProcessors.getObject();
|
|
||||||
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
|
||||||
throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME
|
|
||||||
+ " of type " + HandlerMappingIntrospector.class.getName()
|
|
||||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
|
|
||||||
}
|
|
||||||
HandlerMappingIntrospector introspector = this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
|
||||||
HandlerMappingIntrospector.class);
|
|
||||||
List<MvcRequestMatcher> matchers = new ArrayList<>(mvcPatterns.length);
|
|
||||||
for (String mvcPattern : mvcPatterns) {
|
|
||||||
MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern);
|
|
||||||
opp.postProcess(matcher);
|
|
||||||
if (method != null) {
|
|
||||||
matcher.setMethod(method);
|
|
||||||
}
|
|
||||||
matchers.add(matcher);
|
|
||||||
}
|
|
||||||
return matchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a {@link List} of
|
* Maps a {@link List} of
|
||||||
* {@link org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher}
|
* {@link org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher}
|
||||||
@ -180,12 +122,9 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
* Match when the {@link HttpMethod} is {@code method} and when the request URI
|
||||||
* {@link MvcRequestMatcher} that also specifies a specific {@link HttpMethod} to
|
* matches one of {@code patterns}. See
|
||||||
* match on. This matcher will use the same rules that Spring MVC uses for matching.
|
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules.
|
||||||
* For example, often times a mapping of the path "/path" will match on "/path",
|
|
||||||
* "/path/", "/path.html", etc. If the {@link HandlerMappingIntrospector} is not
|
|
||||||
* available, maps to an {@link AntPathRequestMatcher}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If a specific {@link RequestMatcher} must be specified, use
|
* If a specific {@link RequestMatcher} must be specified, use
|
||||||
@ -193,8 +132,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
* </p>
|
* </p>
|
||||||
* @param method the {@link HttpMethod} to use or {@code null} for any
|
* @param method the {@link HttpMethod} to use or {@code null} for any
|
||||||
* {@link HttpMethod}.
|
* {@link HttpMethod}.
|
||||||
* @param patterns the patterns to match on. The rules for matching are defined by
|
* @param patterns the patterns to match on
|
||||||
* Spring MVC if {@link MvcRequestMatcher} is used
|
|
||||||
* @return the object that is chained after creating the {@link RequestMatcher}.
|
* @return the object that is chained after creating the {@link RequestMatcher}.
|
||||||
* @since 5.8
|
* @since 5.8
|
||||||
*/
|
*/
|
||||||
@ -205,31 +143,32 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
+ "leading slash in all your request matcher patterns. In future versions of "
|
+ "leading slash in all your request matcher patterns. In future versions of "
|
||||||
+ "Spring Security, leaving out the leading slash will result in an exception.");
|
+ "Spring Security, leaving out the leading slash will result in an exception.");
|
||||||
}
|
}
|
||||||
if (!mvcPresent) {
|
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
|
||||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
PathPatternRequestMatcher.Builder builder = getRequestMatcherBuilder();
|
||||||
}
|
|
||||||
if (!(this.context instanceof WebApplicationContext)) {
|
|
||||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
|
||||||
}
|
|
||||||
WebApplicationContext context = (WebApplicationContext) this.context;
|
|
||||||
ServletContext servletContext = context.getServletContext();
|
|
||||||
if (servletContext == null) {
|
|
||||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
|
||||||
}
|
|
||||||
List<RequestMatcher> matchers = new ArrayList<>();
|
List<RequestMatcher> matchers = new ArrayList<>();
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
matchers.add(builder.matcher(method, pattern));
|
||||||
matchers.add(RequestMatcherFactory.matcher(method, pattern));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
AntPathRequestMatcher ant = new AntPathRequestMatcher(pattern, (method != null) ? method.name() : null);
|
|
||||||
MvcRequestMatcher mvc = createMvcMatchers(method, pattern).get(0);
|
|
||||||
matchers.add(new DeferredRequestMatcher((c) -> resolve(ant, mvc, c), mvc, ant));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
|
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PathPatternRequestMatcher.Builder getRequestMatcherBuilder() {
|
||||||
|
if (this.requestMatcherBuilder != null) {
|
||||||
|
return this.requestMatcherBuilder;
|
||||||
|
}
|
||||||
|
this.requestMatcherBuilder = this.context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
|
||||||
|
.getIfUnique(() -> constructRequestMatcherBuilder(this.context));
|
||||||
|
return this.requestMatcherBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PathPatternRequestMatcher.Builder constructRequestMatcherBuilder(ApplicationContext context) {
|
||||||
|
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder = new PathPatternRequestMatcherBuilderFactoryBean();
|
||||||
|
requestMatcherBuilder.setApplicationContext(context);
|
||||||
|
requestMatcherBuilder.setBeanFactory(context.getAutowireCapableBeanFactory());
|
||||||
|
requestMatcherBuilder.setBeanName(requestMatcherBuilder.toString());
|
||||||
|
return ThrowingSupplier.of(requestMatcherBuilder::getObject).get();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean anyPathsDontStartWithLeadingSlash(String... patterns) {
|
private boolean anyPathsDontStartWithLeadingSlash(String... patterns) {
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
if (!pattern.startsWith("/")) {
|
if (!pattern.startsWith("/")) {
|
||||||
@ -239,64 +178,16 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher resolve(AntPathRequestMatcher ant, MvcRequestMatcher mvc, ServletContext servletContext) {
|
|
||||||
ServletRegistrationsSupport registrations = new ServletRegistrationsSupport(servletContext);
|
|
||||||
Collection<RegistrationMapping> mappings = registrations.mappings();
|
|
||||||
if (mappings.isEmpty()) {
|
|
||||||
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher());
|
|
||||||
}
|
|
||||||
Collection<RegistrationMapping> dispatcherServletMappings = registrations.dispatcherServletMappings();
|
|
||||||
if (dispatcherServletMappings.isEmpty()) {
|
|
||||||
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher());
|
|
||||||
}
|
|
||||||
if (dispatcherServletMappings.size() > 1) {
|
|
||||||
String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values());
|
|
||||||
throw new IllegalArgumentException(errorMessage);
|
|
||||||
}
|
|
||||||
RegistrationMapping dispatcherServlet = dispatcherServletMappings.iterator().next();
|
|
||||||
if (mappings.size() > 1 && !dispatcherServlet.isDefault()) {
|
|
||||||
String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values());
|
|
||||||
throw new IllegalArgumentException(errorMessage);
|
|
||||||
}
|
|
||||||
if (dispatcherServlet.isDefault()) {
|
|
||||||
if (mappings.size() == 1) {
|
|
||||||
return mvc;
|
|
||||||
}
|
|
||||||
return new DispatcherServletDelegatingRequestMatcher(ant, mvc);
|
|
||||||
}
|
|
||||||
return mvc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String computeErrorMessage(Collection<? extends ServletRegistration> registrations) {
|
|
||||||
String template = """
|
|
||||||
This method cannot decide whether these patterns are Spring MVC patterns or not. \
|
|
||||||
This is because there is more than one mappable servlet in your servlet context: %s.
|
|
||||||
|
|
||||||
To address this, please create one PathPatternRequestMatcher.Builder#servletPath for each servlet that has \
|
|
||||||
authorized endpoints and use them to construct request matchers manually.
|
|
||||||
""";
|
|
||||||
Map<String, Collection<String>> mappings = new LinkedHashMap<>();
|
|
||||||
for (ServletRegistration registration : registrations) {
|
|
||||||
mappings.put(registration.getClassName(), registration.getMappings());
|
|
||||||
}
|
|
||||||
return String.format(template, mappings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
* Match when the request URI matches one of {@code patterns}. See
|
||||||
* {@link MvcRequestMatcher} that does not care which {@link HttpMethod} is used. This
|
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules.
|
||||||
* matcher will use the same rules that Spring MVC uses for matching. For example,
|
|
||||||
* often times a mapping of the path "/path" will match on "/path", "/path/",
|
|
||||||
* "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
|
|
||||||
* to an {@link AntPathRequestMatcher}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If a specific {@link RequestMatcher} must be specified, use
|
* If a specific {@link RequestMatcher} must be specified, use
|
||||||
* {@link #requestMatchers(RequestMatcher...)} instead
|
* {@link #requestMatchers(RequestMatcher...)} instead
|
||||||
* </p>
|
* </p>
|
||||||
* @param patterns the patterns to match on. The rules for matching are defined by
|
* @param patterns the patterns to match on
|
||||||
* Spring MVC if {@link MvcRequestMatcher} is used
|
|
||||||
* @return the object that is chained after creating the {@link RequestMatcher}.
|
* @return the object that is chained after creating the {@link RequestMatcher}.
|
||||||
* @since 5.8
|
* @since 5.8
|
||||||
*/
|
*/
|
||||||
@ -306,12 +197,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
* Match when the {@link HttpMethod} is {@code method}
|
||||||
* {@link MvcRequestMatcher} that matches on a specific {@link HttpMethod}. This
|
|
||||||
* matcher will use the same rules that Spring MVC uses for matching. For example,
|
|
||||||
* often times a mapping of the path "/path" will match on "/path", "/path/",
|
|
||||||
* "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
|
|
||||||
* to an {@link AntPathRequestMatcher}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If a specific {@link RequestMatcher} must be specified, use
|
* If a specific {@link RequestMatcher} must be specified, use
|
||||||
@ -335,182 +221,4 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
*/
|
*/
|
||||||
protected abstract C chainRequestMatchers(List<RequestMatcher> requestMatchers);
|
protected abstract C chainRequestMatchers(List<RequestMatcher> requestMatchers);
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for creating {@link RequestMatcher} instances.
|
|
||||||
*
|
|
||||||
* @author Rob Winch
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
private static final class RequestMatchers {
|
|
||||||
|
|
||||||
private RequestMatchers() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link AntPathRequestMatcher} instances.
|
|
||||||
* @param httpMethod the {@link HttpMethod} to use or {@code null} for any
|
|
||||||
* {@link HttpMethod}.
|
|
||||||
* @param antPatterns the ant patterns to create {@link AntPathRequestMatcher}
|
|
||||||
* from
|
|
||||||
* @return a {@link List} of {@link AntPathRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> antMatchers(HttpMethod httpMethod, String... antPatterns) {
|
|
||||||
return Arrays.asList(antMatchersAsArray(httpMethod, antPatterns));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link AntPathRequestMatcher} instances that do not
|
|
||||||
* specify an {@link HttpMethod}.
|
|
||||||
* @param antPatterns the ant patterns to create {@link AntPathRequestMatcher}
|
|
||||||
* from
|
|
||||||
* @return a {@link List} of {@link AntPathRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> antMatchers(String... antPatterns) {
|
|
||||||
return antMatchers(null, antPatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
static RequestMatcher[] antMatchersAsArray(HttpMethod httpMethod, String... antPatterns) {
|
|
||||||
String method = (httpMethod != null) ? httpMethod.toString() : null;
|
|
||||||
RequestMatcher[] matchers = new RequestMatcher[antPatterns.length];
|
|
||||||
for (int index = 0; index < antPatterns.length; index++) {
|
|
||||||
matchers[index] = new AntPathRequestMatcher(antPatterns[index], method);
|
|
||||||
}
|
|
||||||
return matchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link RegexRequestMatcher} instances.
|
|
||||||
* @param httpMethod the {@link HttpMethod} to use or {@code null} for any
|
|
||||||
* {@link HttpMethod}.
|
|
||||||
* @param regexPatterns the regular expressions to create
|
|
||||||
* {@link RegexRequestMatcher} from
|
|
||||||
* @return a {@link List} of {@link RegexRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> regexMatchers(HttpMethod httpMethod, String... regexPatterns) {
|
|
||||||
String method = (httpMethod != null) ? httpMethod.toString() : null;
|
|
||||||
List<RequestMatcher> matchers = new ArrayList<>();
|
|
||||||
for (String pattern : regexPatterns) {
|
|
||||||
matchers.add(new RegexRequestMatcher(pattern, method));
|
|
||||||
}
|
|
||||||
return matchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link RegexRequestMatcher} instances that do not
|
|
||||||
* specify an {@link HttpMethod}.
|
|
||||||
* @param regexPatterns the regular expressions to create
|
|
||||||
* {@link RegexRequestMatcher} from
|
|
||||||
* @return a {@link List} of {@link RegexRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> regexMatchers(String... regexPatterns) {
|
|
||||||
return regexMatchers(null, regexPatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DeferredRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
final Function<ServletContext, RequestMatcher> requestMatcherFactory;
|
|
||||||
|
|
||||||
final AtomicReference<String> description = new AtomicReference<>();
|
|
||||||
|
|
||||||
final Map<ServletContext, RequestMatcher> requestMatchers = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
DeferredRequestMatcher(Function<ServletContext, RequestMatcher> resolver, RequestMatcher... candidates) {
|
|
||||||
this.requestMatcherFactory = (sc) -> this.requestMatchers.computeIfAbsent(sc, resolver);
|
|
||||||
this.description.set("Deferred " + Arrays.toString(candidates));
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestMatcher requestMatcher(ServletContext servletContext) {
|
|
||||||
return this.requestMatcherFactory.apply(servletContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
return this.requestMatcherFactory.apply(request.getServletContext()).matches(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MatchResult matcher(HttpServletRequest request) {
|
|
||||||
return this.requestMatcherFactory.apply(request.getServletContext()).matcher(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.description.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MockMvcRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
return request.getAttribute("org.springframework.test.web.servlet.MockMvc.MVC_RESULT_ATTRIBUTE") != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DispatcherServletRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
String name = request.getHttpServletMapping().getServletName();
|
|
||||||
ServletRegistration registration = request.getServletContext().getServletRegistration(name);
|
|
||||||
Assert.notNull(registration,
|
|
||||||
() -> computeErrorMessage(request.getServletContext().getServletRegistrations().values()));
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(registration.getClassName());
|
|
||||||
return DispatcherServlet.class.isAssignableFrom(clazz);
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DispatcherServletDelegatingRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
private final AntPathRequestMatcher ant;
|
|
||||||
|
|
||||||
private final MvcRequestMatcher mvc;
|
|
||||||
|
|
||||||
private final RequestMatcher dispatcherServlet;
|
|
||||||
|
|
||||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc) {
|
|
||||||
this(ant, mvc, new OrRequestMatcher(new MockMvcRequestMatcher(), new DispatcherServletRequestMatcher()));
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc,
|
|
||||||
RequestMatcher dispatcherServlet) {
|
|
||||||
this.ant = ant;
|
|
||||||
this.mvc = mvc;
|
|
||||||
this.dispatcherServlet = dispatcherServlet;
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestMatcher requestMatcher(HttpServletRequest request) {
|
|
||||||
if (this.dispatcherServlet.matches(request)) {
|
|
||||||
return this.mvc;
|
|
||||||
}
|
|
||||||
return this.ant;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
return requestMatcher(request).matches(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MatchResult matcher(HttpServletRequest request) {
|
|
||||||
return requestMatcher(request).matcher(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "DispatcherServletDelegating [" + "ant = " + this.ant + ", mvc = " + this.mvc + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web;
|
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This utility exists only to facilitate applications opting into using path patterns in
|
|
||||||
* the HttpSecurity DSL. It is for internal use only.
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public final class RequestMatcherFactory {
|
|
||||||
|
|
||||||
private static PathPatternRequestMatcher.Builder builder;
|
|
||||||
|
|
||||||
public static void setApplicationContext(ApplicationContext context) {
|
|
||||||
builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class).getIfUnique();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean usesPathPatterns() {
|
|
||||||
return builder != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RequestMatcher matcher(String path) {
|
|
||||||
return matcher(null, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RequestMatcher matcher(HttpMethod method, String path) {
|
|
||||||
if (builder != null) {
|
|
||||||
return builder.matcher(method, path);
|
|
||||||
}
|
|
||||||
return new AntPathRequestMatcher(path, (method != null) ? method.name() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestMatcherFactory() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -55,6 +55,7 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer;
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer;
|
||||||
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
||||||
|
import org.springframework.security.web.access.PathPatternRequestTransformer;
|
||||||
import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||||
@ -139,14 +140,6 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||||||
super(objectPostProcessor);
|
super(objectPostProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public WebSecurity(org.springframework.security.config.annotation.ObjectPostProcessor<Object> objectPostProcessor) {
|
|
||||||
super(objectPostProcessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Allows adding {@link RequestMatcher} instances that Spring Security should ignore.
|
* Allows adding {@link RequestMatcher} instances that Spring Security should ignore.
|
||||||
@ -430,7 +423,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||||||
this.filterChainDecoratorPostProcessor = postProcessor.getIfUnique(ObjectPostProcessor::identity);
|
this.filterChainDecoratorPostProcessor = postProcessor.getIfUnique(ObjectPostProcessor::identity);
|
||||||
Class<HttpServletRequestTransformer> requestTransformerClass = HttpServletRequestTransformer.class;
|
Class<HttpServletRequestTransformer> requestTransformerClass = HttpServletRequestTransformer.class;
|
||||||
this.privilegeEvaluatorRequestTransformer = applicationContext.getBeanProvider(requestTransformerClass)
|
this.privilegeEvaluatorRequestTransformer = applicationContext.getBeanProvider(requestTransformerClass)
|
||||||
.getIfUnique();
|
.getIfUnique(PathPatternRequestTransformer::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -99,11 +99,11 @@ final class WebSecurityFilterChainValidator implements FilterChainProxy.FilterCh
|
|||||||
}
|
}
|
||||||
if (authorizationFilter != null && filterSecurityInterceptor != null) {
|
if (authorizationFilter != null && filterSecurityInterceptor != null) {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
"It is not recommended to use authorizeRequests in the configuration. Please only use authorizeHttpRequests");
|
"It is not recommended to use authorizeRequests or FilterSecurityInterceptor in the configuration. Please only use authorizeHttpRequests");
|
||||||
}
|
}
|
||||||
if (filterSecurityInterceptor != null) {
|
if (filterSecurityInterceptor != null) {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
"Usage of authorizeRequests is deprecated. Please use authorizeHttpRequests in the configuration");
|
"Usage of authorizeRequests and FilterSecurityInterceptor are deprecated. Please use authorizeHttpRequests in the configuration");
|
||||||
}
|
}
|
||||||
authorizationFilter = null;
|
authorizationFilter = null;
|
||||||
filterSecurityInterceptor = null;
|
filterSecurityInterceptor = null;
|
||||||
|
@ -46,8 +46,9 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||||||
*
|
*
|
||||||
* @Bean
|
* @Bean
|
||||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
* http.authorizeHttpRequests().requestMatchers("/public/**").permitAll().anyRequest()
|
* http.authorizeHttpRequests((authorize) -> authorize
|
||||||
* .hasRole("USER").and()
|
* .requestMatchers("/public/**").permitAll()
|
||||||
|
* .anyRequest().hasRole("USER"))
|
||||||
* // Possibly more configuration ...
|
* // Possibly more configuration ...
|
||||||
* .formLogin() // enable form based log in
|
* .formLogin() // enable form based log in
|
||||||
* // set permitAll for all URLs associated with Form Login
|
* // set permitAll for all URLs associated with Form Login
|
||||||
|
@ -16,35 +16,43 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configuration;
|
package org.springframework.security.config.annotation.web.configuration;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
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.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
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;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
|
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
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;
|
||||||
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
||||||
|
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||||
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.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||||
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
import org.springframework.util.function.ThrowingSupplier;
|
||||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
@ -105,7 +113,6 @@ class HttpSecurityConfiguration {
|
|||||||
@Bean(HTTPSECURITY_BEAN_NAME)
|
@Bean(HTTPSECURITY_BEAN_NAME)
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
HttpSecurity httpSecurity() throws Exception {
|
HttpSecurity httpSecurity() throws Exception {
|
||||||
RequestMatcherFactory.setApplicationContext(this.context);
|
|
||||||
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
|
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
|
||||||
AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||||
this.objectPostProcessor, passwordEncoder);
|
this.objectPostProcessor, passwordEncoder);
|
||||||
@ -125,11 +132,13 @@ class HttpSecurityConfiguration {
|
|||||||
.requestCache(withDefaults())
|
.requestCache(withDefaults())
|
||||||
.anonymous(withDefaults())
|
.anonymous(withDefaults())
|
||||||
.servletApi(withDefaults())
|
.servletApi(withDefaults())
|
||||||
.apply(new DefaultLoginPageConfigurer<>());
|
.with(new DefaultLoginPageConfigurer<>());
|
||||||
http.logout(withDefaults());
|
http.logout(withDefaults());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
applyCorsIfAvailable(http);
|
applyCorsIfAvailable(http);
|
||||||
applyDefaultConfigurers(http);
|
applyDefaultConfigurers(http);
|
||||||
|
applyHttpSecurityCustomizers(this.context, http);
|
||||||
|
applyTopLevelCustomizers(this.context, http);
|
||||||
return http;
|
return http;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,17 +164,93 @@ class HttpSecurityConfiguration {
|
|||||||
List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader
|
List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader
|
||||||
.loadFactories(AbstractHttpConfigurer.class, classLoader);
|
.loadFactories(AbstractHttpConfigurer.class, classLoader);
|
||||||
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
|
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
|
||||||
http.apply(configurer);
|
http.with(configurer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies all {@code Customizer<HttpSecurity>} Bean instances to the
|
||||||
|
* {@link HttpSecurity} instance.
|
||||||
|
* @param applicationContext the {@link ApplicationContext} to lookup Bean instances
|
||||||
|
* @param http the {@link HttpSecurity} to apply the Beans to.
|
||||||
|
*/
|
||||||
|
private void applyHttpSecurityCustomizers(ApplicationContext applicationContext, HttpSecurity http) {
|
||||||
|
ResolvableType httpSecurityCustomizerType = ResolvableType.forClassWithGenerics(Customizer.class,
|
||||||
|
HttpSecurity.class);
|
||||||
|
ObjectProvider<Customizer<HttpSecurity>> customizerProvider = this.context
|
||||||
|
.getBeanProvider(httpSecurityCustomizerType);
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
customizerProvider.orderedStream().forEach((customizer) ->
|
||||||
|
customizer.customize(http)
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies all {@link Customizer} Beans to {@link HttpSecurity}. For each public,
|
||||||
|
* non-static method in HttpSecurity that accepts a Customizer
|
||||||
|
* <ul>
|
||||||
|
* <li>Use the {@link MethodParameter} (this preserves generics) to resolve all Beans
|
||||||
|
* for that type</li>
|
||||||
|
* <li>For each {@link Customizer} Bean invoke the {@link java.lang.reflect.Method}
|
||||||
|
* with the {@link Customizer} Bean as the argument</li>
|
||||||
|
* </ul>
|
||||||
|
* @param context the {@link ApplicationContext}
|
||||||
|
* @param http the {@link HttpSecurity}
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private void applyTopLevelCustomizers(ApplicationContext context, HttpSecurity http) {
|
||||||
|
ReflectionUtils.MethodFilter isCustomizerMethod = (method) -> {
|
||||||
|
if (Modifier.isStatic(method.getModifiers())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Modifier.isPublic(method.getModifiers())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!method.canAccess(http)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (method.getParameterCount() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (method.getParameterTypes()[0] == Customizer.class) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
ReflectionUtils.MethodCallback invokeWithEachCustomizerBean = (customizerMethod) -> {
|
||||||
|
|
||||||
|
MethodParameter customizerParameter = new MethodParameter(customizerMethod, 0);
|
||||||
|
ResolvableType customizerType = ResolvableType.forMethodParameter(customizerParameter);
|
||||||
|
ObjectProvider<?> customizerProvider = context.getBeanProvider(customizerType);
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
customizerProvider.orderedStream().forEach((customizer) ->
|
||||||
|
ReflectionUtils.invokeMethod(customizerMethod, http, customizer)
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
};
|
||||||
|
ReflectionUtils.doWithMethods(HttpSecurity.class, invokeWithEachCustomizerBean, isCustomizerMethod);
|
||||||
|
}
|
||||||
|
|
||||||
private Map<Class<?>, Object> createSharedObjects() {
|
private Map<Class<?>, Object> createSharedObjects() {
|
||||||
Map<Class<?>, Object> sharedObjects = new HashMap<>();
|
Map<Class<?>, Object> sharedObjects = new HashMap<>();
|
||||||
sharedObjects.put(ApplicationContext.class, this.context);
|
sharedObjects.put(ApplicationContext.class, this.context);
|
||||||
sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy);
|
sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy);
|
||||||
|
sharedObjects.put(PathPatternRequestMatcher.Builder.class, constructRequestMatcherBuilder(this.context));
|
||||||
return sharedObjects;
|
return sharedObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PathPatternRequestMatcher.Builder constructRequestMatcherBuilder(ApplicationContext context) {
|
||||||
|
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder = new PathPatternRequestMatcherBuilderFactoryBean();
|
||||||
|
requestMatcherBuilder.setApplicationContext(context);
|
||||||
|
requestMatcherBuilder.setBeanFactory(context.getAutowireCapableBeanFactory());
|
||||||
|
requestMatcherBuilder.setBeanName(requestMatcherBuilder.toString());
|
||||||
|
return ThrowingSupplier.of(requestMatcherBuilder::getObject).get();
|
||||||
|
}
|
||||||
|
|
||||||
static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder {
|
static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder {
|
||||||
|
|
||||||
private PasswordEncoder defaultPasswordEncoder;
|
private PasswordEncoder defaultPasswordEncoder;
|
||||||
@ -180,17 +265,6 @@ class HttpSecurityConfiguration {
|
|||||||
this.defaultPasswordEncoder = defaultPasswordEncoder;
|
this.defaultPasswordEncoder = defaultPasswordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
DefaultPasswordEncoderAuthenticationManagerBuilder(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<Object> objectPostProcessor,
|
|
||||||
PasswordEncoder defaultPasswordEncoder) {
|
|
||||||
super(objectPostProcessor);
|
|
||||||
this.defaultPasswordEncoder = defaultPasswordEncoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
|
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -50,13 +50,11 @@ import org.springframework.security.oauth2.client.DelegatingOAuth2AuthorizedClie
|
|||||||
import org.springframework.security.oauth2.client.JwtBearerOAuth2AuthorizedClientProvider;
|
import org.springframework.security.oauth2.client.JwtBearerOAuth2AuthorizedClientProvider;
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
|
||||||
import org.springframework.security.oauth2.client.PasswordOAuth2AuthorizedClientProvider;
|
|
||||||
import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
|
import org.springframework.security.oauth2.client.RefreshTokenOAuth2AuthorizedClientProvider;
|
||||||
import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
|
import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
|
||||||
import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
|
import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest;
|
||||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||||
import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
|
import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
|
||||||
import org.springframework.security.oauth2.client.endpoint.OAuth2PasswordGrantRequest;
|
|
||||||
import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
|
import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
|
||||||
import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
|
import org.springframework.security.oauth2.client.endpoint.TokenExchangeGrantRequest;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||||
@ -173,7 +171,6 @@ final class OAuth2ClientConfiguration {
|
|||||||
AuthorizationCodeOAuth2AuthorizedClientProvider.class,
|
AuthorizationCodeOAuth2AuthorizedClientProvider.class,
|
||||||
RefreshTokenOAuth2AuthorizedClientProvider.class,
|
RefreshTokenOAuth2AuthorizedClientProvider.class,
|
||||||
ClientCredentialsOAuth2AuthorizedClientProvider.class,
|
ClientCredentialsOAuth2AuthorizedClientProvider.class,
|
||||||
PasswordOAuth2AuthorizedClientProvider.class,
|
|
||||||
JwtBearerOAuth2AuthorizedClientProvider.class,
|
JwtBearerOAuth2AuthorizedClientProvider.class,
|
||||||
TokenExchangeOAuth2AuthorizedClientProvider.class
|
TokenExchangeOAuth2AuthorizedClientProvider.class
|
||||||
);
|
);
|
||||||
@ -241,7 +238,6 @@ final class OAuth2ClientConfiguration {
|
|||||||
authorizedClientProviders.add(getRefreshTokenAuthorizedClientProvider(authorizedClientProviderBeans));
|
authorizedClientProviders.add(getRefreshTokenAuthorizedClientProvider(authorizedClientProviderBeans));
|
||||||
authorizedClientProviders
|
authorizedClientProviders
|
||||||
.add(getClientCredentialsAuthorizedClientProvider(authorizedClientProviderBeans));
|
.add(getClientCredentialsAuthorizedClientProvider(authorizedClientProviderBeans));
|
||||||
authorizedClientProviders.add(getPasswordAuthorizedClientProvider(authorizedClientProviderBeans));
|
|
||||||
|
|
||||||
OAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider = getJwtBearerAuthorizedClientProvider(
|
OAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider = getJwtBearerAuthorizedClientProvider(
|
||||||
authorizedClientProviderBeans);
|
authorizedClientProviderBeans);
|
||||||
@ -331,24 +327,6 @@ final class OAuth2ClientConfiguration {
|
|||||||
return authorizedClientProvider;
|
return authorizedClientProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OAuth2AuthorizedClientProvider getPasswordAuthorizedClientProvider(
|
|
||||||
Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
|
|
||||||
PasswordOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
|
|
||||||
authorizedClientProviders, PasswordOAuth2AuthorizedClientProvider.class);
|
|
||||||
if (authorizedClientProvider == null) {
|
|
||||||
authorizedClientProvider = new PasswordOAuth2AuthorizedClientProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> accessTokenResponseClient = getBeanOfType(
|
|
||||||
ResolvableType.forClassWithGenerics(OAuth2AccessTokenResponseClient.class,
|
|
||||||
OAuth2PasswordGrantRequest.class));
|
|
||||||
if (accessTokenResponseClient != null) {
|
|
||||||
authorizedClientProvider.setAccessTokenResponseClient(accessTokenResponseClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizedClientProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private OAuth2AuthorizedClientProvider getJwtBearerAuthorizedClientProvider(
|
private OAuth2AuthorizedClientProvider getJwtBearerAuthorizedClientProvider(
|
||||||
Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
|
Collection<OAuth2AuthorizedClientProvider> authorizedClientProviders) {
|
||||||
JwtBearerOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
|
JwtBearerOAuth2AuthorizedClientProvider authorizedClientProvider = getAuthorizedClientProviderByType(
|
||||||
|
@ -26,15 +26,7 @@ import jakarta.servlet.ServletRequest;
|
|||||||
import jakarta.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
|
||||||
import org.springframework.beans.factory.support.ManagedList;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -45,8 +37,6 @@ 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.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer;
|
|
||||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
|
||||||
import org.springframework.security.web.debug.DebugFilter;
|
import org.springframework.security.web.debug.DebugFilter;
|
||||||
import org.springframework.security.web.firewall.HttpFirewall;
|
import org.springframework.security.web.firewall.HttpFirewall;
|
||||||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||||
@ -58,7 +48,6 @@ import org.springframework.web.filter.CompositeFilter;
|
|||||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,10 +65,6 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
|||||||
*/
|
*/
|
||||||
class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware {
|
class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware {
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final String PATH_PATTERN_REQUEST_TRANSFORMER_BEAN_NAME = "pathPatternRequestTransformer";
|
|
||||||
|
|
||||||
private BeanResolver beanResolver;
|
private BeanResolver beanResolver;
|
||||||
|
|
||||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||||
@ -121,86 +106,6 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
static BeanDefinitionRegistryPostProcessor springSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor() {
|
|
||||||
return new BeanDefinitionRegistryPostProcessor() {
|
|
||||||
@Override
|
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
|
||||||
if (!registry.containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String hmiRequestTransformerBeanName = HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer";
|
|
||||||
if (!registry.containsBeanDefinition(PATH_PATTERN_REQUEST_TRANSFORMER_BEAN_NAME)
|
|
||||||
&& !registry.containsBeanDefinition(hmiRequestTransformerBeanName)) {
|
|
||||||
if (!registry.containsBeanDefinition(hmiRequestTransformerBeanName)) {
|
|
||||||
BeanDefinition hmiRequestTransformer = BeanDefinitionBuilder
|
|
||||||
.rootBeanDefinition(HandlerMappingIntrospectorRequestTransformer.class)
|
|
||||||
.addConstructorArgReference(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)
|
|
||||||
.getBeanDefinition();
|
|
||||||
registry.registerBeanDefinition(hmiRequestTransformerBeanName, hmiRequestTransformer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BeanDefinition filterChainProxy = registry
|
|
||||||
.getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
|
|
||||||
|
|
||||||
if (!filterChainProxy.getResolvableType().isInstance(CompositeFilterChainProxy.class)) {
|
|
||||||
BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder
|
|
||||||
.rootBeanDefinition(HandlerMappingIntrospectorCacheFilterFactoryBean.class)
|
|
||||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
|
||||||
|
|
||||||
ManagedList<BeanMetadataElement> filters = new ManagedList<>();
|
|
||||||
filters.add(hmiCacheFilterBldr.getBeanDefinition());
|
|
||||||
filters.add(filterChainProxy);
|
|
||||||
BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder
|
|
||||||
.rootBeanDefinition(CompositeFilterChainProxy.class)
|
|
||||||
.addConstructorArgValue(filters);
|
|
||||||
|
|
||||||
registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
|
|
||||||
registry.registerBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME,
|
|
||||||
compositeSpringSecurityFilterChainBldr.getBeanDefinition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link FactoryBean} to defer creation of
|
|
||||||
* {@link HandlerMappingIntrospector#createCacheFilter()}
|
|
||||||
*
|
|
||||||
* @deprecated see {@link WebSecurityConfiguration} for
|
|
||||||
* {@link org.springframework.web.util.pattern.PathPattern} replacement
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
static class HandlerMappingIntrospectorCacheFilterFactoryBean
|
|
||||||
implements ApplicationContextAware, FactoryBean<Filter> {
|
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Filter getObject() throws Exception {
|
|
||||||
HandlerMappingIntrospector handlerMappingIntrospector = this.applicationContext
|
|
||||||
.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
|
|
||||||
return handlerMappingIntrospector.createCacheFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return Filter.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link FilterChainProxy} to provide as much passivity as possible but
|
* Extends {@link FilterChainProxy} to provide as much passivity as possible but
|
||||||
* delegates to {@link CompositeFilter} for
|
* delegates to {@link CompositeFilter} for
|
||||||
|
@ -33,7 +33,6 @@ import org.springframework.beans.BeansException;
|
|||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
@ -69,7 +68,6 @@ import org.springframework.security.web.firewall.HttpFirewall;
|
|||||||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||||
import org.springframework.web.filter.CompositeFilter;
|
import org.springframework.web.filter.CompositeFilter;
|
||||||
import org.springframework.web.filter.ServletRequestPathFilter;
|
import org.springframework.web.filter.ServletRequestPathFilter;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
|
* Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
|
||||||
@ -80,6 +78,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @author Keesun Baik
|
* @author Keesun Baik
|
||||||
|
* @author Yanming Zhou
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
* @see EnableWebSecurity
|
* @see EnableWebSecurity
|
||||||
* @see WebSecurity
|
* @see WebSecurity
|
||||||
@ -191,7 +190,7 @@ public class WebSecurityConfiguration implements ImportAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public static BeanFactoryPostProcessor conversionServicePostProcessor() {
|
public static RsaKeyConversionServicePostProcessor conversionServicePostProcessor() {
|
||||||
return new RsaKeyConversionServicePostProcessor();
|
return new RsaKeyConversionServicePostProcessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,12 +208,11 @@ public class WebSecurityConfiguration implements ImportAware {
|
|||||||
/**
|
/**
|
||||||
* Used to ensure Spring MVC request matching is cached.
|
* Used to ensure Spring MVC request matching is cached.
|
||||||
*
|
*
|
||||||
* Creates a {@link BeanDefinitionRegistryPostProcessor} that detects if a bean named
|
* Creates a {@link BeanDefinitionRegistryPostProcessor} that moves the
|
||||||
* HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME is defined. If so, it moves the
|
|
||||||
* AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name
|
* AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name
|
||||||
* and then adds a {@link CompositeFilter} that contains
|
* and then adds a {@link CompositeFilter} that contains
|
||||||
* {@link HandlerMappingIntrospector#createCacheFilter()} and the original
|
* {@link ServletRequestPathFilter} and the original FilterChainProxy under the
|
||||||
* FilterChainProxy under the original Bean name.
|
* original Bean name.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -36,8 +36,6 @@ import org.springframework.util.Assert;
|
|||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
* @see ChannelSecurityConfigurer
|
* @see ChannelSecurityConfigurer
|
||||||
* @see UrlAuthorizationConfigurer
|
|
||||||
* @see ExpressionUrlAuthorizationConfigurer
|
|
||||||
* @deprecated In modern Spring Security APIs, each API manages its own configuration
|
* @deprecated In modern Spring Security APIs, each API manages its own configuration
|
||||||
* context. As such there is no direct replacement for this interface. In the case of
|
* context. As such there is no direct replacement for this interface. In the case of
|
||||||
* method security, please see {@link SecurityAnnotationScanner} and
|
* method security, please see {@link SecurityAnnotationScanner} and
|
||||||
|
@ -25,6 +25,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|||||||
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.web.DefaultSecurityFilterChain;
|
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||||
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a convenient base class for {@link SecurityConfigurer} instances that operate on
|
* Adds a convenient base class for {@link SecurityConfigurer} instances that operate on
|
||||||
@ -55,17 +56,6 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T,
|
|||||||
return (T) this;
|
return (T) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public T withObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return (T) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SecurityContextHolderStrategy getSecurityContextHolderStrategy() {
|
protected SecurityContextHolderStrategy getSecurityContextHolderStrategy() {
|
||||||
if (this.securityContextHolderStrategy != null) {
|
if (this.securityContextHolderStrategy != null) {
|
||||||
return this.securityContextHolderStrategy;
|
return this.securityContextHolderStrategy;
|
||||||
@ -76,4 +66,8 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T,
|
|||||||
return this.securityContextHolderStrategy;
|
return this.securityContextHolderStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PathPatternRequestMatcher.Builder getRequestMatcherBuilder() {
|
||||||
|
return getBuilder().getSharedObject(PathPatternRequestMatcher.Builder.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configurers;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.security.access.AccessDecisionManager;
|
|
||||||
import org.springframework.security.access.AccessDecisionVoter;
|
|
||||||
import org.springframework.security.access.vote.AffirmativeBased;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
|
||||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base class for configuring the {@link FilterSecurityInterceptor}.
|
|
||||||
*
|
|
||||||
* <h2>Security Filters</h2>
|
|
||||||
*
|
|
||||||
* The following Filters are populated
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link FilterSecurityInterceptor}</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <h2>Shared Objects Created</h2>
|
|
||||||
*
|
|
||||||
* The following shared objects are populated to allow other {@link SecurityConfigurer}'s
|
|
||||||
* to customize:
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link FilterSecurityInterceptor}</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <h2>Shared Objects Used</h2>
|
|
||||||
*
|
|
||||||
* The following shared objects are used:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link AuthenticationManager}</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param <C> the AbstractInterceptUrlConfigurer
|
|
||||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured
|
|
||||||
* @author Rob Winch
|
|
||||||
* @since 3.2
|
|
||||||
* @see ExpressionUrlAuthorizationConfigurer
|
|
||||||
* @see UrlAuthorizationConfigurer
|
|
||||||
* @deprecated Use {@link AuthorizeHttpRequestsConfigurer} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C, H>, H extends HttpSecurityBuilder<H>>
|
|
||||||
extends AbstractHttpConfigurer<C, H> {
|
|
||||||
|
|
||||||
private Boolean filterSecurityInterceptorOncePerRequest;
|
|
||||||
|
|
||||||
private AccessDecisionManager accessDecisionManager;
|
|
||||||
|
|
||||||
AbstractInterceptUrlConfigurer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(H http) throws Exception {
|
|
||||||
FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
|
|
||||||
if (metadataSource == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(http, metadataSource,
|
|
||||||
http.getSharedObject(AuthenticationManager.class));
|
|
||||||
if (this.filterSecurityInterceptorOncePerRequest != null) {
|
|
||||||
securityInterceptor.setObserveOncePerRequest(this.filterSecurityInterceptorOncePerRequest);
|
|
||||||
}
|
|
||||||
securityInterceptor = postProcess(securityInterceptor);
|
|
||||||
http.addFilter(securityInterceptor);
|
|
||||||
http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses should implement this method to provide a
|
|
||||||
* {@link FilterInvocationSecurityMetadataSource} for the
|
|
||||||
* {@link FilterSecurityInterceptor}.
|
|
||||||
* @param http the builder to use
|
|
||||||
* @return the {@link FilterInvocationSecurityMetadataSource} to set on the
|
|
||||||
* {@link FilterSecurityInterceptor}. Cannot be null.
|
|
||||||
*/
|
|
||||||
abstract FilterInvocationSecurityMetadataSource createMetadataSource(H http);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses should implement this method to provide the {@link AccessDecisionVoter}
|
|
||||||
* instances used to create the default {@link AccessDecisionManager}
|
|
||||||
* @param http the builder to use
|
|
||||||
* @return the {@link AccessDecisionVoter} instances used to create the default
|
|
||||||
* {@link AccessDecisionManager}
|
|
||||||
*/
|
|
||||||
abstract List<AccessDecisionVoter<?>> getDecisionVoters(H http);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the default {@code AccessDecisionManager}
|
|
||||||
* @return the default {@code AccessDecisionManager}
|
|
||||||
*/
|
|
||||||
private AccessDecisionManager createDefaultAccessDecisionManager(H http) {
|
|
||||||
AffirmativeBased result = new AffirmativeBased(getDecisionVoters(http));
|
|
||||||
return postProcess(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If currently null, creates a default {@link AccessDecisionManager} using
|
|
||||||
* {@link #createDefaultAccessDecisionManager(HttpSecurityBuilder)}. Otherwise returns
|
|
||||||
* the {@link AccessDecisionManager}.
|
|
||||||
* @param http the builder to use
|
|
||||||
* @return the {@link AccessDecisionManager} to use
|
|
||||||
*/
|
|
||||||
private AccessDecisionManager getAccessDecisionManager(H http) {
|
|
||||||
if (this.accessDecisionManager == null) {
|
|
||||||
this.accessDecisionManager = createDefaultAccessDecisionManager(http);
|
|
||||||
}
|
|
||||||
return this.accessDecisionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the {@link FilterSecurityInterceptor}
|
|
||||||
* @param http the builder to use
|
|
||||||
* @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use
|
|
||||||
* @param authenticationManager the {@link AuthenticationManager} to use
|
|
||||||
* @return the {@link FilterSecurityInterceptor}
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private FilterSecurityInterceptor createFilterSecurityInterceptor(H http,
|
|
||||||
FilterInvocationSecurityMetadataSource metadataSource, AuthenticationManager authenticationManager)
|
|
||||||
throws Exception {
|
|
||||||
FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
|
|
||||||
securityInterceptor.setSecurityMetadataSource(metadataSource);
|
|
||||||
securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http));
|
|
||||||
securityInterceptor.setAuthenticationManager(authenticationManager);
|
|
||||||
securityInterceptor.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
|
||||||
securityInterceptor.afterPropertiesSet();
|
|
||||||
return securityInterceptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public abstract class AbstractInterceptUrlRegistry<R extends AbstractInterceptUrlRegistry<R, T>, T>
|
|
||||||
extends AbstractConfigAttributeRequestMatcherRegistry<T> {
|
|
||||||
|
|
||||||
AbstractInterceptUrlRegistry() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows setting the {@link AccessDecisionManager}. If none is provided, a
|
|
||||||
* default {@link AccessDecisionManager} is created.
|
|
||||||
* @param accessDecisionManager the {@link AccessDecisionManager} to use
|
|
||||||
* @return the {@link AbstractInterceptUrlConfigurer} for further customization
|
|
||||||
*/
|
|
||||||
public R accessDecisionManager(AccessDecisionManager accessDecisionManager) {
|
|
||||||
AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager;
|
|
||||||
return getSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows setting if the {@link FilterSecurityInterceptor} should be only applied
|
|
||||||
* once per request (i.e. if the filter intercepts on a forward, should it be
|
|
||||||
* applied again).
|
|
||||||
* @param filterSecurityInterceptorOncePerRequest if the
|
|
||||||
* {@link FilterSecurityInterceptor} should be only applied once per request
|
|
||||||
* @return the {@link AbstractInterceptUrlConfigurer} for further customization
|
|
||||||
*/
|
|
||||||
public R filterSecurityInterceptorOncePerRequest(boolean filterSecurityInterceptorOncePerRequest) {
|
|
||||||
AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest;
|
|
||||||
return getSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a reference to the current object with a single suppression of the type
|
|
||||||
* @return a reference to the current object
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private R getSelf() {
|
|
||||||
return (R) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -21,6 +21,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
|
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
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;
|
||||||
@ -57,7 +58,7 @@ public final class AnonymousConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#anonymous()
|
* @see HttpSecurity#anonymous(Customizer)
|
||||||
*/
|
*/
|
||||||
public AnonymousConfigurer() {
|
public AnonymousConfigurer() {
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
AuthorizationManager<HttpServletRequest> authorizationManager = this.registry.createAuthorizationManager();
|
AuthorizationManager<HttpServletRequest> authorizationManager = this.registry.createAuthorizationManager();
|
||||||
AuthorizationFilter authorizationFilter = new AuthorizationFilter(authorizationManager);
|
AuthorizationFilter authorizationFilter = new AuthorizationFilter(authorizationManager);
|
||||||
authorizationFilter.setAuthorizationEventPublisher(this.publisher);
|
authorizationFilter.setAuthorizationEventPublisher(this.publisher);
|
||||||
authorizationFilter.setShouldFilterAllDispatcherTypes(this.registry.shouldFilterAllDispatcherTypes);
|
|
||||||
authorizationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
authorizationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
||||||
http.addFilter(postProcess(authorizationFilter));
|
http.addFilter(postProcess(authorizationFilter));
|
||||||
}
|
}
|
||||||
@ -144,8 +143,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
|
|
||||||
private int mappingCount;
|
private int mappingCount;
|
||||||
|
|
||||||
private boolean shouldFilterAllDispatcherTypes = true;
|
|
||||||
|
|
||||||
private AuthorizationManagerRequestMatcherRegistry(ApplicationContext context) {
|
private AuthorizationManagerRequestMatcherRegistry(ApplicationContext context) {
|
||||||
setApplicationContext(context);
|
setApplicationContext(context);
|
||||||
}
|
}
|
||||||
@ -191,57 +188,6 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public AuthorizationManagerRequestMatcherRegistry withObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether all dispatcher types should be filtered.
|
|
||||||
* @param shouldFilter should filter all dispatcher types. Default is {@code true}
|
|
||||||
* @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
|
|
||||||
* customizations
|
|
||||||
* @since 5.7
|
|
||||||
* @deprecated Permit access to the {@link jakarta.servlet.DispatcherType}
|
|
||||||
* instead. <pre>
|
|
||||||
* @Configuration
|
|
||||||
* @EnableWebSecurity
|
|
||||||
* public class SecurityConfig {
|
|
||||||
*
|
|
||||||
* @Bean
|
|
||||||
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
||||||
* http
|
|
||||||
* .authorizeHttpRequests((authorize) -> authorize
|
|
||||||
* .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
|
|
||||||
* // ...
|
|
||||||
* );
|
|
||||||
* return http.build();
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public AuthorizationManagerRequestMatcherRegistry shouldFilterAllDispatcherTypes(boolean shouldFilter) {
|
|
||||||
this.shouldFilterAllDispatcherTypes = shouldFilter;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the {@link HttpSecurityBuilder} when done using the
|
|
||||||
* {@link AuthorizeHttpRequestsConfigurer}. This is useful for method chaining.
|
|
||||||
* @return the {@link HttpSecurityBuilder} for further customizations
|
|
||||||
* @deprecated For removal in 7.0. Use the lambda based configuration instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public H and() {
|
|
||||||
return AuthorizeHttpRequestsConfigurer.this.and();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,10 +24,7 @@ import java.util.List;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.access.SecurityConfig;
|
import org.springframework.security.access.SecurityConfig;
|
||||||
import org.springframework.security.config.Customizer;
|
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.SecurityBuilder;
|
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||||
@ -96,7 +93,7 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#requiresChannel()
|
* @see HttpSecurity#requiresChannel(Customizer)
|
||||||
*/
|
*/
|
||||||
public ChannelSecurityConfigurer(ApplicationContext context) {
|
public ChannelSecurityConfigurer(ApplicationContext context) {
|
||||||
this.REGISTRY = new ChannelRequestMatcherRegistry(context);
|
this.REGISTRY = new ChannelRequestMatcherRegistry(context);
|
||||||
@ -175,16 +172,6 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public ChannelRequestMatcherRegistry withObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link ChannelProcessor} instances to use in
|
* Sets the {@link ChannelProcessor} instances to use in
|
||||||
* {@link ChannelDecisionManagerImpl}
|
* {@link ChannelDecisionManagerImpl}
|
||||||
@ -207,18 +194,6 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the {@link SecurityBuilder} when done using the
|
|
||||||
* {@link SecurityConfigurer}. This is useful for method chaining.
|
|
||||||
* @return the type of {@link HttpSecurityBuilder} that is being configured
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link HttpSecurity#requiresChannel(Customizer)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public H and() {
|
|
||||||
return ChannelSecurityConfigurer.this.and();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,21 +18,18 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
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.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds {@link CorsFilter} to the Spring Security filter chain. If a bean by the name of
|
* Adds {@link CorsFilter} to the Spring Security filter chain. If a bean by the name of
|
||||||
* corsFilter is provided, that {@link CorsFilter} is used. Else if
|
* corsFilter is provided, that {@link CorsFilter} is used. Else if
|
||||||
* corsConfigurationSource is defined, then that {@link CorsConfiguration} is used.
|
* corsConfigurationSource is defined, then that {@link CorsConfiguration} is used.
|
||||||
* Otherwise, if Spring MVC is on the classpath a {@link HandlerMappingIntrospector} is
|
|
||||||
* used.
|
|
||||||
*
|
*
|
||||||
* @param <H> the builder to return.
|
* @param <H> the builder to return.
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
@ -44,20 +41,12 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||||||
|
|
||||||
private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
|
private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
private CorsConfigurationSource configurationSource;
|
private CorsConfigurationSource configurationSource;
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, CorsConfigurer.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*
|
*
|
||||||
* @see HttpSecurity#cors()
|
* @see HttpSecurity#cors(Customizer)
|
||||||
*/
|
*/
|
||||||
public CorsConfigurer() {
|
public CorsConfigurer() {
|
||||||
}
|
}
|
||||||
@ -90,10 +79,7 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||||||
CorsConfigurationSource.class);
|
CorsConfigurationSource.class);
|
||||||
return new CorsFilter(configurationSource);
|
return new CorsFilter(configurationSource);
|
||||||
}
|
}
|
||||||
if (mvcPresent) {
|
return MvcCorsFilter.getMvcCorsFilter(context);
|
||||||
return MvcCorsFilter.getMvcCorsFilter(context);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MvcCorsFilter {
|
static class MvcCorsFilter {
|
||||||
|
@ -19,12 +19,15 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||||
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;
|
||||||
@ -34,13 +37,17 @@ import org.springframework.security.web.access.CompositeAccessDeniedHandler;
|
|||||||
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
|
import org.springframework.security.web.access.DelegatingAccessDeniedHandler;
|
||||||
import org.springframework.security.web.access.ObservationMarkingAccessDeniedHandler;
|
import org.springframework.security.web.access.ObservationMarkingAccessDeniedHandler;
|
||||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||||
|
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||||
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
|
import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
|
||||||
import org.springframework.security.web.csrf.CsrfFilter;
|
import org.springframework.security.web.csrf.CsrfFilter;
|
||||||
import org.springframework.security.web.csrf.CsrfLogoutHandler;
|
import org.springframework.security.web.csrf.CsrfLogoutHandler;
|
||||||
|
import org.springframework.security.web.csrf.CsrfToken;
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||||
|
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
||||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||||
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
import org.springframework.security.web.csrf.MissingCsrfTokenException;
|
||||||
|
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
|
||||||
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
import org.springframework.security.web.session.InvalidSessionAccessDeniedHandler;
|
||||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||||
@ -48,6 +55,7 @@ import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
|||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds
|
* Adds
|
||||||
@ -96,7 +104,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#csrf()
|
* @see HttpSecurity#csrf(Customizer)
|
||||||
*/
|
*/
|
||||||
public CsrfConfigurer(ApplicationContext context) {
|
public CsrfConfigurer(ApplicationContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -156,16 +164,16 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* http
|
* http
|
||||||
* .csrf()
|
* .csrf((csrf) -> csrf
|
||||||
* .ignoringRequestMatchers((request) -> "XMLHttpRequest".equals(request.getHeader("X-Requested-With")))
|
* .ignoringRequestMatchers((request) -> "XMLHttpRequest".equals(request.getHeader("X-Requested-With"))))
|
||||||
* .and()
|
|
||||||
* ...
|
* ...
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public CsrfConfigurer<H> ignoringRequestMatchers(RequestMatcher... requestMatchers) {
|
public CsrfConfigurer<H> ignoringRequestMatchers(RequestMatcher... requestMatchers) {
|
||||||
return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(requestMatchers).and();
|
new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(requestMatchers);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,9 +192,8 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* http
|
* http
|
||||||
* .csrf()
|
* .csrf((csrf) -> csrf
|
||||||
* .ignoringRequestMatchers("/sockjs/**")
|
* .ignoringRequestMatchers("/sockjs/**"))
|
||||||
* .and()
|
|
||||||
* ...
|
* ...
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
@ -194,7 +201,8 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* @see AbstractRequestMatcherRegistry#requestMatchers(String...)
|
* @see AbstractRequestMatcherRegistry#requestMatchers(String...)
|
||||||
*/
|
*/
|
||||||
public CsrfConfigurer<H> ignoringRequestMatchers(String... patterns) {
|
public CsrfConfigurer<H> ignoringRequestMatchers(String... patterns) {
|
||||||
return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(patterns).and();
|
new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(patterns);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,6 +222,21 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sensible CSRF defaults when used in combination with a single page application.
|
||||||
|
* Creates a cookie-based token repository and a custom request handler to resolve the
|
||||||
|
* actual token value instead of the encoded token.
|
||||||
|
* </p>
|
||||||
|
* @return the {@link CsrfConfigurer} for further customizations
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
public CsrfConfigurer<H> spa() {
|
||||||
|
this.csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||||
|
this.requestHandler = new SpaCsrfTokenRequestHandler();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void configure(H http) {
|
public void configure(H http) {
|
||||||
@ -363,10 +386,6 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
setApplicationContext(context);
|
setApplicationContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
CsrfConfigurer<H> and() {
|
|
||||||
return CsrfConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IgnoreCsrfProtectionRegistry chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
protected IgnoreCsrfProtectionRegistry chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
||||||
CsrfConfigurer.this.ignoredCsrfProtectionMatchers.addAll(requestMatchers);
|
CsrfConfigurer.this.ignoredCsrfProtectionMatchers.addAll(requestMatchers);
|
||||||
@ -375,4 +394,27 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class SpaCsrfTokenRequestHandler implements CsrfTokenRequestHandler {
|
||||||
|
|
||||||
|
private final CsrfTokenRequestAttributeHandler plain = new CsrfTokenRequestAttributeHandler();
|
||||||
|
|
||||||
|
private final CsrfTokenRequestAttributeHandler xor = new XorCsrfTokenRequestAttributeHandler();
|
||||||
|
|
||||||
|
SpaCsrfTokenRequestHandler() {
|
||||||
|
this.xor.setCsrfRequestAttributeName(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HttpServletRequest request, HttpServletResponse response, Supplier<CsrfToken> csrfToken) {
|
||||||
|
this.xor.handle(request, response, csrfToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {
|
||||||
|
String headerValue = request.getHeader(csrfToken.getHeaderName());
|
||||||
|
return (StringUtils.hasText(headerValue) ? this.plain : this.xor).resolveCsrfTokenValue(request, csrfToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
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.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
@ -76,7 +77,7 @@ public final class ExceptionHandlingConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#exceptionHandling()
|
* @see HttpSecurity#exceptionHandling(Customizer)
|
||||||
*/
|
*/
|
||||||
public ExceptionHandlingConfigurer() {
|
public ExceptionHandlingConfigurer() {
|
||||||
}
|
}
|
||||||
|
@ -1,421 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.config.annotation.web.configurers;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.security.access.AccessDecisionVoter;
|
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
|
||||||
import org.springframework.security.access.PermissionEvaluator;
|
|
||||||
import org.springframework.security.access.SecurityConfig;
|
|
||||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
|
||||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
|
||||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
||||||
import org.springframework.security.web.FilterInvocation;
|
|
||||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
|
||||||
import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
|
|
||||||
import org.springframework.security.web.access.expression.WebExpressionVoter;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds URL based authorization based upon SpEL expressions to an application. At least
|
|
||||||
* one {@link org.springframework.web.bind.annotation.RequestMapping} needs to be mapped
|
|
||||||
* to {@link ConfigAttribute}'s for this {@link SecurityContextConfigurer} to have
|
|
||||||
* meaning.
|
|
||||||
* <h2>Security Filters</h2>
|
|
||||||
*
|
|
||||||
* The following Filters are populated
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <h2>Shared Objects Created</h2>
|
|
||||||
*
|
|
||||||
* The following shared objects are populated to allow other
|
|
||||||
* {@link org.springframework.security.config.annotation.SecurityConfigurer}'s to
|
|
||||||
* customize:
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link org.springframework.security.web.access.intercept.FilterSecurityInterceptor}
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <h2>Shared Objects Used</h2>
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the
|
|
||||||
* {@link DefaultWebSecurityExpressionHandler}</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured
|
|
||||||
* @author Rob Winch
|
|
||||||
* @author Yanming Zhou
|
|
||||||
* @author Ngoc Nhan
|
|
||||||
* @since 3.2
|
|
||||||
* @see org.springframework.security.config.annotation.web.builders.HttpSecurity#authorizeRequests()
|
|
||||||
* @deprecated Use {@link AuthorizeHttpRequestsConfigurer} instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
|
|
||||||
extends AbstractInterceptUrlConfigurer<ExpressionUrlAuthorizationConfigurer<H>, H> {
|
|
||||||
|
|
||||||
static final String permitAll = "permitAll";
|
|
||||||
|
|
||||||
private static final String denyAll = "denyAll";
|
|
||||||
|
|
||||||
private static final String anonymous = "anonymous";
|
|
||||||
|
|
||||||
private static final String authenticated = "authenticated";
|
|
||||||
|
|
||||||
private static final String fullyAuthenticated = "fullyAuthenticated";
|
|
||||||
|
|
||||||
private static final String rememberMe = "rememberMe";
|
|
||||||
|
|
||||||
private final String rolePrefix;
|
|
||||||
|
|
||||||
private final ExpressionInterceptUrlRegistry REGISTRY;
|
|
||||||
|
|
||||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
* @see HttpSecurity#authorizeRequests()
|
|
||||||
*/
|
|
||||||
public ExpressionUrlAuthorizationConfigurer(ApplicationContext context) {
|
|
||||||
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBeanProvider(GrantedAuthorityDefaults.class)
|
|
||||||
.getIfUnique();
|
|
||||||
if (grantedAuthorityDefaults != null) {
|
|
||||||
this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.rolePrefix = "ROLE_";
|
|
||||||
}
|
|
||||||
this.REGISTRY = new ExpressionInterceptUrlRegistry(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionInterceptUrlRegistry getRegistry() {
|
|
||||||
return this.REGISTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows registering multiple {@link RequestMatcher} instances to a collection of
|
|
||||||
* {@link ConfigAttribute} instances
|
|
||||||
* @param requestMatchers the {@link RequestMatcher} instances to register to the
|
|
||||||
* {@link ConfigAttribute} instances
|
|
||||||
* @param configAttributes the {@link ConfigAttribute} to be mapped by the
|
|
||||||
* {@link RequestMatcher} instances
|
|
||||||
*/
|
|
||||||
private void interceptUrl(Iterable<? extends RequestMatcher> requestMatchers,
|
|
||||||
Collection<ConfigAttribute> configAttributes) {
|
|
||||||
for (RequestMatcher requestMatcher : requestMatchers) {
|
|
||||||
this.REGISTRY.addMapping(
|
|
||||||
new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
List<AccessDecisionVoter<?>> getDecisionVoters(H http) {
|
|
||||||
List<AccessDecisionVoter<?>> decisionVoters = new ArrayList<>();
|
|
||||||
WebExpressionVoter expressionVoter = new WebExpressionVoter();
|
|
||||||
expressionVoter.setExpressionHandler(getExpressionHandler(http));
|
|
||||||
decisionVoters.add(expressionVoter);
|
|
||||||
return decisionVoters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) {
|
|
||||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = this.REGISTRY.createRequestMap();
|
|
||||||
Assert.state(!requestMap.isEmpty(),
|
|
||||||
"At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())");
|
|
||||||
return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SecurityExpressionHandler<FilterInvocation> getExpressionHandler(H http) {
|
|
||||||
if (this.expressionHandler != null) {
|
|
||||||
return this.expressionHandler;
|
|
||||||
}
|
|
||||||
DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler();
|
|
||||||
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
|
|
||||||
if (trustResolver != null) {
|
|
||||||
defaultHandler.setTrustResolver(trustResolver);
|
|
||||||
}
|
|
||||||
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
|
|
||||||
if (context != null) {
|
|
||||||
context.getBeanProvider(RoleHierarchy.class).ifUnique(defaultHandler::setRoleHierarchy);
|
|
||||||
context.getBeanProvider(GrantedAuthorityDefaults.class)
|
|
||||||
.ifUnique((grantedAuthorityDefaults) -> defaultHandler
|
|
||||||
.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix()));
|
|
||||||
context.getBeanProvider(PermissionEvaluator.class).ifUnique(defaultHandler::setPermissionEvaluator);
|
|
||||||
}
|
|
||||||
this.expressionHandler = postProcess(defaultHandler);
|
|
||||||
return this.expressionHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String hasAnyRole(String rolePrefix, String... authorities) {
|
|
||||||
String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','" + rolePrefix);
|
|
||||||
return "hasAnyRole('" + rolePrefix + anyAuthorities + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String hasRole(String rolePrefix, String role) {
|
|
||||||
Assert.notNull(role, "role cannot be null");
|
|
||||||
Assert.isTrue(rolePrefix.isEmpty() || !role.startsWith(rolePrefix), () -> "role should not start with '"
|
|
||||||
+ rolePrefix + "' since it is automatically inserted. Got '" + role + "'");
|
|
||||||
return "hasRole('" + rolePrefix + role + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String hasAuthority(String authority) {
|
|
||||||
return "hasAuthority('" + authority + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String hasAnyAuthority(String... authorities) {
|
|
||||||
String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','");
|
|
||||||
return "hasAnyAuthority('" + anyAuthorities + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String hasIpAddress(String ipAddressExpression) {
|
|
||||||
return "hasIpAddress('" + ipAddressExpression + "')";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public final class ExpressionInterceptUrlRegistry extends
|
|
||||||
ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<ExpressionInterceptUrlRegistry, AuthorizedUrl> {
|
|
||||||
|
|
||||||
private ExpressionInterceptUrlRegistry(ApplicationContext context) {
|
|
||||||
setApplicationContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AuthorizedUrl chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
|
|
||||||
return new AuthorizedUrl(requestMatchers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows customization of the {@link SecurityExpressionHandler} to be used. The
|
|
||||||
* default is {@link DefaultWebSecurityExpressionHandler}
|
|
||||||
* @param expressionHandler the {@link SecurityExpressionHandler} to be used
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization.
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry expressionHandler(
|
|
||||||
SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
|
||||||
ExpressionUrlAuthorizationConfigurer.this.expressionHandler = expressionHandler;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an {@link ObjectPostProcessor} for this class.
|
|
||||||
* @param objectPostProcessor
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customizations
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.4", forRemoval = true)
|
|
||||||
public ExpressionInterceptUrlRegistry withObjectPostProcessor(
|
|
||||||
org.springframework.security.config.annotation.ObjectPostProcessor<?> objectPostProcessor) {
|
|
||||||
addObjectPostProcessor(objectPostProcessor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public H and() {
|
|
||||||
return ExpressionUrlAuthorizationConfigurer.this.and();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AuthorizedUrl {
|
|
||||||
|
|
||||||
private List<? extends RequestMatcher> requestMatchers;
|
|
||||||
|
|
||||||
private boolean not;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
* @param requestMatchers the {@link RequestMatcher} instances to map
|
|
||||||
*/
|
|
||||||
AuthorizedUrl(List<? extends RequestMatcher> requestMatchers) {
|
|
||||||
this.requestMatchers = requestMatchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<? extends RequestMatcher> getMatchers() {
|
|
||||||
return this.requestMatchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Negates the following expression.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public AuthorizedUrl not() {
|
|
||||||
this.not = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for specifying URLs require a particular role. If you do not want to
|
|
||||||
* have role prefix (default "ROLE_") automatically inserted see
|
|
||||||
* {@link #hasAuthority(String)}.
|
|
||||||
* @param role the role to require (i.e. USER, ADMIN, etc). Note, it should not
|
|
||||||
* start with role prefix as this is automatically inserted.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry hasRole(String role) {
|
|
||||||
return access(ExpressionUrlAuthorizationConfigurer
|
|
||||||
.hasRole(ExpressionUrlAuthorizationConfigurer.this.rolePrefix, role));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for specifying URLs require any of a number of roles. If you do not
|
|
||||||
* want to have role prefix (default "ROLE_") automatically inserted see
|
|
||||||
* {@link #hasAnyAuthority(String...)}
|
|
||||||
* @param roles the roles to require (i.e. USER, ADMIN, etc). Note, it should not
|
|
||||||
* start with role prefix as this is automatically inserted.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry hasAnyRole(String... roles) {
|
|
||||||
return access(ExpressionUrlAuthorizationConfigurer
|
|
||||||
.hasAnyRole(ExpressionUrlAuthorizationConfigurer.this.rolePrefix, roles));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs require a particular authority.
|
|
||||||
* @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry hasAuthority(String authority) {
|
|
||||||
return access(ExpressionUrlAuthorizationConfigurer.hasAuthority(authority));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs requires any of a number authorities.
|
|
||||||
* @param authorities the requests require at least one of the authorities (i.e.
|
|
||||||
* "ROLE_USER","ROLE_ADMIN" would mean either "ROLE_USER" or "ROLE_ADMIN" is
|
|
||||||
* required).
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry hasAnyAuthority(String... authorities) {
|
|
||||||
return access(ExpressionUrlAuthorizationConfigurer.hasAnyAuthority(authorities));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs requires a specific IP Address or subnet.
|
|
||||||
* @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet
|
|
||||||
* (i.e. 192.168.0/24)
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry hasIpAddress(String ipaddressExpression) {
|
|
||||||
return access(ExpressionUrlAuthorizationConfigurer.hasIpAddress(ipaddressExpression));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs are allowed by anyone.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry permitAll() {
|
|
||||||
return access(permitAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs are allowed by anonymous users.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry anonymous() {
|
|
||||||
return access(anonymous);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs are allowed by users that have been remembered.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
* @see RememberMeConfigurer
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry rememberMe() {
|
|
||||||
return access(rememberMe);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs are not allowed by anyone.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry denyAll() {
|
|
||||||
return access(denyAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs are allowed by any authenticated user.
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry authenticated() {
|
|
||||||
return access(authenticated);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that URLs are allowed by users who have authenticated and were not
|
|
||||||
* "remembered".
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
* @see RememberMeConfigurer
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry fullyAuthenticated() {
|
|
||||||
return access(fullyAuthenticated);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows specifying that URLs are secured by an arbitrary expression
|
|
||||||
* @param attribute the expression to secure the URLs (i.e. "hasRole('ROLE_USER')
|
|
||||||
* and hasRole('ROLE_SUPER')")
|
|
||||||
* @return the {@link ExpressionUrlAuthorizationConfigurer} for further
|
|
||||||
* customization
|
|
||||||
*/
|
|
||||||
public ExpressionInterceptUrlRegistry access(String attribute) {
|
|
||||||
if (this.not) {
|
|
||||||
attribute = "!" + attribute;
|
|
||||||
}
|
|
||||||
interceptUrl(this.requestMatchers, SecurityConfig.createList(attribute));
|
|
||||||
return ExpressionUrlAuthorizationConfigurer.this.REGISTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -17,8 +17,8 @@
|
|||||||
package org.springframework.security.config.annotation.web.configurers;
|
package org.springframework.security.config.annotation.web.configurers;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
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.RequestMatcherFactory;
|
|
||||||
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;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
@ -74,7 +74,7 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#formLogin()
|
* @see HttpSecurity#formLogin(Customizer)
|
||||||
*/
|
*/
|
||||||
public FormLoginConfigurer() {
|
public FormLoginConfigurer() {
|
||||||
super(new UsernamePasswordAuthenticationFilter(), null);
|
super(new UsernamePasswordAuthenticationFilter(), null);
|
||||||
@ -235,7 +235,7 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||||
return RequestMatcherFactory.matcher(HttpMethod.POST, loginProcessingUrl);
|
return getRequestMatcherBuilder().matcher(HttpMethod.POST, loginProcessingUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,7 +111,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*
|
*
|
||||||
* @see HttpSecurity#headers()
|
* @see HttpSecurity#headers(Customizer)
|
||||||
*/
|
*/
|
||||||
public HeadersConfigurer() {
|
public HeadersConfigurer() {
|
||||||
}
|
}
|
||||||
@ -127,26 +127,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the
|
|
||||||
* <a href= "https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx"
|
|
||||||
* >X-Content-Type-Options</a>:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* X-Content-Type-Options: nosniff
|
|
||||||
* </pre>
|
|
||||||
* @return the {@link ContentTypeOptionsConfig} for additional customizations
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #contentTypeOptions(Customizer)} or
|
|
||||||
* {@code contentTypeOptions(Customizer.withDefaults())} to stick with defaults. See
|
|
||||||
* the <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public ContentTypeOptionsConfig contentTypeOptions() {
|
|
||||||
return this.contentTypeOptions.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the
|
* Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the
|
||||||
* <a href= "https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx"
|
* <a href= "https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx"
|
||||||
@ -164,26 +144,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <strong>Note this is not comprehensive XSS protection!</strong>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
|
|
||||||
* "https://web.archive.org/web/20160201174302/https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
|
|
||||||
* >X-XSS-Protection header</a>
|
|
||||||
* </p>
|
|
||||||
* @return the {@link XXssConfig} for additional customizations
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #xssProtection(Customizer)} or
|
|
||||||
* {@code xssProtection(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public XXssConfig xssProtection() {
|
|
||||||
return this.xssProtection.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <strong>Note this is not comprehensive XSS protection!</strong>
|
* <strong>Note this is not comprehensive XSS protection!</strong>
|
||||||
*
|
*
|
||||||
@ -201,26 +161,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the
|
|
||||||
* following headers:
|
|
||||||
* <ul>
|
|
||||||
* <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
|
|
||||||
* <li>Pragma: no-cache</li>
|
|
||||||
* <li>Expires: 0</li>
|
|
||||||
* </ul>
|
|
||||||
* @return the {@link CacheControlConfig} for additional customizations
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #cacheControl(Customizer)} or
|
|
||||||
* {@code cacheControl(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public CacheControlConfig cacheControl() {
|
|
||||||
return this.cacheControl.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the
|
* Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the
|
||||||
* following headers:
|
* following headers:
|
||||||
@ -238,19 +178,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows customizing the {@link HstsHeaderWriter} which provides support for
|
|
||||||
* <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
|
|
||||||
* (HSTS)</a>.
|
|
||||||
* @return the {@link HstsConfig} for additional customizations
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link #httpStrictTransportSecurity(Customizer)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HstsConfig httpStrictTransportSecurity() {
|
|
||||||
return this.hsts.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows customizing the {@link HstsHeaderWriter} which provides support for
|
* Allows customizing the {@link HstsHeaderWriter} which provides support for
|
||||||
* <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
|
* <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
|
||||||
@ -264,20 +191,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows customizing the {@link XFrameOptionsHeaderWriter}.
|
|
||||||
* @return the {@link FrameOptionsConfig} for additional customizations
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #frameOptions(Customizer)} or
|
|
||||||
* {@code frameOptions(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public FrameOptionsConfig frameOptions() {
|
|
||||||
return this.frameOptions.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows customizing the {@link XFrameOptionsHeaderWriter}.
|
* Allows customizing the {@link XFrameOptionsHeaderWriter}.
|
||||||
* @param frameOptionsCustomizer the {@link Customizer} to provide more options for
|
* @param frameOptionsCustomizer the {@link Customizer} to provide more options for
|
||||||
@ -289,21 +202,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows customizing the {@link HpkpHeaderWriter} which provides support for
|
|
||||||
* <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
|
|
||||||
* @return the {@link HpkpConfig} for additional customizations
|
|
||||||
*
|
|
||||||
* @since 4.1
|
|
||||||
* @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
|
|
||||||
public HpkpConfig httpPublicKeyPinning() {
|
|
||||||
return this.hpkp.enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows customizing the {@link HpkpHeaderWriter} which provides support for
|
* Allows customizing the {@link HpkpHeaderWriter} which provides support for
|
||||||
* <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
|
* <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
|
||||||
@ -320,39 +218,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
|
|
||||||
* Policy (CSP) Level 2</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Calling this method automatically enables (includes) the Content-Security-Policy
|
|
||||||
* header in the response using the supplied security policy directive(s).
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which
|
|
||||||
* supports the writing of the two headers as detailed in the W3C Candidate
|
|
||||||
* Recommendation:
|
|
||||||
* </p>
|
|
||||||
* <ul>
|
|
||||||
* <li>Content-Security-Policy</li>
|
|
||||||
* <li>Content-Security-Policy-Report-Only</li>
|
|
||||||
* </ul>
|
|
||||||
* @return the {@link ContentSecurityPolicyConfig} for additional configuration
|
|
||||||
* @throws IllegalArgumentException if policyDirectives is null or empty
|
|
||||||
* @since 4.1
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #contentSecurityPolicy(Customizer)}
|
|
||||||
* instead
|
|
||||||
* @see ContentSecurityPolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public ContentSecurityPolicyConfig contentSecurityPolicy(String policyDirectives) {
|
|
||||||
this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(policyDirectives);
|
|
||||||
return this.contentSecurityPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
|
* Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
|
||||||
@ -454,71 +319,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
|
|
||||||
* Policy</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
|
|
||||||
* the writing of the header as detailed in the W3C Technical Report:
|
|
||||||
* </p>
|
|
||||||
* <ul>
|
|
||||||
* <li>Referrer-Policy</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Default value is:
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* Referrer-Policy: no-referrer
|
|
||||||
* </pre>
|
|
||||||
* @return the {@link ReferrerPolicyConfig} for additional configuration
|
|
||||||
* @since 4.2
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #referrerPolicy(Customizer)} or
|
|
||||||
* {@code referrerPolicy(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
* @see ReferrerPolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public ReferrerPolicyConfig referrerPolicy() {
|
|
||||||
this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter();
|
|
||||||
return this.referrerPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
|
|
||||||
* Policy</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
|
|
||||||
* the writing of the header as detailed in the W3C Technical Report:
|
|
||||||
* </p>
|
|
||||||
* <ul>
|
|
||||||
* <li>Referrer-Policy</li>
|
|
||||||
* </ul>
|
|
||||||
* @return the {@link ReferrerPolicyConfig} for additional configuration
|
|
||||||
* @throws IllegalArgumentException if policy is null or empty
|
|
||||||
* @since 4.2
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #referrerPolicy(Customizer)} or
|
|
||||||
* {@code referrerPolicy(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
* @see ReferrerPolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public ReferrerPolicyConfig referrerPolicy(ReferrerPolicy policy) {
|
|
||||||
this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(policy);
|
|
||||||
return this.referrerPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
|
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
|
||||||
@ -568,35 +368,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this.featurePolicy;
|
return this.featurePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Allows configuration for
|
|
||||||
* <a href="https://w3c.github.io/webappsec-permissions-policy/">Permissions
|
|
||||||
* Policy</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link PermissionsPolicyHeaderWriter} which
|
|
||||||
* support the writing of the header as detailed in the W3C Technical Report:
|
|
||||||
* </p>
|
|
||||||
* <ul>
|
|
||||||
* <li>Permissions-Policy</li>
|
|
||||||
* </ul>
|
|
||||||
* @return the {@link PermissionsPolicyConfig} for additional configuration
|
|
||||||
* @since 5.5
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #permissionsPolicyHeader(Customizer)} or
|
|
||||||
* {@code permissionsPolicy(Customizer.withDefaults())} to stick with defaults. See
|
|
||||||
* the <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
* @see PermissionsPolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public PermissionsPolicyConfig permissionsPolicy() {
|
|
||||||
this.permissionsPolicy.writer = new PermissionsPolicyHeaderWriter();
|
|
||||||
return this.permissionsPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows configuration for
|
* Allows configuration for
|
||||||
* <a href="https://w3c.github.io/webappsec-permissions-policy/"> Permissions
|
* <a href="https://w3c.github.io/webappsec-permissions-policy/"> Permissions
|
||||||
@ -643,26 +414,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows configuration for <a href=
|
|
||||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
|
||||||
* Cross-Origin-Opener-Policy</a> header.
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link CrossOriginOpenerPolicyHeaderWriter} which
|
|
||||||
* responsible for writing the header.
|
|
||||||
* </p>
|
|
||||||
* @return the {@link CrossOriginOpenerPolicyConfig} for additional confniguration
|
|
||||||
* @since 5.7
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #crossOriginOpenerPolicy(Customizer)}
|
|
||||||
* instead
|
|
||||||
* @see CrossOriginOpenerPolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public CrossOriginOpenerPolicyConfig crossOriginOpenerPolicy() {
|
|
||||||
this.crossOriginOpenerPolicy.writer = new CrossOriginOpenerPolicyHeaderWriter();
|
|
||||||
return this.crossOriginOpenerPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows configuration for <a href=
|
* Allows configuration for <a href=
|
||||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
@ -687,26 +438,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows configuration for <a href=
|
|
||||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
|
||||||
* Cross-Origin-Embedder-Policy</a> header.
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link CrossOriginEmbedderPolicyHeaderWriter}
|
|
||||||
* which is responsible for writing the header.
|
|
||||||
* </p>
|
|
||||||
* @return the {@link CrossOriginEmbedderPolicyConfig} for additional customizations
|
|
||||||
* @since 5.7
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #crossOriginEmbedderPolicy(Customizer)}
|
|
||||||
* instead
|
|
||||||
* @see CrossOriginEmbedderPolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public CrossOriginEmbedderPolicyConfig crossOriginEmbedderPolicy() {
|
|
||||||
this.crossOriginEmbedderPolicy.writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
|
||||||
return this.crossOriginEmbedderPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows configuration for <a href=
|
* Allows configuration for <a href=
|
||||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
@ -731,26 +462,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows configuration for <a href=
|
|
||||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
|
||||||
* Cross-Origin-Resource-Policy</a> header.
|
|
||||||
* <p>
|
|
||||||
* Configuration is provided to the {@link CrossOriginResourcePolicyHeaderWriter}
|
|
||||||
* which is responsible for writing the header:
|
|
||||||
* </p>
|
|
||||||
* @return the {@link HeadersConfigurer} for additional customizations
|
|
||||||
* @since 5.7
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #crossOriginResourcePolicy(Customizer)}
|
|
||||||
* instead
|
|
||||||
* @see CrossOriginResourcePolicyHeaderWriter
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public CrossOriginResourcePolicyConfig crossOriginResourcePolicy() {
|
|
||||||
this.crossOriginResourcePolicy.writer = new CrossOriginResourcePolicyHeaderWriter();
|
|
||||||
return this.crossOriginResourcePolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows configuration for <a href=
|
* Allows configuration for <a href=
|
||||||
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
@ -789,17 +500,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public HeadersConfigurer<H> disable() {
|
public HeadersConfigurer<H> disable() {
|
||||||
this.writer = null;
|
this.writer = null;
|
||||||
return and();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows customizing the {@link HeadersConfigurer}
|
|
||||||
* @return the {@link HeadersConfigurer} for additional customization
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #contentTypeOptions(Customizer)}
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,21 +564,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public HeadersConfigurer<H> disable() {
|
public HeadersConfigurer<H> disable() {
|
||||||
this.writer = null;
|
this.writer = null;
|
||||||
return and();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of X-XSS-Protection and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #xssProtection(Customizer)} or
|
|
||||||
* {@code xssProtection(Customizer.withDefaults())} to stick with defaults. See
|
|
||||||
* the <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,21 +597,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Cache Control and continuing configuration
|
|
||||||
* of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #cacheControl(Customizer)} or
|
|
||||||
* {@code cacheControl(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures the Cache Control headers are enabled if they are not already.
|
* Ensures the Cache Control headers are enabled if they are not already.
|
||||||
* @return the {@link CacheControlConfig} for additional customization
|
* @return the {@link CacheControlConfig} for additional customization
|
||||||
@ -1024,18 +694,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Strict Transport Security and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link #httpStrictTransportSecurity(Customizer)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that Strict-Transport-Security is enabled if it is not already
|
* Ensures that Strict-Transport-Security is enabled if it is not already
|
||||||
* @return the {@link HstsConfig} for additional customization
|
* @return the {@link HstsConfig} for additional customization
|
||||||
@ -1063,7 +721,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public HeadersConfigurer<H> deny() {
|
public HeadersConfigurer<H> deny() {
|
||||||
this.writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY);
|
this.writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY);
|
||||||
return and();
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1077,7 +735,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public HeadersConfigurer<H> sameOrigin() {
|
public HeadersConfigurer<H> sameOrigin() {
|
||||||
this.writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN);
|
this.writer = new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN);
|
||||||
return and();
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1086,20 +744,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
*/
|
*/
|
||||||
public HeadersConfigurer<H> disable() {
|
public HeadersConfigurer<H> disable() {
|
||||||
this.writer = null;
|
this.writer = null;
|
||||||
return and();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows continuing customizing the headers configuration.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #frameOptions(Customizer)} or
|
|
||||||
* {@code frameOptions(Customizer.withDefaults())} to stick with defaults. See the
|
|
||||||
* <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
return HeadersConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1317,18 +961,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Content Security Policy and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #contentSecurityPolicy(Customizer)}
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ReferrerPolicyConfig {
|
public final class ReferrerPolicyConfig {
|
||||||
@ -1349,18 +981,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #referrerPolicy(Customizer)} or
|
|
||||||
* {@code referrerPolicy(Customizer.withDefaults())} to stick with defaults. See
|
|
||||||
* the <a href=
|
|
||||||
* "https://docs.spring.io/spring-security/reference/migration-7/configuration.html#_use_the_lambda_dsl">documentation</a>
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class FeaturePolicyConfig {
|
public final class FeaturePolicyConfig {
|
||||||
@ -1399,18 +1019,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Permissions Policy and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use {@link #permissionsPolicy(Customizer)}
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class CrossOriginOpenerPolicyConfig {
|
public final class CrossOriginOpenerPolicyConfig {
|
||||||
@ -1432,18 +1040,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Cross Origin Opener Policy and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link #crossOriginOpenerPolicy(Customizer)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class CrossOriginEmbedderPolicyConfig {
|
public final class CrossOriginEmbedderPolicyConfig {
|
||||||
@ -1466,18 +1062,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Cross-Origin-Embedder-Policy and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link #crossOriginEmbedderPolicy(Customizer)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class CrossOriginResourcePolicyConfig {
|
public final class CrossOriginResourcePolicyConfig {
|
||||||
@ -1500,18 +1084,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows completing configuration of Cross-Origin-Resource-Policy and continuing
|
|
||||||
* configuration of headers.
|
|
||||||
* @return the {@link HeadersConfigurer} for additional configuration
|
|
||||||
* @deprecated For removal in 7.0. Use
|
|
||||||
* {@link #crossOriginResourcePolicy(Customizer)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.1", forRemoval = true)
|
|
||||||
public HeadersConfigurer<H> and() {
|
|
||||||
return HeadersConfigurer.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
@ -98,7 +99,7 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#httpBasic()
|
* @see HttpSecurity#httpBasic(Customizer)
|
||||||
*/
|
*/
|
||||||
public HttpBasicConfigurer() {
|
public HttpBasicConfigurer() {
|
||||||
realmName(DEFAULT_REALM);
|
realmName(DEFAULT_REALM);
|
||||||
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.core.authority.mapping.SimpleMappableAttributesRetriever;
|
import org.springframework.security.core.authority.mapping.SimpleMappableAttributesRetriever;
|
||||||
@ -77,7 +78,7 @@ public final class JeeConfigurer<H extends HttpSecurityBuilder<H>> extends Abstr
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#jee()
|
* @see HttpSecurity#jee(Customizer)
|
||||||
*/
|
*/
|
||||||
public JeeConfigurer() {
|
public JeeConfigurer() {
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ import java.util.List;
|
|||||||
import jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
|
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
|
||||||
@ -92,7 +92,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @see HttpSecurity#logout()
|
* @see HttpSecurity#logout(Customizer)
|
||||||
*/
|
*/
|
||||||
public LogoutConfigurer() {
|
public LogoutConfigurer() {
|
||||||
}
|
}
|
||||||
@ -145,12 +145,12 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* (i.e. log out) to protect against
|
* (i.e. log out) to protect against
|
||||||
* <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF
|
* <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF
|
||||||
* attacks</a>. If you really want to use an HTTP GET, you can use
|
* attacks</a>. If you really want to use an HTTP GET, you can use
|
||||||
* <code>logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GEt, logoutUrl));</code>
|
* <code>logoutRequestMatcher(PathPatternRequestMatcher.pathPattern(HttpMethod.GEt, logoutUrl));</code>
|
||||||
* </p>
|
* </p>
|
||||||
* @param logoutUrl the URL that will invoke logout.
|
* @param logoutUrl the URL that will invoke logout.
|
||||||
* @return the {@link LogoutConfigurer} for further customization
|
* @return the {@link LogoutConfigurer} for further customization
|
||||||
* @see #logoutRequestMatcher(RequestMatcher)
|
* @see #logoutRequestMatcher(RequestMatcher)
|
||||||
* @see HttpSecurity#csrf()
|
* @see HttpSecurity#csrf(Customizer)
|
||||||
*/
|
*/
|
||||||
public LogoutConfigurer<H> logoutUrl(String logoutUrl) {
|
public LogoutConfigurer<H> logoutUrl(String logoutUrl) {
|
||||||
this.logoutRequestMatcher = null;
|
this.logoutRequestMatcher = null;
|
||||||
@ -369,7 +369,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher createLogoutRequestMatcher(String httpMethod) {
|
private RequestMatcher createLogoutRequestMatcher(String httpMethod) {
|
||||||
return RequestMatcherFactory.matcher(HttpMethod.valueOf(httpMethod), this.logoutUrl);
|
return getRequestMatcherBuilder().matcher(HttpMethod.valueOf(httpMethod), this.logoutUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
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