Compare commits
430 Commits
cas-client
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
c516025070 | |
|
|
71e71f15ff | |
|
|
448b08c43c | |
|
|
06f87f85fc | |
|
|
f2c44b7e74 | |
|
|
94d81c32ba | |
|
|
a96a13c630 | |
|
|
06f3ebc7c2 | |
|
|
0dce0aa69e | |
|
|
8a665e1cb1 | |
|
|
dce1a94d9a | |
|
|
76fb6a4f9c | |
|
|
8d38080354 | |
|
|
be803939d8 | |
|
|
af1bbb2f32 | |
|
|
c5a5a9961b | |
|
|
6e2fbec2a4 | |
|
|
638c2d6fe4 | |
|
|
efd6dbb491 | |
|
|
905ce61e82 | |
|
|
3ba892e482 | |
|
|
62cc93399f | |
|
|
cd67d874a2 | |
|
|
46381476e9 | |
|
|
d2538f378d | |
|
|
f14d836e03 | |
|
|
e2e4ea9fa1 | |
|
|
df89820368 | |
|
|
3005cc8607 | |
|
|
e0374d61ac | |
|
|
360ff59ddd | |
|
|
59f42b7edf | |
|
|
409bd553ba | |
|
|
3ec16e8aaf | |
|
|
08bedcf889 | |
|
|
da7ff03cff | |
|
|
5aaf09b3e4 | |
|
|
fd176bc1a7 | |
|
|
9f09c15673 | |
|
|
e4c1df0280 | |
|
|
a00064d1d8 | |
|
|
21d5f37322 | |
|
|
872fc49fb7 | |
|
|
18c79fcf00 | |
|
|
9394a6e190 | |
|
|
3e99e678ca | |
|
|
2beda557e1 | |
|
|
a233009f68 | |
|
|
e7d2c87668 | |
|
|
8a972d38e1 | |
|
|
2ac1e1b7a6 | |
|
|
bca6d9b830 | |
|
|
9e89fe960a | |
|
|
15567ef2a6 | |
|
|
5b47efa407 | |
|
|
3ff317846f | |
|
|
e39d35fbd7 | |
|
|
0fbe33a7e5 | |
|
|
b531896715 | |
|
|
e3b109264c | |
|
|
81cdceca8f | |
|
|
5b5ca68d05 | |
|
|
2728f0597d | |
|
|
5bd4465298 | |
|
|
7d9ee60b73 | |
|
|
5f82143b00 | |
|
|
1fad31d8b0 | |
|
|
3d391b62b8 | |
|
|
913c412fba | |
|
|
b355b526d6 | |
|
|
858b0ca77d | |
|
|
c00ee02f44 | |
|
|
40848d251e | |
|
|
a7b7660772 | |
|
|
440f2edaa6 | |
|
|
8667f0b946 | |
|
|
60a8cb3825 | |
|
|
11a53a6fc2 | |
|
|
58a54c7372 | |
|
|
53f34e175e | |
|
|
9279ab8d54 | |
|
|
6352b7991a | |
|
|
db9f0a3301 | |
|
|
4c4202de24 | |
|
|
6f7ef142bc | |
|
|
7e34235578 | |
|
|
07a700f531 | |
|
|
31756bd6fc | |
|
|
95583500c0 | |
|
|
c096b4c82b | |
|
|
63d638b452 | |
|
|
ee21f2874a | |
|
|
24c3f92030 | |
|
|
3b312e1cff | |
|
|
7f0b42df31 | |
|
|
4d84e02c5f | |
|
|
ca5e5f1f06 | |
|
|
387e7249e0 | |
|
|
8a7e04d7cf | |
|
|
11d3c21889 | |
|
|
a51fd8f8f8 | |
|
|
1a6da20b3e | |
|
|
2a3adb4ec4 | |
|
|
a5a7d30791 | |
|
|
bab29c84f4 | |
|
|
8eaec09704 | |
|
|
da07e4815b | |
|
|
de1f05dc8b | |
|
|
1300774928 | |
|
|
f946c2845b | |
|
|
3cd4e12fa9 | |
|
|
3e5eeaabe1 | |
|
|
fdc948b8ec | |
|
|
1966a26d6f | |
|
|
c2886ea70c | |
|
|
850a6c0373 | |
|
|
764d2220d6 | |
|
|
77abda055b | |
|
|
505160b15e | |
|
|
fdab7aea5b | |
|
|
9e95c8a10c | |
|
|
f7234f9aea | |
|
|
0e4c82cc94 | |
|
|
8596db4de3 | |
|
|
ccf8b89dee | |
|
|
3f45530e0e | |
|
|
46341d3e42 | |
|
|
9fabd9fbf1 | |
|
|
be29e420c0 | |
|
|
2734d45f3e | |
|
|
601959f85c | |
|
|
bf4e1e60b6 | |
|
|
0c041d5376 | |
|
|
a7101b6cc8 | |
|
|
7ce4cb8aa5 | |
|
|
a95a98dd9b | |
|
|
a3dbe594c3 | |
|
|
49f9a4e309 | |
|
|
fd72cb6bfc | |
|
|
78b2997c5d | |
|
|
cfebf0acc7 | |
|
|
874958641a | |
|
|
691bf12697 | |
|
|
4332186ea7 | |
|
|
52274f828f | |
|
|
5c3d185e8d | |
|
|
35d611b8e8 | |
|
|
d940cfd417 | |
|
|
1d78f74b2a | |
|
|
12da0340a1 | |
|
|
e283a9a7a5 | |
|
|
1c29fa7ebd | |
|
|
7bea9bb258 | |
|
|
4ada1b1327 | |
|
|
32d14893ae | |
|
|
0f395b3a2c | |
|
|
0e750de5f5 | |
|
|
26479f3d99 | |
|
|
11e9b543e5 | |
|
|
5c2c6b00aa | |
|
|
f0bd481a13 | |
|
|
8fb8e9d0e4 | |
|
|
3213920bff | |
|
|
01812e755d | |
|
|
d35172dff9 | |
|
|
1999bd4670 | |
|
|
4f411c4342 | |
|
|
c6a46da7fa | |
|
|
c8c0d844b4 | |
|
|
cf7e09b1c4 | |
|
|
68a0cc0433 | |
|
|
c8eb5b4e5a | |
|
|
0f69d262e8 | |
|
|
748a7172f5 | |
|
|
d1c3660cda | |
|
|
78470351f6 | |
|
|
9e7ad3f046 | |
|
|
3688949646 | |
|
|
a091c2795b | |
|
|
411a105fb1 | |
|
|
bd7ebc11c7 | |
|
|
61c842124e | |
|
|
bb95fd733f | |
|
|
2b61ca1df3 | |
|
|
b61487766c | |
|
|
1f6881829b | |
|
|
a8ec3de36e | |
|
|
a4cde4359e | |
|
|
44adee82ec | |
|
|
97632483aa | |
|
|
2362481941 | |
|
|
733ce5ba5d | |
|
|
66742817cc | |
|
|
0e333ec040 | |
|
|
a09641b184 | |
|
|
28ffa12548 | |
|
|
f6f20da863 | |
|
|
22e77d2d12 | |
|
|
93dac9b3fe | |
|
|
db0b8f8a42 | |
|
|
1c5dee3edf | |
|
|
abacb75df2 | |
|
|
96f51465a8 | |
|
|
58de00e34b | |
|
|
8cc5ad182c | |
|
|
e3f532acde | |
|
|
86b93cbb26 | |
|
|
cc756cb72d | |
|
|
e2798c09cb | |
|
|
f06895bc18 | |
|
|
18d981efaa | |
|
|
080405b4c0 | |
|
|
45d4180a7f | |
|
|
77c013b03b | |
|
|
7513f94877 | |
|
|
2b1b7a142a | |
|
|
ba50664582 | |
|
|
bafe64e7cd | |
|
|
b2e1643893 | |
|
|
e155261a6b | |
|
|
c39735729d | |
|
|
2a570b26f1 | |
|
|
1d4312b64f | |
|
|
af78b8703f | |
|
|
0e943179f1 | |
|
|
72e9aa9378 | |
|
|
c5d1b1ef84 | |
|
|
40dcc8b34a | |
|
|
ba5982e1eb | |
|
|
b6f6b5de76 | |
|
|
93561a297f | |
|
|
c979e64006 | |
|
|
306ec75569 | |
|
|
a061764ca1 | |
|
|
7fbac753ee | |
|
|
15100f3c39 | |
|
|
87ac085dfd | |
|
|
a34a397a68 | |
|
|
94b23a7f2d | |
|
|
c015e226ba | |
|
|
5d18b34159 | |
|
|
ae50749c5f | |
|
|
3875c39a21 | |
|
|
b208e94b93 | |
|
|
c00da6bb81 | |
|
|
486aa66587 | |
|
|
527f60f334 | |
|
|
c06facd9e1 | |
|
|
962c8185ae | |
|
|
6280319d80 | |
|
|
2d6b80842b | |
|
|
b8f2e0a32c | |
|
|
47efae9e92 | |
|
|
ef2baa8983 | |
|
|
9d57eb3655 | |
|
|
f341f50cd5 | |
|
|
52edf95202 | |
|
|
f9202b9a8a | |
|
|
b02a122e9d | |
|
|
ccf8e718b2 | |
|
|
91dd394a08 | |
|
|
6468166c40 | |
|
|
6f84cc2356 | |
|
|
f5a0ee6987 | |
|
|
e56e0d2aa0 | |
|
|
dfb13e5397 | |
|
|
552b9f9fac | |
|
|
1e1a0ec5e8 | |
|
|
24f1f9c814 | |
|
|
059ec7d527 | |
|
|
f2ea4129bd | |
|
|
88789ef358 | |
|
|
5152f40be9 | |
|
|
1fc896c458 | |
|
|
1561da75ad | |
|
|
834531c7a6 | |
|
|
2f7729a892 | |
|
|
f998bb07c3 | |
|
|
47fb9c0fbb | |
|
|
4d1d62bd62 | |
|
|
bad68332a6 | |
|
|
2ae54e8d98 | |
|
|
6be07281d5 | |
|
|
7db200e8c6 | |
|
|
527f0c6d28 | |
|
|
7d5a9bc124 | |
|
|
92371f794a | |
|
|
9e95ee5825 | |
|
|
86a8f7395b | |
|
|
9d4cafd2c9 | |
|
|
745fda6113 | |
|
|
aa6cab7d8d | |
|
|
9b71825e1a | |
|
|
2e27e09f3b | |
|
|
b4d9570bdc | |
|
|
7cb5380e75 | |
|
|
e7292c78a0 | |
|
|
771288475f | |
|
|
ee4a05d409 | |
|
|
f1cd2441ca | |
|
|
95c5d8ee73 | |
|
|
f1908ba5fc | |
|
|
8e1a7789b1 | |
|
|
b20d4d241c | |
|
|
bc586d7b4b | |
|
|
06b566e2d6 | |
|
|
3f0a1c6883 | |
|
|
812198b6a5 | |
|
|
88d847102c | |
|
|
40291a4478 | |
|
|
184868b296 | |
|
|
5a68c92268 | |
|
|
f09ee1c0e7 | |
|
|
971d4b4854 | |
|
|
f04dedd9bb | |
|
|
53dbb48882 | |
|
|
61bd0eeb86 | |
|
|
e4b767700a | |
|
|
346374ebc8 | |
|
|
4b63e06418 | |
|
|
32963967d4 | |
|
|
9d9e5cad72 | |
|
|
598fb02dda | |
|
|
a417f78521 | |
|
|
a5e2b8ae61 | |
|
|
650cee05bc | |
|
|
e5f933754b | |
|
|
1bdc456bf4 | |
|
|
8067714256 | |
|
|
85b0454e8d | |
|
|
2eb132c0b4 | |
|
|
0022c622e1 | |
|
|
ab105cdcfa | |
|
|
1f3a745ec8 | |
|
|
ba47157062 | |
|
|
4f746b3b58 | |
|
|
d7538dfd61 | |
|
|
335d3f3a3e | |
|
|
618a99a245 | |
|
|
0d2740ec0c | |
|
|
69bba0c21a | |
|
|
f0047eb8eb | |
|
|
60b8ad70f8 | |
|
|
d46e3c6220 | |
|
|
8ff374b949 | |
|
|
e9b79194d7 | |
|
|
72685767f7 | |
|
|
bb11bfa7c8 | |
|
|
bdecba6431 | |
|
|
67b4b26819 | |
|
|
f3d7156482 | |
|
|
8bab6d1f4e | |
|
|
76ba57a541 | |
|
|
ec744b2c9f | |
|
|
4db9948c19 | |
|
|
0a7ffac846 | |
|
|
c8e50905bb | |
|
|
eaee34b361 | |
|
|
6ce10daea0 | |
|
|
f98e776869 | |
|
|
df07758a89 | |
|
|
302822f361 | |
|
|
e1e12a5f3f | |
|
|
8c77fc4eaf | |
|
|
607d53a2aa | |
|
|
70b8aa8032 | |
|
|
806672e525 | |
|
|
853450a8a6 | |
|
|
05873137dc | |
|
|
8bc89e648a | |
|
|
f1ac21943d | |
|
|
c6c106c375 | |
|
|
0a6ce18150 | |
|
|
73e2a63a5b | |
|
|
77e5340c3c | |
|
|
573976cda9 | |
|
|
dc028a6652 | |
|
|
50fc28034d | |
|
|
3c40922847 | |
|
|
d72913b53a | |
|
|
a31979920b | |
|
|
8ec71aa2c6 | |
|
|
74f0a209dd | |
|
|
f8f5b908d0 | |
|
|
d3ba9c0ae7 | |
|
|
f68281d0e4 | |
|
|
863038605f | |
|
|
f5b2275913 | |
|
|
1edef62ecb | |
|
|
7c58629958 | |
|
|
70ed5fd8bb | |
|
|
6e261e7251 | |
|
|
0652f4ee23 | |
|
|
d8980535b7 | |
|
|
dd0818b84f | |
|
|
4527671568 | |
|
|
e998985732 | |
|
|
6f7fe61780 | |
|
|
db3610123f | |
|
|
380585d391 | |
|
|
4aef368057 | |
|
|
6de80009cf | |
|
|
bec0e6bb2e | |
|
|
2a98556daa | |
|
|
f49c08ce93 | |
|
|
ec92d97518 | |
|
|
34458db530 | |
|
|
0b220c6f55 | |
|
|
39f0f29dd9 | |
|
|
d1da02f457 | |
|
|
d7ca6a098e | |
|
|
f17c4d6087 | |
|
|
a780e39ab9 | |
|
|
bef2a88603 | |
|
|
3af5683dc1 | |
|
|
5109132df3 | |
|
|
51a9192792 | |
|
|
c7e66d7df2 | |
|
|
d011f5e64a | |
|
|
17f887595f | |
|
|
324b0919b6 | |
|
|
461cdcd8fc | |
|
|
4e3f761efe | |
|
|
c61dea96bf | |
|
|
99763ab2b6 | |
|
|
7ac4c7afb7 | |
|
|
0ef575ae84 | |
|
|
887da3bffd | |
|
|
90ccc41db3 | |
|
|
80ff9857f0 |
|
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# Licensed to Apereo under one or more contributor license
|
||||
# agreements. See the NOTICE file distributed with this work
|
||||
# for additional information regarding copyright ownership.
|
||||
# Apereo licenses this file to you 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 the following location:
|
||||
#
|
||||
# http://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.
|
||||
#
|
||||
|
||||
custom: ['https://www.apereo.org/content/apereo-membership']
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": [
|
||||
"config:base",
|
||||
":preserveSemverRanges",
|
||||
":rebaseStalePrs",
|
||||
":disableRateLimiting",
|
||||
":semanticCommits",
|
||||
":semanticCommitTypeAll(renovatebot)"
|
||||
],
|
||||
"labels": ["dependencies", "bot"]
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#
|
||||
# Licensed to Apereo under one or more contributor license
|
||||
# agreements. See the NOTICE file distributed with this work
|
||||
# for additional information regarding copyright ownership.
|
||||
# Apereo licenses this file to you 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 the following location:
|
||||
#
|
||||
# http://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.
|
||||
#
|
||||
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 7
|
||||
|
||||
# Number of days of inactivity before a stale Issue or Pull Request is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 7
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: Pending
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This patch has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
This patch has been automatically closed because it has not had
|
||||
recent activity. If you wish to resume work, please re-open the pull request
|
||||
and continue as usual. Thank you for your contributions.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: pulls
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# Licensed to Apereo under one or more contributor license
|
||||
# agreements. See the NOTICE file distributed with this work
|
||||
# for additional information regarding copyright ownership.
|
||||
# Apereo licenses this file to you 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 the following location:
|
||||
#
|
||||
# http://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.
|
||||
#
|
||||
|
||||
pull_request_rules:
|
||||
- name: automatic merge by dependabot
|
||||
conditions:
|
||||
- status-success=continuous-integration/travis-ci/pr
|
||||
- status-success=WIP
|
||||
- "#changes-requested-reviews-by=0"
|
||||
- base=master
|
||||
- label=dependencies
|
||||
actions:
|
||||
merge:
|
||||
method: squash
|
||||
strict: false
|
||||
delete_head_branch:
|
||||
- name: automatic merge by renovate
|
||||
conditions:
|
||||
- status-success=continuous-integration/travis-ci/pr
|
||||
- status-success=WIP
|
||||
- "#changes-requested-reviews-by=0"
|
||||
- base=master
|
||||
- label=dependencies
|
||||
actions:
|
||||
merge:
|
||||
method: squash
|
||||
strict: false
|
||||
delete_head_branch:
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# Licensed to Jasig under one or more contributor license
|
||||
# agreements. See the NOTICE file distributed with this work
|
||||
# for additional information regarding copyright ownership.
|
||||
# Jasig licenses this file to you 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 the following location:
|
||||
#
|
||||
# http://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.
|
||||
#
|
||||
|
||||
language: java
|
||||
sudo: required
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
cache:
|
||||
directories:
|
||||
- "$HOME/.m2/repository"
|
||||
script: "mvn install --settings travis/settings.xml"
|
||||
jdk:
|
||||
- openjdk8
|
||||
env:
|
||||
global:
|
||||
- secure: "JM/FMiec3GYShrMlJQSW2QG208+V0GCAj2bsP5eF8q4yzgp6o4rT+r57KDIDD6MapRN+G1Pnl3WPcS0aQYnwOhPg4tA2De1bFUPaJltP47eHFfblpjZeHMxcauCQ6BwFFr8yuC0ORsYCW3TOK00Mxq4CRlTlg5iclzHyS/pnkLI="
|
||||
- secure: "eXfgf3v8Kw/L22DO39Y61os13bfNpop8Xpkmz+HZ1djQWavOkRn58gSg8EVjBYRPOrTuEbhEWb+s3qpx8j3qRdi6roMs9MTr5gEPTAyjTtJ/Zv1qhJ6OlEl2w5c2fRMsk5cB//mtxtZ+qMaz6sdZI2csbQ2xlhjz4AbGQL5i1lY="
|
||||
|
||||
after_success:
|
||||
- chmod -R 777 ./travis/deploy-to-sonatype.sh
|
||||
- ./travis/deploy-to-sonatype.sh
|
||||
129
NOTICE
129
NOTICE
|
|
@ -1,80 +1,101 @@
|
|||
Copyright 2010, JA-SIG, Inc.
|
||||
This project includes software developed by Jasig.
|
||||
http://www.jasig.org/
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Apereo licenses this file to you 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 the following location:
|
||||
|
||||
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:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://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
|
||||
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.
|
||||
|
||||
This project includes:
|
||||
"Java Concurrency in Practice" book annotations under Creative Commons Attribution License
|
||||
AOP alliance under Public Domain
|
||||
Apache Commons Codec under Apache License, Version 2.0
|
||||
Apache Log4j under The Apache Software License, Version 2.0
|
||||
Apache Santuario under The Apache Software License, Version 2.0
|
||||
Apache Velocity under The Apache Software License, Version 2.0
|
||||
Apache Log4j API under Apache License, Version 2.0
|
||||
Apache Log4j to SLF4J Adapter under Apache License, Version 2.0
|
||||
Apache XML Security under The Apache Software License, Version 2.0
|
||||
Apereo CAS Client for Java under Apache License Version 2.0
|
||||
asm under BSD
|
||||
asm-analysis under BSD
|
||||
asm-commons under BSD
|
||||
asm-tree under BSD
|
||||
Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs under Bouncy Castle Licence
|
||||
Bouncy Castle Provider under Bouncy Castle Licence
|
||||
catalina under Apache License, Version 2.0
|
||||
Codec under The Apache Software License, Version 2.0
|
||||
com.atlassian.confluence:confluence under Atlassian End User License
|
||||
com.atlassian.event:atlassian-event under Atlassian End User License
|
||||
com.atlassian.jira:jira-core under Atlassian End User License
|
||||
com.atlassian.osuser:atlassian-osuser under Atlassian End User License
|
||||
com.atlassian.seraph:atlassian-seraph under Atlassian End User License
|
||||
Commons Codec under The Apache Software License, Version 2.0
|
||||
commons-collections under Apache License, Version 2.0
|
||||
coyote under Apache License, Version 2.0
|
||||
Eclipse Compiler for Java(TM) under Eclipse Public License - v 2.0
|
||||
Ehcache Core under The Apache Software License, Version 2.0
|
||||
ESAPI 2.0 under BSD or Creative Commons 3.0 BY-SA
|
||||
Google Collections Library under The Apache Software License, Version 2.0
|
||||
HttpClient under Apache License
|
||||
Jasig CAS Client for Java under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Atlassian Integration under Apache License Version 2.0
|
||||
Hamcrest Core under New BSD License
|
||||
Jackson-annotations under The Apache Software License, Version 2.0
|
||||
Jackson-core under The Apache Software License, Version 2.0
|
||||
jackson-databind under The Apache Software License, Version 2.0
|
||||
Jasig CAS Client for Java - Common Tomcat Integration Support under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Core under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Distributed Proxy Storage Support:
|
||||
Memcached under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Distributed Proxy Storage Support: EhCache under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Distributed Proxy Storage Support: Memcached under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - JBoss Integration under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Jetty Container Integration under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - SAML Protocol Support under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Spring Boot Support under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Tomcat 6.x Integration under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Tomcat 7.x Integration under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Tomcat 8.5.x Integration under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Tomcat 8.x Integration under Apache License Version 2.0
|
||||
Jasig CAS Client for Java - Tomcat 9.0.x Integration under Apache License Version 2.0
|
||||
Java Servlet API under CDDL + GPLv2 with classpath exception
|
||||
JavaBeans Activation Framework (JAF) under Common Development and Distribution License (CDDL) v1.0
|
||||
JavaMail API under Common Development and Distribution License (CDDL) v1.0
|
||||
javax.annotation API under CDDL + GPLv2 with classpath exception
|
||||
JBoss Application Server Tomcat under lgpl
|
||||
JCL 1.1.1 implemented over SLF4J under MIT License
|
||||
Joda time under Apache 2
|
||||
JCL 1.2 implemented over SLF4J under MIT License
|
||||
Jetty :: Apache JSP Implementation under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Http Utility under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: IO Utility under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: JNDI Naming under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Plus under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Schemas under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Security under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Server Core under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Servlet Annotations under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Servlet Handling under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Utilities under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: Webapp Application Support under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Jetty :: XML utilities under Apache Software License - Version 2.0 or Eclipse Public License - Version 1.0
|
||||
Joda-Time under Apache License, Version 2.0
|
||||
JUL to SLF4J bridge under MIT License
|
||||
JUnit under Common Public License Version 1.0
|
||||
Lang under The Apache Software License, Version 2.0
|
||||
Log4j Implemented Over SLF4J under Apache Software Licenses
|
||||
Not Yet Commons SSL under Apache License v2
|
||||
OpenSAML-J under Apache 2
|
||||
OpenWS under Apache 2
|
||||
JUnit under Eclipse Public License 1.0
|
||||
Logback Classic Module under Eclipse Public License - v 1.0 or GNU Lesser General Public License
|
||||
Logback Core Module under Eclipse Public License - v 1.0 or GNU Lesser General Public License
|
||||
MortBay :: Apache EL :: API and Implementation under Apache License Version 2.0
|
||||
MortBay :: Apache Jasper :: JSP Implementation under Apache License Version 2.0
|
||||
SLF4J API Module under MIT License
|
||||
SLF4J Simple Binding under MIT License
|
||||
Spring Framework: Context under The Apache Software License, Version 2.0
|
||||
spring-aop under The Apache Software License, Version 2.0
|
||||
spring-asm under The Apache Software License, Version 2.0
|
||||
spring-beans under The Apache Software License, Version 2.0
|
||||
spring-context under The Apache Software License, Version 2.0
|
||||
spring-core under The Apache Software License, Version 2.0
|
||||
spring-expression under The Apache Software License, Version 2.0
|
||||
spring-test under The Apache Software License, Version 2.0
|
||||
SnakeYAML under Apache License, Version 2.0
|
||||
Spring AOP under Apache License, Version 2.0
|
||||
Spring Beans under Apache License, Version 2.0
|
||||
Spring Boot under Apache License, Version 2.0
|
||||
Spring Boot AutoConfigure under Apache License, Version 2.0
|
||||
Spring Boot Logging Starter under Apache License, Version 2.0
|
||||
Spring Boot Starter under Apache License, Version 2.0
|
||||
Spring Commons Logging Bridge under Apache License, Version 2.0
|
||||
Spring Context under Apache License, Version 2.0
|
||||
Spring Core under Apache License, Version 2.0
|
||||
Spring Expression Language (SpEL) under Apache License, Version 2.0
|
||||
Spring TestContext Framework under Apache License, Version 2.0
|
||||
Spring Web under Apache License, Version 2.0
|
||||
Spymemcached under The Apache Software License, Version 2.0
|
||||
tomcat-annotations-api under Apache License, Version 2.0
|
||||
tomcat-catalina under Apache License, Version 2.0
|
||||
Xalan Java under The Apache Software License, Version 2.0
|
||||
Xalan Java Serializer under The Apache Software License, Version 2.0
|
||||
Xerces2-j under The Apache Software License, Version 2.0
|
||||
XML Commons External Components XML APIs under The Apache Software License, Version 2.0 or The SAX License or The W3C License
|
||||
XML Commons Resolver Component under The Apache Software License, Version 2.0
|
||||
XMLTooling-J under Apache 2
|
||||
tomcat-coyote under Apache License, Version 2.0
|
||||
tomcat-el-api under Apache License, Version 2.0
|
||||
tomcat-embed-core under Apache License, Version 2.0
|
||||
tomcat-jaspic-api under Apache License, Version 2.0
|
||||
tomcat-jni under Apache License, Version 2.0
|
||||
tomcat-jsp-api under Apache License, Version 2.0
|
||||
tomcat-util-scan under Apache License, Version 2.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
BUILDING THE CAS CLIENT FOR JAVA
|
||||
|
||||
Please note that to be deployed in Maven Central, we mark a number of JARs as provided (related to JBoss and Memcache
|
||||
Clients). In order to build the clients, you must enable the commented out repositories in the appropriate pom.xml
|
||||
files in the modules (cas-client-integration-jboss and cas-client-support-distributed-memcached) or follow the
|
||||
instructions on how to install the file manually.
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<!--
|
||||
|
||||
Licensed to Jasig under one or more contributor license
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Jasig licenses this file to you under the Apache License,
|
||||
Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
====
|
||||
Licensed to Jasig under one or more contributor license
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Jasig licenses this file to you under the Apache License,
|
||||
Apereo licenses this file to you 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:
|
||||
except in compliance with the License. You may obtain a
|
||||
copy of the License at the following location:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://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
|
||||
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.
|
||||
====
|
||||
|
|
|
|||
|
|
@ -1,58 +1,42 @@
|
|||
Copyright 2010, JA-SIG, Inc.
|
||||
This project includes software developed by Jasig.
|
||||
http://www.jasig.org/
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Apereo licenses this file to you 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 the following location:
|
||||
|
||||
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:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://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
|
||||
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.
|
||||
|
||||
This project includes:
|
||||
"Java Concurrency in Practice" book annotations under Creative Commons Attribution License
|
||||
AOP alliance under Public Domain
|
||||
Apache Commons Codec under Apache License, Version 2.0
|
||||
Apache Log4j under The Apache Software License, Version 2.0
|
||||
Apache Santuario under The Apache Software License, Version 2.0
|
||||
Apache Velocity under The Apache Software License, Version 2.0
|
||||
Apache XML Security under The Apache Software License, Version 2.0
|
||||
Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs under Bouncy Castle Licence
|
||||
Bouncy Castle Provider under Bouncy Castle Licence
|
||||
Commons Codec under The Apache Software License, Version 2.0
|
||||
commons-collections under Apache License, Version 2.0
|
||||
ESAPI 2.0 under BSD or Creative Commons 3.0 BY-SA
|
||||
HttpClient under Apache License
|
||||
Hamcrest Core under New BSD License
|
||||
Jackson-annotations under The Apache Software License, Version 2.0
|
||||
Jackson-core under The Apache Software License, Version 2.0
|
||||
jackson-databind under The Apache Software License, Version 2.0
|
||||
Jasig CAS Client for Java - Core under Apache License Version 2.0
|
||||
Java Servlet API under CDDL + GPLv2 with classpath exception
|
||||
JavaBeans Activation Framework (JAF) under Common Development and Distribution License (CDDL) v1.0
|
||||
JavaMail API under Common Development and Distribution License (CDDL) v1.0
|
||||
JCL 1.1.1 implemented over SLF4J under MIT License
|
||||
Joda time under Apache 2
|
||||
JUL to SLF4J bridge under MIT License
|
||||
JUnit under Common Public License Version 1.0
|
||||
Lang under The Apache Software License, Version 2.0
|
||||
Log4j Implemented Over SLF4J under Apache Software Licenses
|
||||
Not Yet Commons SSL under Apache License v2
|
||||
OpenSAML-J under Apache 2
|
||||
OpenWS under Apache 2
|
||||
JCL 1.2 implemented over SLF4J under MIT License
|
||||
JUnit under Eclipse Public License 1.0
|
||||
SLF4J API Module under MIT License
|
||||
SLF4J Simple Binding under MIT License
|
||||
spring-aop under The Apache Software License, Version 2.0
|
||||
spring-asm under The Apache Software License, Version 2.0
|
||||
spring-beans under The Apache Software License, Version 2.0
|
||||
spring-context under The Apache Software License, Version 2.0
|
||||
spring-core under The Apache Software License, Version 2.0
|
||||
spring-expression under The Apache Software License, Version 2.0
|
||||
spring-test under The Apache Software License, Version 2.0
|
||||
Xalan Java under The Apache Software License, Version 2.0
|
||||
Xalan Java Serializer under The Apache Software License, Version 2.0
|
||||
Xerces2-j under The Apache Software License, Version 2.0
|
||||
XML Commons External Components XML APIs under The Apache Software License, Version 2.0 or The SAX License or The W3C License
|
||||
XML Commons Resolver Component under The Apache Software License, Version 2.0
|
||||
XMLTooling-J under Apache 2
|
||||
Spring AOP under Apache License, Version 2.0
|
||||
Spring Beans under Apache License, Version 2.0
|
||||
Spring Commons Logging Bridge under Apache License, Version 2.0
|
||||
Spring Context under Apache License, Version 2.0
|
||||
Spring Core under Apache License, Version 2.0
|
||||
Spring Expression Language (SpEL) under Apache License, Version 2.0
|
||||
Spring TestContext Framework under Apache License, Version 2.0
|
||||
Spring Web under Apache License, Version 2.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,51 @@
|
|||
<!--
|
||||
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Apereo licenses this file to you 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 the following location:
|
||||
|
||||
http://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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.3</version>
|
||||
<version>3.6.2-SNAPSHOT</version>
|
||||
<artifactId>cas-client</artifactId>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<artifactId>cas-client-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Jasig CAS Client for Java - Core</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>xml-security</groupId>
|
||||
|
|
@ -20,27 +56,10 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.opensaml</groupId>
|
||||
<artifactId>opensaml</artifactId>
|
||||
<version>${opensaml.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.4</version>
|
||||
<type>jar</type>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
|
|
@ -48,30 +67,27 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
|
@ -79,7 +95,7 @@
|
|||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>1.2.15</version>
|
||||
<version>1.2.17</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>jmxri</artifactId>
|
||||
|
|
@ -97,8 +113,4 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring.version>3.1.3.RELEASE</spring.version>
|
||||
<opensaml.version>2.5.1-1</opensaml.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client;
|
||||
|
||||
/**
|
||||
* Simple enumeration to hold/capture some of the standard request parameters used by the various protocols.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public enum Protocol {
|
||||
|
||||
CAS1("ticket", "service"), CAS2(CAS1), CAS3(CAS2), SAML11("SAMLart", "TARGET");
|
||||
|
||||
private final String artifactParameterName;
|
||||
|
||||
private final String serviceParameterName;
|
||||
|
||||
private Protocol(final String artifactParameterName, final String serviceParameterName) {
|
||||
this.artifactParameterName = artifactParameterName;
|
||||
this.serviceParameterName = serviceParameterName;
|
||||
}
|
||||
|
||||
private Protocol(final Protocol protocol) {
|
||||
this(protocol.getArtifactParameterName(), protocol.getServiceParameterName());
|
||||
}
|
||||
|
||||
public String getArtifactParameterName() {
|
||||
return this.artifactParameterName;
|
||||
}
|
||||
|
||||
public String getServiceParameterName() {
|
||||
return this.serviceParameterName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -96,11 +96,13 @@ public class AttributePrincipalImpl extends SimplePrincipal implements Attribute
|
|||
CommonUtils.assertNotNull(this.attributes, "attributes cannot be null.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
public String getProxyTicketFor(String service) {
|
||||
@Override
|
||||
public String getProxyTicketFor(final String service) {
|
||||
if (proxyGrantingTicket != null) {
|
||||
return this.proxyRetriever.getProxyTicketIdFor(this.proxyGrantingTicket, service);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,20 +18,25 @@
|
|||
*/
|
||||
package org.jasig.cas.client.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.ReflectUtils;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Filter implementation to intercept all requests and attempt to authenticate
|
||||
* the user by redirecting them to CAS (unless the user has a ticket).
|
||||
|
|
@ -41,6 +46,7 @@ import org.jasig.cas.client.validation.Assertion;
|
|||
* <li><code>casServerLoginUrl</code> - the url to log into CAS, i.e. https://cas.rutgers.edu/login</li>
|
||||
* <li><code>renew</code> - true/false on whether to use renew or not.</li>
|
||||
* <li><code>gateway</code> - true/false on whether to use gateway or not.</li>
|
||||
* <li><code>method</code> - the method used by the CAS server to send the user back to the application (redirect or post).</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Please see AbstractCasFilter for additional properties.</p>
|
||||
|
|
@ -65,37 +71,59 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
*/
|
||||
private boolean gateway = false;
|
||||
|
||||
/**
|
||||
* The method used by the CAS server to send the user back to the application.
|
||||
*/
|
||||
private String method;
|
||||
|
||||
private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
|
||||
|
||||
private AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
|
||||
|
||||
|
||||
private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass = null;
|
||||
|
||||
|
||||
private String internalIp = null;
|
||||
|
||||
private static final String X_REAL_IP = "x-real-ip";
|
||||
|
||||
private static final Map<String, Class<? extends UrlPatternMatcherStrategy>> PATTERN_MATCHER_TYPES =
|
||||
new HashMap<String, Class<? extends UrlPatternMatcherStrategy>>();
|
||||
|
||||
new HashMap<String, Class<? extends UrlPatternMatcherStrategy>>();
|
||||
|
||||
static {
|
||||
PATTERN_MATCHER_TYPES.put("CONTAINS", ContainsPatternUrlPatternMatcherStrategy.class);
|
||||
PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);
|
||||
PATTERN_MATCHER_TYPES.put("FULL_REGEX", EntireRegionRegexUrlPatternMatcherStrategy.class);
|
||||
PATTERN_MATCHER_TYPES.put("EXACT", ExactUrlPatternMatcherStrategy.class);
|
||||
}
|
||||
|
||||
|
||||
public AuthenticationFilter() {
|
||||
this(Protocol.CAS2);
|
||||
}
|
||||
|
||||
protected AuthenticationFilter(final Protocol protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
|
||||
if (!isIgnoreInitConfiguration()) {
|
||||
super.initInternal(filterConfig);
|
||||
setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));
|
||||
logger.trace("Loaded CasServerLoginUrl parameter: {}", this.casServerLoginUrl);
|
||||
setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
|
||||
logger.trace("Loaded renew parameter: {}", this.renew);
|
||||
setGateway(parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false")));
|
||||
logger.trace("Loaded gateway parameter: {}", this.gateway);
|
||||
|
||||
final String ignorePattern = getPropertyFromInitParams(filterConfig, "ignorePattern", null);
|
||||
logger.trace("Loaded ignorePattern parameter: {}", ignorePattern);
|
||||
|
||||
final String ignoreUrlPatternType = getPropertyFromInitParams(filterConfig, "ignoreUrlPatternType", "REGEX");
|
||||
logger.trace("Loaded ignoreUrlPatternType parameter: {}", ignoreUrlPatternType);
|
||||
|
||||
|
||||
final String loginUrl = getString(ConfigurationKeys.CAS_SERVER_LOGIN_URL);
|
||||
if (loginUrl != null) {
|
||||
setCasServerLoginUrl(loginUrl);
|
||||
} else {
|
||||
setCasServerUrlPrefix(getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX));
|
||||
}
|
||||
|
||||
setRenew(getBoolean(ConfigurationKeys.RENEW));
|
||||
setGateway(getBoolean(ConfigurationKeys.GATEWAY));
|
||||
setMethod(getString(ConfigurationKeys.METHOD));
|
||||
setInternalIp(getString(ConfigurationKeys.INTERNAL_IP));
|
||||
|
||||
final String ignorePattern = getString(ConfigurationKeys.IGNORE_PATTERN);
|
||||
final String ignoreUrlPatternType = getString(ConfigurationKeys.IGNORE_URL_PATTERN_TYPE);
|
||||
|
||||
if (ignorePattern != null) {
|
||||
final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
|
||||
if (ignoreUrlMatcherClass != null) {
|
||||
|
|
@ -112,15 +140,14 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
|
||||
}
|
||||
}
|
||||
|
||||
final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null);
|
||||
|
||||
final Class<? extends GatewayResolver> gatewayStorageClass = getClass(ConfigurationKeys.GATEWAY_STORAGE_CLASS);
|
||||
|
||||
if (gatewayStorageClass != null) {
|
||||
this.gatewayStorage = ReflectUtils.newInstance(gatewayStorageClass);
|
||||
setGatewayStorage(ReflectUtils.newInstance(gatewayStorageClass));
|
||||
}
|
||||
|
||||
final String authenticationRedirectStrategyClass = getPropertyFromInitParams(filterConfig,
|
||||
"authenticationRedirectStrategyClass", null);
|
||||
|
||||
final Class<? extends AuthenticationRedirectStrategy> authenticationRedirectStrategyClass = getClass(ConfigurationKeys.AUTHENTICATION_REDIRECT_STRATEGY_CLASS);
|
||||
|
||||
if (authenticationRedirectStrategyClass != null) {
|
||||
this.authenticationRedirectStrategy = ReflectUtils.newInstance(authenticationRedirectStrategyClass);
|
||||
|
|
@ -128,23 +155,37 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");
|
||||
|
||||
final String message = String.format(
|
||||
"one of %s and %s must not be null.",
|
||||
ConfigurationKeys.CAS_SERVER_LOGIN_URL.getName(),
|
||||
ConfigurationKeys.CAS_SERVER_URL_PREFIX.getName());
|
||||
|
||||
CommonUtils.assertNotNull(this.casServerLoginUrl, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
|
||||
if (isInternalRequest(request)) {
|
||||
logger.debug("Request is ignored [internal].");
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRequestUrlExcluded(request)) {
|
||||
logger.debug("Request is ignored.");
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final HttpSession session = request.getSession(false);
|
||||
final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
|
||||
|
||||
|
|
@ -175,7 +216,7 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
logger.debug("Constructed service url: {}", modifiedServiceUrl);
|
||||
|
||||
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
|
||||
getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
|
||||
getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway, this.method);
|
||||
|
||||
logger.debug("redirecting to \"{}\"", urlToRedirectTo);
|
||||
this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
|
||||
|
|
@ -189,19 +230,41 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
this.gateway = gateway;
|
||||
}
|
||||
|
||||
public void setMethod(final String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public final void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
setCasServerLoginUrl(CommonUtils.addTrailingSlash(casServerUrlPrefix) + "login");
|
||||
}
|
||||
|
||||
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
|
||||
this.casServerLoginUrl = casServerLoginUrl;
|
||||
}
|
||||
|
||||
public void setInternalIp(String internalIp) {
|
||||
this.internalIp = internalIp;
|
||||
}
|
||||
|
||||
public final void setGatewayStorage(final GatewayResolver gatewayStorage) {
|
||||
this.gatewayStorage = gatewayStorage;
|
||||
}
|
||||
|
||||
|
||||
private boolean isInternalRequest(final HttpServletRequest request) {
|
||||
if (this.internalIp == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String realIp = request.getHeader(X_REAL_IP);
|
||||
|
||||
return this.internalIp.equals(realIp);
|
||||
}
|
||||
|
||||
private boolean isRequestUrlExcluded(final HttpServletRequest request) {
|
||||
if (this.ignoreUrlPatternMatcherStrategyClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
final StringBuffer urlBuffer = request.getRequestURL();
|
||||
if (request.getQueryString() != null) {
|
||||
urlBuffer.append("?").append(request.getQueryString());
|
||||
|
|
@ -209,4 +272,10 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
final String requestUri = urlBuffer.toString();
|
||||
return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
|
||||
}
|
||||
|
||||
public final void setIgnoreUrlPatternMatcherStrategyClass(
|
||||
final UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass) {
|
||||
this.ignoreUrlPatternMatcherStrategyClass = ignoreUrlPatternMatcherStrategyClass;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -28,10 +28,12 @@ public final class ContainsPatternUrlPatternMatcherStrategy implements UrlPatter
|
|||
|
||||
private String pattern;
|
||||
|
||||
@Override
|
||||
public boolean matches(final String url) {
|
||||
return url.contains(this.pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -30,8 +30,9 @@ import javax.servlet.http.HttpServletResponse;
|
|||
*/
|
||||
public final class DefaultAuthenticationRedirectStrategy implements AuthenticationRedirectStrategy {
|
||||
|
||||
@Override
|
||||
public void redirect(final HttpServletRequest request, final HttpServletResponse response,
|
||||
final String potentialRedirectUrl) throws IOException {
|
||||
final String potentialRedirectUrl) throws IOException {
|
||||
response.sendRedirect(potentialRedirectUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -25,6 +25,7 @@ public final class DefaultGatewayResolverImpl implements GatewayResolver {
|
|||
|
||||
public static final String CONST_CAS_GATEWAY = "_const_cas_gateway_";
|
||||
|
||||
@Override
|
||||
public boolean hasGatewayedAlready(final HttpServletRequest request, final String serviceUrl) {
|
||||
final HttpSession session = request.getSession(false);
|
||||
|
||||
|
|
@ -33,10 +34,10 @@ public final class DefaultGatewayResolverImpl implements GatewayResolver {
|
|||
}
|
||||
|
||||
final boolean result = session.getAttribute(CONST_CAS_GATEWAY) != null;
|
||||
session.removeAttribute(CONST_CAS_GATEWAY);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String storeGatewayInformation(final HttpServletRequest request, final String serviceUrl) {
|
||||
request.getSession(true).setAttribute(CONST_CAS_GATEWAY, "yes");
|
||||
return serviceUrl;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.authentication;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A pattern matcher that looks inside the url to find the pattern, that
|
||||
* is assumed to have been specified via regular expressions syntax.
|
||||
* The match behavior is based on {@link Matcher#matches()}:
|
||||
* Attempts to match the entire region against the pattern.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.5
|
||||
*/
|
||||
public final class EntireRegionRegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
|
||||
|
||||
private Pattern pattern;
|
||||
|
||||
public EntireRegionRegexUrlPatternMatcherStrategy() {
|
||||
}
|
||||
|
||||
public EntireRegionRegexUrlPatternMatcherStrategy(final String pattern) {
|
||||
this.setPattern(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final String url) {
|
||||
return this.pattern.matcher(url).matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -28,11 +28,19 @@ package org.jasig.cas.client.authentication;
|
|||
public final class ExactUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
|
||||
|
||||
private String pattern;
|
||||
|
||||
|
||||
public ExactUrlPatternMatcherStrategy() {}
|
||||
|
||||
public ExactUrlPatternMatcherStrategy(final String pattern) {
|
||||
this.setPattern(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final String url) {
|
||||
return url.equals(this.pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -34,8 +34,9 @@ public final class FacesCompatibleAuthenticationRedirectStrategy implements Auth
|
|||
|
||||
private static final String FACES_PARTIAL_AJAX_PARAMETER = "javax.faces.partial.ajax";
|
||||
|
||||
@Override
|
||||
public void redirect(final HttpServletRequest request, final HttpServletResponse response,
|
||||
final String potentialRedirectUrl) throws IOException {
|
||||
final String potentialRedirectUrl) throws IOException {
|
||||
|
||||
if (CommonUtils.isNotBlank(request.getParameter(FACES_PARTIAL_AJAX_PARAMETER))) {
|
||||
// this is an ajax request - redirect ajaxly
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,23 +18,39 @@
|
|||
*/
|
||||
package org.jasig.cas.client.authentication;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A pattern matcher that looks inside the url to find the pattern,. that
|
||||
* A pattern matcher that looks inside the url to find the pattern, that
|
||||
* is assumed to have been specified via regular expressions syntax.
|
||||
*
|
||||
* The match behavior is based on {@link Matcher#find()}:
|
||||
* Attempts to find the next subsequence of the input sequence that matches
|
||||
* the pattern. This method starts at the beginning of this matcher's region, or, if
|
||||
* a previous invocation of the method was successful and the matcher has
|
||||
* not since been reset, at the first character not matched by the previous
|
||||
* match.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public final class RegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
|
||||
|
||||
private Pattern pattern;
|
||||
|
||||
|
||||
public RegexUrlPatternMatcherStrategy() {
|
||||
}
|
||||
|
||||
public RegexUrlPatternMatcherStrategy(final String pattern) {
|
||||
this.setPattern(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final String url) {
|
||||
return this.pattern.matcher(url).find();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -49,18 +49,22 @@ public final class SimpleGroup extends SimplePrincipal implements Group {
|
|||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addMember(final Principal user) {
|
||||
return this.members.add(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMember(final Principal member) {
|
||||
return this.members.contains(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<? extends Principal> members() {
|
||||
return Collections.enumeration(this.members);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMember(final Principal user) {
|
||||
return this.members.remove(user);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -47,6 +47,7 @@ public class SimplePrincipal implements Principal, Serializable {
|
|||
CommonUtils.assertNotNull(this.name, "name cannot be null.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.ReflectUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Base class to provide most of the boiler-plate code (i.e. checking for proper values, returning defaults, etc.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public abstract class BaseConfigurationStrategy implements ConfigurationStrategy {
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public final boolean getBoolean(final ConfigurationKey<Boolean> configurationKey) {
|
||||
return getValue(configurationKey, new Parser<Boolean>() {
|
||||
@Override
|
||||
public Boolean parse(final String value) {
|
||||
return CommonUtils.toBoolean(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final long getLong(final ConfigurationKey<Long> configurationKey) {
|
||||
return getValue(configurationKey, new Parser<Long>() {
|
||||
@Override
|
||||
public Long parse(final String value) {
|
||||
return CommonUtils.toLong(value, configurationKey.getDefaultValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getInt(final ConfigurationKey<Integer> configurationKey) {
|
||||
return getValue(configurationKey, new Parser<Integer>() {
|
||||
@Override
|
||||
public Integer parse(final String value) {
|
||||
return CommonUtils.toInt(value, configurationKey.getDefaultValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getString(final ConfigurationKey<String> configurationKey) {
|
||||
return getValue(configurationKey, new Parser<String>() {
|
||||
@Override
|
||||
public String parse(final String value) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Class<? extends T> getClass(final ConfigurationKey<Class<? extends T>> configurationKey) {
|
||||
return getValue(configurationKey, new Parser<Class<? extends T>>() {
|
||||
@Override
|
||||
public Class<? extends T> parse(final String value) {
|
||||
try {
|
||||
return ReflectUtils.loadClass(value);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return configurationKey.getDefaultValue();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> T getValue(final ConfigurationKey<T> configurationKey, final Parser<T> parser) {
|
||||
final String value = getWithCheck(configurationKey);
|
||||
|
||||
if (CommonUtils.isBlank(value)) {
|
||||
logger.trace("No value found for property {}, returning default {}", configurationKey.getName(), configurationKey.getDefaultValue());
|
||||
return configurationKey.getDefaultValue();
|
||||
} else {
|
||||
logger.trace("Loaded property {} with value {}", configurationKey.getName(), configurationKey.getDefaultValue());
|
||||
}
|
||||
|
||||
return parser.parse(value);
|
||||
}
|
||||
|
||||
private String getWithCheck(final ConfigurationKey configurationKey) {
|
||||
CommonUtils.assertNotNull(configurationKey, "configurationKey cannot be null");
|
||||
|
||||
return get(configurationKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the String value for this key. Returns null if there is no value.
|
||||
*
|
||||
* @param configurationKey the key to retrieve. MUST NOT BE NULL.
|
||||
* @return the String if its found, null otherwise.
|
||||
*/
|
||||
protected abstract String get(ConfigurationKey configurationKey);
|
||||
|
||||
private interface Parser<T> {
|
||||
|
||||
T parse(String value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
|
||||
/**
|
||||
* Holder class to represent a particular configuration key and its optional default value.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public final class ConfigurationKey<E> {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final E defaultValue;
|
||||
|
||||
public ConfigurationKey(final String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
public ConfigurationKey(final String name, final E defaultValue) {
|
||||
CommonUtils.assertNotNull(name, "name must not be null.");
|
||||
this.name = name;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* The referencing name of the configuration key (i.e. what you would use to look it up in your configuration strategy)
|
||||
*
|
||||
* @return the name. MUST NOT BE NULL.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The (optional) default value to use when this configuration key is not set. If a value is provided it should be used. A <code>null</code> value indicates that there is no default.
|
||||
*
|
||||
* @return the default value or null.
|
||||
*/
|
||||
public E getDefaultValue() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.authentication.AuthenticationRedirectStrategy;
|
||||
import org.jasig.cas.client.authentication.DefaultGatewayResolverImpl;
|
||||
import org.jasig.cas.client.authentication.GatewayResolver;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl;
|
||||
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
|
||||
/**
|
||||
* Holder interface for all known configuration keys.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public interface ConfigurationKeys {
|
||||
|
||||
ConfigurationKey<String> ARTIFACT_PARAMETER_NAME = new ConfigurationKey<String>("artifactParameterName", Protocol.CAS2.getArtifactParameterName());
|
||||
ConfigurationKey<String> SERVER_NAME = new ConfigurationKey<String>("serverName", null);
|
||||
ConfigurationKey<String> SERVICE = new ConfigurationKey<String>("service");
|
||||
ConfigurationKey<Boolean> RENEW = new ConfigurationKey<Boolean>("renew", Boolean.FALSE);
|
||||
ConfigurationKey<String> LOGOUT_PARAMETER_NAME = new ConfigurationKey<String>("logoutParameterName", "logoutRequest");
|
||||
ConfigurationKey<Boolean> ARTIFACT_PARAMETER_OVER_POST = new ConfigurationKey<Boolean>("artifactParameterOverPost", Boolean.FALSE);
|
||||
ConfigurationKey<Boolean> EAGERLY_CREATE_SESSIONS = new ConfigurationKey<Boolean>("eagerlyCreateSessions", Boolean.TRUE);
|
||||
ConfigurationKey<Boolean> ENCODE_SERVICE_URL = new ConfigurationKey<Boolean>("encodeServiceUrl", Boolean.TRUE);
|
||||
ConfigurationKey<String> SSL_CONFIG_FILE = new ConfigurationKey<String>("sslConfigFile", null);
|
||||
ConfigurationKey<String> ROLE_ATTRIBUTE = new ConfigurationKey<String>("roleAttribute", null);
|
||||
ConfigurationKey<Boolean> IGNORE_CASE = new ConfigurationKey<Boolean>("ignoreCase", Boolean.FALSE);
|
||||
ConfigurationKey<String> CAS_SERVER_LOGIN_URL = new ConfigurationKey<String>("casServerLoginUrl", null);
|
||||
ConfigurationKey<Boolean> GATEWAY = new ConfigurationKey<Boolean>("gateway", Boolean.FALSE);
|
||||
ConfigurationKey<String> METHOD = new ConfigurationKey<String>("method", null);
|
||||
ConfigurationKey<Class<? extends AuthenticationRedirectStrategy>> AUTHENTICATION_REDIRECT_STRATEGY_CLASS = new ConfigurationKey<Class<? extends AuthenticationRedirectStrategy>>("authenticationRedirectStrategyClass", null);
|
||||
ConfigurationKey<Class<? extends GatewayResolver>> GATEWAY_STORAGE_CLASS = new ConfigurationKey<Class<? extends GatewayResolver>>("gatewayStorageClass", DefaultGatewayResolverImpl.class);
|
||||
ConfigurationKey<String> CAS_SERVER_URL_PREFIX = new ConfigurationKey<String>("casServerUrlPrefix", null);
|
||||
ConfigurationKey<String> ENCODING = new ConfigurationKey<String>("encoding", null);
|
||||
ConfigurationKey<Long> TOLERANCE = new ConfigurationKey<Long>("tolerance", 1000L);
|
||||
ConfigurationKey<String> PRIVATE_KEY_PATH = new ConfigurationKey<String>("privateKeyPath", null);
|
||||
ConfigurationKey<String> PRIVATE_KEY_ALGORITHM = new ConfigurationKey<String>("privateKeyAlgorithm", "RSA");
|
||||
|
||||
/**
|
||||
* @deprecated As of 3.4. This constant is not used by the client and will
|
||||
* be removed in future versions.
|
||||
*/
|
||||
@Deprecated
|
||||
ConfigurationKey<Boolean> DISABLE_XML_SCHEMA_VALIDATION = new ConfigurationKey<Boolean>("disableXmlSchemaValidation", Boolean.FALSE);
|
||||
ConfigurationKey<String> INTERNAL_IP = new ConfigurationKey<String>("internalIp", null);
|
||||
ConfigurationKey<String> IGNORE_PATTERN = new ConfigurationKey<String>("ignorePattern", null);
|
||||
ConfigurationKey<String> IGNORE_URL_PATTERN_TYPE = new ConfigurationKey<String>("ignoreUrlPatternType", "REGEX");
|
||||
ConfigurationKey<Class<? extends HostnameVerifier>> HOSTNAME_VERIFIER = new ConfigurationKey<Class<? extends HostnameVerifier>>("hostnameVerifier", null);
|
||||
ConfigurationKey<String> HOSTNAME_VERIFIER_CONFIG = new ConfigurationKey<String>("hostnameVerifierConfig", null);
|
||||
ConfigurationKey<Boolean> EXCEPTION_ON_VALIDATION_FAILURE = new ConfigurationKey<Boolean>("exceptionOnValidationFailure", Boolean.TRUE);
|
||||
ConfigurationKey<Boolean> REDIRECT_AFTER_VALIDATION = new ConfigurationKey<Boolean>("redirectAfterValidation", Boolean.TRUE);
|
||||
ConfigurationKey<Boolean> USE_SESSION = new ConfigurationKey<Boolean>("useSession", Boolean.TRUE);
|
||||
ConfigurationKey<String> SECRET_KEY = new ConfigurationKey<String>("secretKey", null);
|
||||
ConfigurationKey<String> CIPHER_ALGORITHM = new ConfigurationKey<String>("cipherAlgorithm", "DESede");
|
||||
ConfigurationKey<String> PROXY_RECEPTOR_URL = new ConfigurationKey<String>("proxyReceptorUrl", null);
|
||||
ConfigurationKey<Class<? extends ProxyGrantingTicketStorage>> PROXY_GRANTING_TICKET_STORAGE_CLASS = new ConfigurationKey<Class<? extends ProxyGrantingTicketStorage>>("proxyGrantingTicketStorageClass", ProxyGrantingTicketStorageImpl.class);
|
||||
ConfigurationKey<Integer> MILLIS_BETWEEN_CLEAN_UPS = new ConfigurationKey<Integer>("millisBetweenCleanUps", 60000);
|
||||
ConfigurationKey<Boolean> ACCEPT_ANY_PROXY = new ConfigurationKey<Boolean>("acceptAnyProxy", Boolean.FALSE);
|
||||
ConfigurationKey<String> ALLOWED_PROXY_CHAINS = new ConfigurationKey<String>("allowedProxyChains", null);
|
||||
ConfigurationKey<Class<? extends Cas20ServiceTicketValidator>> TICKET_VALIDATOR_CLASS = new ConfigurationKey<Class<? extends Cas20ServiceTicketValidator>>("ticketValidatorClass", null);
|
||||
ConfigurationKey<String> PROXY_CALLBACK_URL = new ConfigurationKey<String>("proxyCallbackUrl", null);
|
||||
ConfigurationKey<String> RELAY_STATE_PARAMETER_NAME = new ConfigurationKey<String>("relayStateParameterName", "RelayState");
|
||||
ConfigurationKey<String> LOGOUT_CALLBACK_PATH = new ConfigurationKey<String>("logoutCallbackPath", null);
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
||||
/**
|
||||
* Abstraction to allow for pluggable methods for retrieving filter configuration.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public interface ConfigurationStrategy {
|
||||
|
||||
/**
|
||||
* Retrieves the value for the provided {@param configurationKey}, falling back to the {@param configurationKey}'s {@link ConfigurationKey#getDefaultValue()} if nothing can be found.
|
||||
*
|
||||
* @param configurationKey the configuration key. MUST NOT BE NULL.
|
||||
* @return the configured value, or the default value.
|
||||
*/
|
||||
boolean getBoolean(ConfigurationKey<Boolean> configurationKey);
|
||||
|
||||
/**
|
||||
* Retrieves the value for the provided {@param configurationKey}, falling back to the {@param configurationKey}'s {@link ConfigurationKey#getDefaultValue()} if nothing can be found.
|
||||
*
|
||||
* @param configurationKey the configuration key. MUST NOT BE NULL.
|
||||
* @return the configured value, or the default value.
|
||||
*/
|
||||
String getString(ConfigurationKey<String> configurationKey);
|
||||
|
||||
/**
|
||||
* Retrieves the value for the provided {@param configurationKey}, falling back to the {@param configurationKey}'s {@link ConfigurationKey#getDefaultValue()} if nothing can be found.
|
||||
*
|
||||
* @param configurationKey the configuration key. MUST NOT BE NULL.
|
||||
* @return the configured value, or the default value.
|
||||
*/
|
||||
long getLong(ConfigurationKey<Long> configurationKey);
|
||||
|
||||
/**
|
||||
* Retrieves the value for the provided {@param configurationKey}, falling back to the {@param configurationKey}'s {@link ConfigurationKey#getDefaultValue()} if nothing can be found.
|
||||
*
|
||||
* @param configurationKey the configuration key. MUST NOT BE NULL.
|
||||
* @return the configured value, or the default value.
|
||||
*/
|
||||
int getInt(ConfigurationKey<Integer> configurationKey);
|
||||
|
||||
/**
|
||||
* Retrieves the value for the provided {@param configurationKey}, falling back to the {@param configurationKey}'s {@link ConfigurationKey#getDefaultValue()} if nothing can be found.
|
||||
*
|
||||
* @param configurationKey the configuration key. MUST NOT BE NULL.
|
||||
* @return the configured value, or the default value.
|
||||
*/
|
||||
<T> Class<? extends T> getClass(ConfigurationKey<Class<? extends T>> configurationKey);
|
||||
|
||||
/**
|
||||
* Initializes the strategy. This must be called before calling any of the "get" methods.
|
||||
*
|
||||
* @param filterConfig the filter configuration object.
|
||||
* @param filterClazz the filter
|
||||
*/
|
||||
void init(FilterConfig filterConfig, Class<? extends Filter> filterClazz);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Enumeration to map simple names to the underlying classes so that deployers can reference the simple name in the
|
||||
* <code>web.xml</code> instead of the fully qualified class name.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public enum ConfigurationStrategyName {
|
||||
|
||||
DEFAULT(LegacyConfigurationStrategyImpl.class), JNDI(JndiConfigurationStrategyImpl.class), WEB_XML(WebXmlConfigurationStrategyImpl.class),
|
||||
PROPERTY_FILE(PropertiesConfigurationStrategyImpl.class), SYSTEM_PROPERTIES(SystemPropertiesConfigurationStrategyImpl.class);
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationStrategyName.class);
|
||||
|
||||
private final Class<? extends ConfigurationStrategy> configurationStrategyClass;
|
||||
|
||||
private ConfigurationStrategyName(final Class<? extends ConfigurationStrategy> configurationStrategyClass) {
|
||||
this.configurationStrategyClass = configurationStrategyClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static helper method that will resolve a simple string to either an enum value or a {@link org.jasig.cas.client.configuration.ConfigurationStrategy} class.
|
||||
*
|
||||
* @param value the value to attempt to resolve.
|
||||
* @return the underlying class that this maps to (either via simple name or fully qualified class name).
|
||||
*/
|
||||
public static Class<? extends ConfigurationStrategy> resolveToConfigurationStrategy(final String value) {
|
||||
if (CommonUtils.isBlank(value)) {
|
||||
return DEFAULT.configurationStrategyClass;
|
||||
}
|
||||
|
||||
for (final ConfigurationStrategyName csn : values()) {
|
||||
if (csn.name().equalsIgnoreCase(value)) {
|
||||
return csn.configurationStrategyClass;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final Class<?> clazz = Class.forName(value);
|
||||
|
||||
if (ConfigurationStrategy.class.isAssignableFrom(clazz)) {
|
||||
return (Class<? extends ConfigurationStrategy>) clazz;
|
||||
}
|
||||
} catch (final ClassNotFoundException e) {
|
||||
LOGGER.error("Unable to locate strategy {} by name or class name. Using default strategy instead.", value, e);
|
||||
}
|
||||
|
||||
return DEFAULT.configurationStrategyClass;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
||||
/**
|
||||
* Loads configuration information from JNDI, using the <code>defaultValue</code> if it can't.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public class JndiConfigurationStrategyImpl extends BaseConfigurationStrategy {
|
||||
|
||||
private static final String ENVIRONMENT_PREFIX = "java:comp/env/cas/";
|
||||
|
||||
private final String environmentPrefix;
|
||||
|
||||
private InitialContext context;
|
||||
|
||||
private String simpleFilterName;
|
||||
|
||||
public JndiConfigurationStrategyImpl() {
|
||||
this(ENVIRONMENT_PREFIX);
|
||||
}
|
||||
|
||||
public JndiConfigurationStrategyImpl(final String environmentPrefix) {
|
||||
this.environmentPrefix = environmentPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final String get(final ConfigurationKey configurationKey) {
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String propertyName = configurationKey.getName();
|
||||
final String filterValue = loadFromContext(context, this.environmentPrefix + this.simpleFilterName + "/" + propertyName);
|
||||
|
||||
if (CommonUtils.isNotBlank(filterValue)) {
|
||||
logger.info("Property [{}] loaded from JNDI Filter Specific Property with value [{}]", propertyName, filterValue);
|
||||
return filterValue;
|
||||
}
|
||||
|
||||
final String rootValue = loadFromContext(context, this.environmentPrefix + propertyName);
|
||||
|
||||
if (CommonUtils.isNotBlank(rootValue)) {
|
||||
logger.info("Property [{}] loaded from JNDI with value [{}]", propertyName, rootValue);
|
||||
return rootValue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String loadFromContext(final InitialContext context, final String path) {
|
||||
try {
|
||||
return (String) context.lookup(path);
|
||||
} catch (final NamingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void init(final FilterConfig filterConfig, final Class<? extends Filter> clazz) {
|
||||
this.simpleFilterName = clazz.getSimpleName();
|
||||
try {
|
||||
this.context = new InitialContext();
|
||||
} catch (final NamingException e) {
|
||||
logger.error("Unable to create InitialContext. No properties can be loaded via JNDI.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
||||
/**
|
||||
* Replicates the original behavior by checking the {@link org.jasig.cas.client.configuration.WebXmlConfigurationStrategyImpl} first, and then
|
||||
* the {@link org.jasig.cas.client.configuration.JndiConfigurationStrategyImpl} before using the <code>defaultValue</code>.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public final class LegacyConfigurationStrategyImpl extends BaseConfigurationStrategy {
|
||||
|
||||
private final WebXmlConfigurationStrategyImpl webXmlConfigurationStrategy = new WebXmlConfigurationStrategyImpl();
|
||||
|
||||
private final JndiConfigurationStrategyImpl jndiConfigurationStrategy = new JndiConfigurationStrategyImpl();
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig, final Class<? extends Filter> filterClazz) {
|
||||
this.webXmlConfigurationStrategy.init(filterConfig, filterClazz);
|
||||
this.jndiConfigurationStrategy.init(filterConfig, filterClazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String get(final ConfigurationKey key) {
|
||||
final String value1 = this.webXmlConfigurationStrategy.get(key);
|
||||
|
||||
if (CommonUtils.isNotBlank(value1)) {
|
||||
return value1;
|
||||
}
|
||||
|
||||
return this.jndiConfigurationStrategy.get(key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public final class PropertiesConfigurationStrategyImpl extends BaseConfigurationStrategy {
|
||||
|
||||
/**
|
||||
* Property name we'll use in the {@link javax.servlet.FilterConfig} and {@link javax.servlet.ServletConfig} to try and find where
|
||||
* you stored the configuration file.
|
||||
*/
|
||||
private static final String CONFIGURATION_FILE_LOCATION = "configFileLocation";
|
||||
|
||||
/**
|
||||
* Default location of the configuration file. Mostly for testing/demo. You will most likely want to configure an alternative location.
|
||||
*/
|
||||
private static final String DEFAULT_CONFIGURATION_FILE_LOCATION = "/etc/java-cas-client.properties";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesConfigurationStrategyImpl.class);
|
||||
|
||||
private String simpleFilterName;
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
@Override
|
||||
protected String get(final ConfigurationKey configurationKey) {
|
||||
final String property = configurationKey.getName();
|
||||
final String filterSpecificProperty = this.simpleFilterName + "." + property;
|
||||
|
||||
final String filterSpecificValue = this.properties.getProperty(filterSpecificProperty);
|
||||
|
||||
if (CommonUtils.isNotEmpty(filterSpecificValue)) {
|
||||
return filterSpecificValue;
|
||||
}
|
||||
|
||||
return this.properties.getProperty(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig, final Class<? extends Filter> filterClazz) {
|
||||
this.simpleFilterName = filterClazz.getSimpleName();
|
||||
final String fileLocationFromFilterConfig = filterConfig.getInitParameter(CONFIGURATION_FILE_LOCATION);
|
||||
final boolean filterConfigFileLoad = loadPropertiesFromFile(fileLocationFromFilterConfig);
|
||||
|
||||
if (!filterConfigFileLoad) {
|
||||
final String fileLocationFromServletConfig = filterConfig.getServletContext().getInitParameter(CONFIGURATION_FILE_LOCATION);
|
||||
final boolean servletContextFileLoad = loadPropertiesFromFile(fileLocationFromServletConfig);
|
||||
|
||||
if (!servletContextFileLoad) {
|
||||
final boolean defaultConfigFileLoaded = loadPropertiesFromFile(DEFAULT_CONFIGURATION_FILE_LOCATION);
|
||||
CommonUtils.assertTrue(defaultConfigFileLoaded, "unable to load properties to configure CAS client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadPropertiesFromFile(final String file) {
|
||||
if (CommonUtils.isEmpty(file)) {
|
||||
return false;
|
||||
}
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
this.properties.load(fis);
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
LOGGER.warn("Unable to load properties for file {}", file, e);
|
||||
return false;
|
||||
} finally {
|
||||
CommonUtils.closeQuietly(fis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
||||
/**
|
||||
* Load all configuration from system properties.
|
||||
*
|
||||
* @author Jerome Leleu
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public class SystemPropertiesConfigurationStrategyImpl extends BaseConfigurationStrategy {
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig, final Class<? extends Filter> filterClazz) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String get(final ConfigurationKey configurationKey) {
|
||||
return System.getProperty(configurationKey.getName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.configuration;
|
||||
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link org.jasig.cas.client.configuration.ConfigurationStrategy} that first checks the {@link javax.servlet.FilterConfig} and
|
||||
* then checks the {@link javax.servlet.ServletContext}, ultimately falling back to the <code>defaultValue</code>.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public final class WebXmlConfigurationStrategyImpl extends BaseConfigurationStrategy {
|
||||
|
||||
private FilterConfig filterConfig;
|
||||
|
||||
@Override
|
||||
protected String get(final ConfigurationKey configurationKey) {
|
||||
final String value = this.filterConfig.getInitParameter(configurationKey.getName());
|
||||
|
||||
if (CommonUtils.isNotBlank(value)) {
|
||||
CommonUtils.assertFalse(ConfigurationKeys.RENEW.equals(configurationKey), "Renew MUST be specified via context parameter or JNDI environment to avoid misconfiguration.");
|
||||
logger.info("Property [{}] loaded from FilterConfig.getInitParameter with value [{}]", configurationKey, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
final String value2 = filterConfig.getServletContext().getInitParameter(configurationKey.getName());
|
||||
|
||||
if (CommonUtils.isNotBlank(value2)) {
|
||||
logger.info("Property [{}] loaded from ServletContext.getInitParameter with value [{}]", configurationKey,
|
||||
value2);
|
||||
return value2;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig, final Class<? extends Filter> clazz) {
|
||||
this.filterConfig = filterConfig;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -36,7 +36,7 @@ public class AssertionPrincipal extends SimplePrincipal implements Serializable
|
|||
private static final long serialVersionUID = 2288520214366461693L;
|
||||
|
||||
/** CAS assertion describing authenticated state */
|
||||
private Assertion assertion;
|
||||
private final Assertion assertion;
|
||||
|
||||
/**
|
||||
* Creates a new principal containing the CAS assertion.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -162,7 +162,7 @@ public class CasLoginModule implements LoginModule {
|
|||
protected String[] defaultRoles;
|
||||
|
||||
/** Names of attributes in the CAS assertion that should be used for role data */
|
||||
protected Set<String> roleAttributeNames = new HashSet<String>();
|
||||
protected final Set<String> roleAttributeNames = new HashSet<String>();
|
||||
|
||||
/** Name of JAAS Group containing caller principal */
|
||||
protected String principalGroupName = DEFAULT_PRINCIPAL_GROUP_NAME;
|
||||
|
|
@ -203,8 +203,9 @@ public class CasLoginModule implements LoginModule {
|
|||
* names, e.g. DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS. Default unit is MINUTES.</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public final void initialize(final Subject subject, final CallbackHandler handler, final Map<String, ?> state,
|
||||
final Map<String, ?> options) {
|
||||
final Map<String, ?> options) {
|
||||
|
||||
this.assertion = null;
|
||||
this.callbackHandler = handler;
|
||||
|
|
@ -277,6 +278,7 @@ public class CasLoginModule implements LoginModule {
|
|||
// template method
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean login() throws LoginException {
|
||||
logger.debug("Performing login.");
|
||||
|
||||
|
|
@ -292,10 +294,10 @@ public class CasLoginModule implements LoginModule {
|
|||
try {
|
||||
this.callbackHandler.handle(new Callback[] { ticketCallback, serviceCallback });
|
||||
} catch (final IOException e) {
|
||||
logger.info("Login failed due to IO exception in callback handler: {}", e);
|
||||
logger.info("Login failed due to IO exception in callback handler", e);
|
||||
throw (LoginException) new LoginException("IO exception in callback handler: " + e).initCause(e);
|
||||
} catch (final UnsupportedCallbackException e) {
|
||||
logger.info("Login failed due to unsupported callback: {}", e);
|
||||
logger.info("Login failed due to unsupported callback", e);
|
||||
throw (LoginException) new LoginException(
|
||||
"Callback handler does not support PasswordCallback and TextInputCallback.").initCause(e);
|
||||
}
|
||||
|
|
@ -325,7 +327,7 @@ public class CasLoginModule implements LoginModule {
|
|||
this.assertion = this.ticketValidator.validate(this.ticket.getName(), service);
|
||||
|
||||
} catch (final Exception e) {
|
||||
logger.info("Login failed due to CAS ticket validation failure: {}", e);
|
||||
logger.info("Login failed due to CAS ticket validation failure", e);
|
||||
throw (LoginException) new LoginException("CAS ticket validation failed: " + e).initCause(e);
|
||||
}
|
||||
}
|
||||
|
|
@ -341,6 +343,7 @@ public class CasLoginModule implements LoginModule {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean abort() throws LoginException {
|
||||
if (this.ticket != null) {
|
||||
this.ticket = null;
|
||||
|
|
@ -369,6 +372,7 @@ public class CasLoginModule implements LoginModule {
|
|||
// template method
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean commit() throws LoginException {
|
||||
|
||||
if (!preCommit()) {
|
||||
|
|
@ -439,6 +443,7 @@ public class CasLoginModule implements LoginModule {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean logout() throws LoginException {
|
||||
logger.debug("Performing logout.");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -50,6 +50,7 @@ public class ServiceAndTicketCallbackHandler implements CallbackHandler {
|
|||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||
for (final Callback callback : callbacks) {
|
||||
if (callback instanceof NameCallback) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
|
||||
|
|
@ -50,12 +51,17 @@ import org.jasig.cas.client.util.CommonUtils;
|
|||
*/
|
||||
public final class Servlet3AuthenticationFilter extends AbstractCasFilter {
|
||||
|
||||
public Servlet3AuthenticationFilter() {
|
||||
super(Protocol.CAS2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain chain) throws IOException, ServletException {
|
||||
final FilterChain chain) throws IOException, ServletException {
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
final HttpSession session = request.getSession();
|
||||
final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());
|
||||
final String ticket = CommonUtils.safeGetParameter(request, getProtocol().getArtifactParameterName());
|
||||
|
||||
if (session != null && session.getAttribute(CONST_CAS_ASSERTION) == null && ticket != null) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -34,7 +34,7 @@ public final class TicketCredential implements Principal {
|
|||
private static final int HASHCODE_SEED = 17;
|
||||
|
||||
/** Ticket ID string */
|
||||
private String ticket;
|
||||
private final String ticket;
|
||||
|
||||
/**
|
||||
* Creates a new instance that wraps the given ticket.
|
||||
|
|
@ -44,6 +44,7 @@ public final class TicketCredential implements Principal {
|
|||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.ticket;
|
||||
}
|
||||
|
|
@ -52,7 +53,7 @@ public final class TicketCredential implements Principal {
|
|||
return this.ticket;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jasig.cas.client.proxy;
|
||||
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
|
@ -36,11 +38,9 @@ import javax.crypto.spec.DESedeKeySpec;
|
|||
*/
|
||||
public abstract class AbstractEncryptedProxyGrantingTicketStorageImpl implements ProxyGrantingTicketStorage {
|
||||
|
||||
public static final String DEFAULT_ENCRYPTION_ALGORITHM = "DESede";
|
||||
|
||||
private Key key;
|
||||
|
||||
private String cipherAlgorithm = DEFAULT_ENCRYPTION_ALGORITHM;
|
||||
private String cipherAlgorithm = ConfigurationKeys.CIPHER_ALGORITHM.getDefaultValue();
|
||||
|
||||
public final void setSecretKey(final String key) throws NoSuchAlgorithmException, InvalidKeyException,
|
||||
InvalidKeySpecException {
|
||||
|
|
@ -60,10 +60,12 @@ public abstract class AbstractEncryptedProxyGrantingTicketStorageImpl implements
|
|||
this.cipherAlgorithm = cipherAlgorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void save(final String proxyGrantingTicketIou, final String proxyGrantingTicket) {
|
||||
saveInternal(proxyGrantingTicketIou, encrypt(proxyGrantingTicket));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String retrieve(final String proxyGrantingTicketIou) {
|
||||
return decrypt(retrieveInternal(proxyGrantingTicketIou));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -75,6 +75,7 @@ public final class Cas20ProxyRetriever implements ProxyRetriever {
|
|||
this.urlConnectionFactory = urlFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyTicketIdFor(final String proxyGrantingTicketId, final String targetService) {
|
||||
CommonUtils.assertNotNull(proxyGrantingTicketId, "proxyGrantingTicketId cannot be null.");
|
||||
CommonUtils.assertNotNull(targetService, "targetService cannot be null.");
|
||||
|
|
@ -94,7 +95,9 @@ public final class Cas20ProxyRetriever implements ProxyRetriever {
|
|||
return null;
|
||||
}
|
||||
|
||||
return XmlUtils.getTextForElement(response, "proxyTicket");
|
||||
final String ticket = XmlUtils.getTextForElement(response, "proxyTicket");
|
||||
logger.debug("Got proxy ticket {}", ticket);
|
||||
return ticket;
|
||||
}
|
||||
|
||||
private URL constructUrl(final String proxyGrantingTicketId, final String targetService) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -39,6 +39,7 @@ public final class CleanUpTimerTask extends TimerTask {
|
|||
this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.proxyGrantingTicketStorage.cleanUp();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -23,7 +23,6 @@ package org.jasig.cas.client.proxy;
|
|||
* them to a specific ProxyGrantingTicketIou.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface ProxyGrantingTicketStorage {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory;
|
|||
*
|
||||
* @author Scott Battaglia
|
||||
* @author Brad Cupit (brad [at] lsu {dot} edu)
|
||||
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicketStorage {
|
||||
|
|
@ -57,7 +56,7 @@ public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicket
|
|||
*
|
||||
* @see ProxyGrantingTicketStorageImpl#DEFAULT_TIMEOUT
|
||||
*/
|
||||
private long timeout;
|
||||
private final long timeout;
|
||||
|
||||
/**
|
||||
* Constructor set the timeout to the default value.
|
||||
|
|
@ -80,6 +79,7 @@ public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicket
|
|||
* NOTE: you can only retrieve a ProxyGrantingTicket once with this method.
|
||||
* Its removed after retrieval.
|
||||
*/
|
||||
@Override
|
||||
public String retrieve(final String proxyGrantingTicketIou) {
|
||||
if (CommonUtils.isBlank(proxyGrantingTicketIou)) {
|
||||
return null;
|
||||
|
|
@ -98,6 +98,7 @@ public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicket
|
|||
return holder.getProxyGrantingTicket();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final String proxyGrantingTicketIou, final String proxyGrantingTicket) {
|
||||
final ProxyGrantingTicketHolder holder = new ProxyGrantingTicketHolder(proxyGrantingTicket);
|
||||
|
||||
|
|
@ -110,6 +111,7 @@ public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicket
|
|||
* Cleans up old, expired proxy tickets. This method must be
|
||||
* called regularly via an external thread or timer.
|
||||
*/
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
for (final Map.Entry<String, ProxyGrantingTicketHolder> holder : this.cache.entrySet()) {
|
||||
if (holder.getValue().isExpired(this.timeout)) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -25,7 +25,6 @@ import java.io.Serializable;
|
|||
* implementation a black box to the client.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface ProxyRetriever extends Serializable {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<!--
|
||||
|
||||
Licensed to Jasig under one or more contributor license
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Jasig licenses this file to you under the Apache License,
|
||||
Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -46,12 +46,14 @@ public final class HashMapBackedSessionMappingStorage implements SessionMappingS
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
public synchronized void addSessionById(String mappingId, HttpSession session) {
|
||||
@Override
|
||||
public synchronized void addSessionById(final String mappingId, final HttpSession session) {
|
||||
ID_TO_SESSION_KEY_MAPPING.put(session.getId(), mappingId);
|
||||
MANAGED_SESSIONS.put(mappingId, session);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void removeBySessionById(final String sessionId) {
|
||||
logger.debug("Attempting to remove Session=[{}]", sessionId);
|
||||
|
||||
|
|
@ -68,7 +70,8 @@ public final class HashMapBackedSessionMappingStorage implements SessionMappingS
|
|||
ID_TO_SESSION_KEY_MAPPING.remove(sessionId);
|
||||
}
|
||||
|
||||
public synchronized HttpSession removeSessionByMappingId(String mappingId) {
|
||||
@Override
|
||||
public synchronized HttpSession removeSessionByMappingId(final String mappingId) {
|
||||
final HttpSession session = MANAGED_SESSIONS.get(mappingId);
|
||||
|
||||
if (session != null) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -22,8 +22,10 @@ import java.io.IOException;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.util.AbstractConfigurationFilter;
|
||||
|
||||
/**
|
||||
|
|
@ -37,23 +39,18 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
|
|||
|
||||
private static final SingleSignOutHandler HANDLER = new SingleSignOutHandler();
|
||||
|
||||
private AtomicBoolean handlerInitialized = new AtomicBoolean(false);
|
||||
private final AtomicBoolean handlerInitialized = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
super.init(filterConfig);
|
||||
if (!isIgnoreInitConfiguration()) {
|
||||
HANDLER.setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName",
|
||||
SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME));
|
||||
HANDLER.setLogoutParameterName(getPropertyFromInitParams(filterConfig, "logoutParameterName",
|
||||
SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME));
|
||||
HANDLER.setFrontLogoutParameterName(getPropertyFromInitParams(filterConfig, "frontLogoutParameterName",
|
||||
SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME));
|
||||
HANDLER.setRelayStateParameterName(getPropertyFromInitParams(filterConfig, "relayStateParameterName",
|
||||
SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME));
|
||||
HANDLER.setCasServerUrlPrefix(getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", ""));
|
||||
HANDLER.setArtifactParameterOverPost(parseBoolean(getPropertyFromInitParams(filterConfig,
|
||||
"artifactParameterOverPost", "false")));
|
||||
HANDLER.setEagerlyCreateSessions(parseBoolean(getPropertyFromInitParams(filterConfig,
|
||||
"eagerlyCreateSessions", "true")));
|
||||
setArtifactParameterName(getString(ConfigurationKeys.ARTIFACT_PARAMETER_NAME));
|
||||
setLogoutParameterName(getString(ConfigurationKeys.LOGOUT_PARAMETER_NAME));
|
||||
setRelayStateParameterName(getString(ConfigurationKeys.RELAY_STATE_PARAMETER_NAME));
|
||||
setLogoutCallbackPath(getString(ConfigurationKeys.LOGOUT_CALLBACK_PATH));
|
||||
HANDLER.setArtifactParameterOverPost(getBoolean(ConfigurationKeys.ARTIFACT_PARAMETER_OVER_POST));
|
||||
HANDLER.setEagerlyCreateSessions(getBoolean(ConfigurationKeys.EAGERLY_CREATE_SESSIONS));
|
||||
}
|
||||
HANDLER.init();
|
||||
handlerInitialized.set(true);
|
||||
|
|
@ -66,25 +63,22 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
|
|||
public void setLogoutParameterName(final String name) {
|
||||
HANDLER.setLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setFrontLogoutParameterName(final String name) {
|
||||
HANDLER.setFrontLogoutParameterName(name);
|
||||
}
|
||||
|
||||
|
||||
public void setRelayStateParameterName(final String name) {
|
||||
HANDLER.setRelayStateParameterName(name);
|
||||
}
|
||||
|
||||
public void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
HANDLER.setCasServerUrlPrefix(casServerUrlPrefix);
|
||||
public void setLogoutCallbackPath(final String logoutCallbackPath) {
|
||||
HANDLER.setLogoutCallbackPath(logoutCallbackPath);
|
||||
}
|
||||
|
||||
public void setSessionMappingStorage(final SessionMappingStorage storage) {
|
||||
HANDLER.setSessionMappingStorage(storage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
|
|
@ -101,6 +95,7 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
package org.jasig.cas.client.session;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
|
|
@ -26,9 +27,10 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.XmlUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -44,11 +46,6 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public final class SingleSignOutHandler {
|
||||
|
||||
public final static String DEFAULT_ARTIFACT_PARAMETER_NAME = "ticket";
|
||||
public final static String DEFAULT_LOGOUT_PARAMETER_NAME = "logoutRequest";
|
||||
public final static String DEFAULT_FRONT_LOGOUT_PARAMETER_NAME = "SAMLRequest";
|
||||
public final static String DEFAULT_RELAY_STATE_PARAMETER_NAME = "RelayState";
|
||||
|
||||
private final static int DECOMPRESSION_FACTOR = 10;
|
||||
|
||||
/** Logger instance */
|
||||
|
|
@ -58,19 +55,16 @@ public final class SingleSignOutHandler {
|
|||
private SessionMappingStorage sessionMappingStorage = new HashMapBackedSessionMappingStorage();
|
||||
|
||||
/** The name of the artifact parameter. This is used to capture the session identifier. */
|
||||
private String artifactParameterName = DEFAULT_ARTIFACT_PARAMETER_NAME;
|
||||
private String artifactParameterName = Protocol.CAS2.getArtifactParameterName();
|
||||
|
||||
/** Parameter name that stores logout request for back channel SLO */
|
||||
private String logoutParameterName = DEFAULT_LOGOUT_PARAMETER_NAME;
|
||||
|
||||
/** Parameter name that stores logout request for front channel SLO */
|
||||
private String frontLogoutParameterName = DEFAULT_FRONT_LOGOUT_PARAMETER_NAME;
|
||||
|
||||
/** Parameter name that stores the state of the CAS server webflow for the callback */
|
||||
private String relayStateParameterName = DEFAULT_RELAY_STATE_PARAMETER_NAME;
|
||||
/** Parameter name that stores logout request for SLO */
|
||||
private String logoutParameterName = ConfigurationKeys.LOGOUT_PARAMETER_NAME.getDefaultValue();
|
||||
|
||||
/** The prefix url of the CAS server */
|
||||
private String casServerUrlPrefix = "";
|
||||
/** Parameter name that stores the state of the CAS server webflow for the callback */
|
||||
private String relayStateParameterName = ConfigurationKeys.RELAY_STATE_PARAMETER_NAME.getDefaultValue();
|
||||
|
||||
/** The logout callback path configured at the CAS server, if there is one */
|
||||
private String logoutCallbackPath;
|
||||
|
||||
private boolean artifactParameterOverPost = false;
|
||||
|
||||
|
|
@ -78,7 +72,7 @@ public final class SingleSignOutHandler {
|
|||
|
||||
private List<String> safeParameters;
|
||||
|
||||
private LogoutStrategy logoutStrategy = isServlet30() ? new Servlet30LogoutStrategy() : new Servlet25LogoutStrategy();
|
||||
private final LogoutStrategy logoutStrategy = isServlet30() ? new Servlet30LogoutStrategy() : new Servlet25LogoutStrategy();
|
||||
|
||||
public void setSessionMappingStorage(final SessionMappingStorage storage) {
|
||||
this.sessionMappingStorage = storage;
|
||||
|
|
@ -100,24 +94,17 @@ public final class SingleSignOutHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param name Name of parameter containing CAS logout request message for back channel SLO.
|
||||
* @param name Name of parameter containing CAS logout request message for SLO.
|
||||
*/
|
||||
public void setLogoutParameterName(final String name) {
|
||||
this.logoutParameterName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param casServerUrlPrefix The prefix url of the CAS server.
|
||||
* @param logoutCallbackPath The logout callback path configured at the CAS server.
|
||||
*/
|
||||
public void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
this.casServerUrlPrefix = casServerUrlPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of parameter containing CAS logout request message for front channel SLO.
|
||||
*/
|
||||
public void setFrontLogoutParameterName(final String name) {
|
||||
this.frontLogoutParameterName = name;
|
||||
public void setLogoutCallbackPath(final String logoutCallbackPath) {
|
||||
this.logoutCallbackPath = logoutCallbackPath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -138,19 +125,13 @@ public final class SingleSignOutHandler {
|
|||
if (this.safeParameters == null) {
|
||||
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.logoutParameterName, "logoutParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.frontLogoutParameterName, "frontLogoutParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.sessionMappingStorage, "sessionMappingStorage cannot be null.");
|
||||
CommonUtils.assertNotNull(this.relayStateParameterName, "relayStateParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
|
||||
|
||||
if (CommonUtils.isBlank(this.casServerUrlPrefix)) {
|
||||
logger.warn("Front Channel single sign out redirects are disabled when the 'casServerUrlPrefix' value is not set.");
|
||||
}
|
||||
|
||||
if (this.artifactParameterOverPost) {
|
||||
this.safeParameters = Arrays.asList(this.logoutParameterName, this.artifactParameterName);
|
||||
} else {
|
||||
this.safeParameters = Arrays.asList(this.logoutParameterName);
|
||||
this.safeParameters = Collections.singletonList(this.logoutParameterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -168,30 +149,32 @@ public final class SingleSignOutHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given request is a CAS back channel logout request.
|
||||
* Determines whether the given request is a CAS logout request.
|
||||
*
|
||||
* @param request HTTP request.
|
||||
*
|
||||
* @return True if request is logout request, false otherwise.
|
||||
*/
|
||||
private boolean isBackChannelLogoutRequest(final HttpServletRequest request) {
|
||||
return "POST".equals(request.getMethod())
|
||||
&& !isMultipartRequest(request)
|
||||
&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName,
|
||||
this.safeParameters));
|
||||
private boolean isLogoutRequest(final HttpServletRequest request) {
|
||||
if ("POST".equalsIgnoreCase(request.getMethod())) {
|
||||
return !isMultipartRequest(request)
|
||||
&& pathEligibleForLogout(request)
|
||||
&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName,
|
||||
this.safeParameters));
|
||||
}
|
||||
|
||||
if ("GET".equalsIgnoreCase(request.getMethod())) {
|
||||
return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given request is a CAS front channel logout request. Front Channel log out requests are only supported
|
||||
* when the 'casServerUrlPrefix' value is set.
|
||||
*
|
||||
* @param request HTTP request.
|
||||
*
|
||||
* @return True if request is logout request, false otherwise.
|
||||
*/
|
||||
private boolean isFrontChannelLogoutRequest(final HttpServletRequest request) {
|
||||
return "GET".equals(request.getMethod()) && CommonUtils.isNotBlank(this.casServerUrlPrefix)
|
||||
&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.frontLogoutParameterName));
|
||||
private boolean pathEligibleForLogout(final HttpServletRequest request) {
|
||||
return logoutCallbackPath == null || logoutCallbackPath.equals(getPath(request));
|
||||
}
|
||||
|
||||
private String getPath(final HttpServletRequest request) {
|
||||
return request.getServletPath() + CommonUtils.nullToEmpty(request.getPathInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -206,26 +189,15 @@ public final class SingleSignOutHandler {
|
|||
logger.trace("Received a token request");
|
||||
recordSession(request);
|
||||
return true;
|
||||
|
||||
} else if (isBackChannelLogoutRequest(request)) {
|
||||
logger.trace("Received a back channel logout request");
|
||||
}
|
||||
|
||||
if (isLogoutRequest(request)) {
|
||||
logger.trace("Received a logout request");
|
||||
destroySession(request);
|
||||
return false;
|
||||
|
||||
} else if (isFrontChannelLogoutRequest(request)) {
|
||||
logger.trace("Received a front channel logout request");
|
||||
destroySession(request);
|
||||
// redirection url to the CAS server
|
||||
final String redirectionUrl = computeRedirectionToServer(request);
|
||||
if (redirectionUrl != null) {
|
||||
CommonUtils.sendRedirect(response, redirectionUrl);
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
logger.trace("Ignoring URI for logout: {}", request.getRequestURI());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
logger.trace("Ignoring URI for logout: {}", request.getRequestURI());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -248,7 +220,7 @@ public final class SingleSignOutHandler {
|
|||
try {
|
||||
this.sessionMappingStorage.removeBySessionById(session.getId());
|
||||
} catch (final Exception e) {
|
||||
// ignore if the session is already marked as invalid. Nothing we can do!
|
||||
// ignore if the session is already marked as invalid. Nothing we can do!
|
||||
}
|
||||
sessionMappingStorage.addSessionById(token, session);
|
||||
}
|
||||
|
|
@ -260,7 +232,7 @@ public final class SingleSignOutHandler {
|
|||
* @return the uncompressed logout message.
|
||||
*/
|
||||
private String uncompressLogoutMessage(final String originalMessage) {
|
||||
final byte[] binaryMessage = Base64.decodeBase64(originalMessage);
|
||||
final byte[] binaryMessage = DatatypeConverter.parseBase64Binary(originalMessage);
|
||||
|
||||
Inflater decompresser = null;
|
||||
try {
|
||||
|
|
@ -289,23 +261,23 @@ public final class SingleSignOutHandler {
|
|||
* @param request HTTP request containing a CAS logout message.
|
||||
*/
|
||||
private void destroySession(final HttpServletRequest request) {
|
||||
final String logoutMessage;
|
||||
// front channel logout -> the message needs to be base64 decoded + decompressed
|
||||
if (isFrontChannelLogoutRequest(request)) {
|
||||
logoutMessage = uncompressLogoutMessage(CommonUtils.safeGetParameter(request,
|
||||
this.frontLogoutParameterName));
|
||||
} else {
|
||||
logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters);
|
||||
String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters);
|
||||
if (CommonUtils.isBlank(logoutMessage)) {
|
||||
logger.error("Could not locate logout message of the request from {}", this.logoutParameterName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!logoutMessage.contains("SessionIndex")) {
|
||||
logoutMessage = uncompressLogoutMessage(logoutMessage);
|
||||
}
|
||||
|
||||
logger.trace("Logout request:\n{}", logoutMessage);
|
||||
|
||||
final String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");
|
||||
if (CommonUtils.isNotBlank(token)) {
|
||||
final HttpSession session = this.sessionMappingStorage.removeSessionByMappingId(token);
|
||||
|
||||
if (session != null) {
|
||||
String sessionID = session.getId();
|
||||
|
||||
final String sessionID = session.getId();
|
||||
logger.debug("Invalidating session [{}] for token [{}]", sessionID, token);
|
||||
|
||||
try {
|
||||
|
|
@ -318,33 +290,6 @@ public final class SingleSignOutHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the redirection url to the CAS server when it's a front channel SLO
|
||||
* (depending on the relay state parameter).
|
||||
*
|
||||
* @param request The HTTP request.
|
||||
* @return the redirection url to the CAS server.
|
||||
*/
|
||||
private String computeRedirectionToServer(final HttpServletRequest request) {
|
||||
final String relayStateValue = CommonUtils.safeGetParameter(request, this.relayStateParameterName);
|
||||
// if we have a state value -> redirect to the CAS server to continue the logout process
|
||||
if (StringUtils.isNotBlank(relayStateValue)) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(casServerUrlPrefix);
|
||||
if (!this.casServerUrlPrefix.endsWith("/")) {
|
||||
buffer.append("/");
|
||||
}
|
||||
buffer.append("logout?_eventId=next&");
|
||||
buffer.append(this.relayStateParameterName);
|
||||
buffer.append("=");
|
||||
buffer.append(CommonUtils.urlEncode(relayStateValue));
|
||||
final String redirectUrl = buffer.toString();
|
||||
logger.debug("Redirection url to the CAS server: {}", redirectUrl);
|
||||
return redirectUrl;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isMultipartRequest(final HttpServletRequest request) {
|
||||
return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart");
|
||||
}
|
||||
|
|
@ -368,6 +313,7 @@ public final class SingleSignOutHandler {
|
|||
|
||||
private class Servlet25LogoutStrategy implements LogoutStrategy {
|
||||
|
||||
@Override
|
||||
public void logout(final HttpServletRequest request) {
|
||||
// nothing additional to do here
|
||||
}
|
||||
|
|
@ -375,6 +321,7 @@ public final class SingleSignOutHandler {
|
|||
|
||||
private class Servlet30LogoutStrategy implements LogoutStrategy {
|
||||
|
||||
@Override
|
||||
public void logout(final HttpServletRequest request) {
|
||||
try {
|
||||
request.logout();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -36,10 +36,12 @@ public final class SingleSignOutHttpSessionListener implements HttpSessionListen
|
|||
|
||||
private SessionMappingStorage sessionMappingStorage;
|
||||
|
||||
@Override
|
||||
public void sessionCreated(final HttpSessionEvent event) {
|
||||
// nothing to do at the moment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(final HttpSessionEvent event) {
|
||||
if (sessionMappingStorage == null) {
|
||||
sessionMappingStorage = getSessionMappingStorage();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -32,6 +32,7 @@ import javax.net.ssl.SSLSession;
|
|||
public final class AnyHostnameVerifier implements HostnameVerifier {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean verify(final String hostname, final SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jasig.cas.client.ssl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
|
@ -28,7 +29,7 @@ import java.net.URLConnection;
|
|||
* @author Misagh Moayyed
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface HttpURLConnectionFactory {
|
||||
public interface HttpURLConnectionFactory extends Serializable {
|
||||
|
||||
/**
|
||||
* Receives a {@link URLConnection} instance typically as a result of a {@link URL}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,8 +18,7 @@
|
|||
*/
|
||||
package org.jasig.cas.client.ssl;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLConnection;
|
||||
import java.security.KeyStore;
|
||||
|
|
@ -41,6 +40,8 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public final class HttpsURLConnectionFactory implements HttpURLConnectionFactory {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpsURLConnectionFactory.class);
|
||||
|
||||
/**
|
||||
|
|
@ -77,6 +78,7 @@ public final class HttpsURLConnectionFactory implements HttpURLConnectionFactory
|
|||
this.hostnameVerifier = verifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpURLConnection buildHttpURLConnection(final URLConnection url) {
|
||||
return this.configureHttpsConnectionIfNeeded(url);
|
||||
}
|
||||
|
|
@ -146,4 +148,45 @@ public final class HttpsURLConnectionFactory implements HttpURLConnectionFactory
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final HttpsURLConnectionFactory that = (HttpsURLConnectionFactory) o;
|
||||
|
||||
if (!hostnameVerifier.equals(that.hostnameVerifier)) return false;
|
||||
if (!sslConfiguration.equals(that.sslConfiguration)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = hostnameVerifier.hashCode();
|
||||
result = 31 * result + sslConfiguration.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||
if (this.hostnameVerifier == HttpsURLConnection.getDefaultHostnameVerifier()) {
|
||||
out.writeObject(null);
|
||||
} else {
|
||||
out.writeObject(this.hostnameVerifier);
|
||||
}
|
||||
|
||||
out.writeObject(this.sslConfiguration);
|
||||
|
||||
}
|
||||
|
||||
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
final Object internalHostNameVerifier = in.readObject();
|
||||
if (internalHostNameVerifier == null) {
|
||||
this.hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
|
||||
} else {
|
||||
this.hostnameVerifier = (HostnameVerifier) internalHostNameVerifier;
|
||||
}
|
||||
|
||||
this.sslConfiguration = (Properties) in.readObject();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -16,9 +16,9 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.jasig.cas.client.ssl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
|
@ -32,10 +32,12 @@ import javax.net.ssl.SSLSession;
|
|||
* @since 3.1.10
|
||||
*
|
||||
*/
|
||||
public final class RegexHostnameVerifier implements HostnameVerifier {
|
||||
public final class RegexHostnameVerifier implements HostnameVerifier, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Allowed hostname pattern */
|
||||
private Pattern pattern;
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given regular expression.
|
||||
|
|
@ -47,6 +49,7 @@ public final class RegexHostnameVerifier implements HostnameVerifier {
|
|||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean verify(final String hostname, final SSLSession session) {
|
||||
return pattern.matcher(hostname).matches();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -20,6 +20,7 @@ package org.jasig.cas.client.ssl;
|
|||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Verifies a SSL peer host name based on an explicit whitelist of allowed hosts.
|
||||
|
|
@ -29,10 +30,12 @@ import javax.net.ssl.SSLSession;
|
|||
* @since 3.1.10
|
||||
*
|
||||
*/
|
||||
public final class WhitelistHostnameVerifier implements HostnameVerifier {
|
||||
public final class WhitelistHostnameVerifier implements HostnameVerifier, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Allowed hosts */
|
||||
private String[] allowedHosts;
|
||||
private final String[] allowedHosts;
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given array of allowed hosts.
|
||||
|
|
@ -53,6 +56,7 @@ public final class WhitelistHostnameVerifier implements HostnameVerifier {
|
|||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean verify(final String hostname, final SSLSession session) {
|
||||
|
||||
for (final String allowedHost : this.allowedHosts) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,10 +18,14 @@
|
|||
*/
|
||||
package org.jasig.cas.client.util;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Abstract filter that contains code that is common to all CAS filters.
|
||||
|
|
@ -42,12 +46,8 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
/** Represents the constant for where the assertion will be located in memory. */
|
||||
public static final String CONST_CAS_ASSERTION = "_const_cas_assertion_";
|
||||
|
||||
/** Defines the parameter to look for for the artifact. */
|
||||
private String artifactParameterName = "ticket";
|
||||
private final Protocol protocol;
|
||||
|
||||
/** Defines the parameter to look for for the service. */
|
||||
private String serviceParameterName = "service";
|
||||
|
||||
/** Sets where response.encodeUrl should be called on service urls when constructed. */
|
||||
private boolean encodeServiceUrl = true;
|
||||
|
||||
|
|
@ -59,18 +59,17 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
/** The exact url of the service. */
|
||||
private String service;
|
||||
|
||||
protected AbstractCasFilter(final Protocol protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void init(final FilterConfig filterConfig) throws ServletException {
|
||||
super.init(filterConfig);
|
||||
if (!isIgnoreInitConfiguration()) {
|
||||
setServerName(getPropertyFromInitParams(filterConfig, "serverName", null));
|
||||
logger.trace("Loading serverName property: {}", this.serverName);
|
||||
setService(getPropertyFromInitParams(filterConfig, "service", null));
|
||||
logger.trace("Loading service property: {}", this.service);
|
||||
setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
|
||||
logger.trace("Loading artifact parameter name property: {}", this.artifactParameterName);
|
||||
setServiceParameterName(getPropertyFromInitParams(filterConfig, "serviceParameterName", "service"));
|
||||
logger.trace("Loading serviceParameterName property: {} ", this.serviceParameterName);
|
||||
setEncodeServiceUrl(parseBoolean(getPropertyFromInitParams(filterConfig, "encodeServiceUrl", "true")));
|
||||
logger.trace("Loading encodeServiceUrl property: {}", this.encodeServiceUrl);
|
||||
setServerName(getString(ConfigurationKeys.SERVER_NAME));
|
||||
setService(getString(ConfigurationKeys.SERVICE));
|
||||
setEncodeServiceUrl(getBoolean(ConfigurationKeys.ENCODE_SERVICE_URL));
|
||||
|
||||
initInternal(filterConfig);
|
||||
}
|
||||
|
|
@ -92,8 +91,6 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
* afterPropertiesSet();
|
||||
*/
|
||||
public void init() {
|
||||
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.serviceParameterName, "serviceParameterName cannot be null.");
|
||||
CommonUtils.assertTrue(CommonUtils.isNotEmpty(this.serverName) || CommonUtils.isNotEmpty(this.service),
|
||||
"serverName or service must be set.");
|
||||
CommonUtils.assertTrue(CommonUtils.isBlank(this.serverName) || CommonUtils.isBlank(this.service),
|
||||
|
|
@ -101,13 +98,15 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
}
|
||||
|
||||
// empty implementation as most filters won't need this.
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
protected final String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName,
|
||||
this.artifactParameterName, this.encodeServiceUrl);
|
||||
this.protocol.getServiceParameterName(),
|
||||
this.protocol.getArtifactParameterName(), this.encodeServiceUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,26 +128,14 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
this.service = service;
|
||||
}
|
||||
|
||||
public final void setArtifactParameterName(final String artifactParameterName) {
|
||||
this.artifactParameterName = artifactParameterName;
|
||||
}
|
||||
|
||||
public final void setServiceParameterName(final String serviceParameterName) {
|
||||
this.serviceParameterName = serviceParameterName;
|
||||
}
|
||||
|
||||
public final void setEncodeServiceUrl(final boolean encodeServiceUrl) {
|
||||
this.encodeServiceUrl = encodeServiceUrl;
|
||||
}
|
||||
|
||||
public final String getArtifactParameterName() {
|
||||
return this.artifactParameterName;
|
||||
protected Protocol getProtocol() {
|
||||
return this.protocol;
|
||||
}
|
||||
|
||||
public final String getServiceParameterName() {
|
||||
return this.serviceParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to allow you to change how you retrieve the ticket.
|
||||
*
|
||||
|
|
@ -156,6 +143,7 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
* @return the ticket if its found, null otherwise.
|
||||
*/
|
||||
protected String retrieveTicketFromRequest(final HttpServletRequest request) {
|
||||
return CommonUtils.safeGetParameter(request, getArtifactParameterName());
|
||||
return CommonUtils.safeGetParameter(request, this.protocol.getArtifactParameterName(),
|
||||
Arrays.asList(this.protocol.getArtifactParameterName()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,10 +18,13 @@
|
|||
*/
|
||||
package org.jasig.cas.client.util;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.jasig.cas.client.configuration.ConfigurationKey;
|
||||
import org.jasig.cas.client.configuration.ConfigurationStrategy;
|
||||
import org.jasig.cas.client.configuration.ConfigurationStrategyName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -34,94 +37,42 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public abstract class AbstractConfigurationFilter implements Filter {
|
||||
|
||||
private static final String CONFIGURATION_STRATEGY_KEY = "configurationStrategy";
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private boolean ignoreInitConfiguration = false;
|
||||
|
||||
/**
|
||||
* Retrieves the property from the FilterConfig. First it checks the FilterConfig's initParameters to see if it
|
||||
* has a value.
|
||||
* If it does, it returns that, otherwise it retrieves the ServletContext's initParameters and returns that value if any.
|
||||
* <p>
|
||||
* Finally, it will check JNDI if all other methods fail. All the JNDI properties should be stored under either java:comp/env/cas/SHORTFILTERNAME/{propertyName}
|
||||
* or java:comp/env/cas/{propertyName}
|
||||
* <p>
|
||||
* Essentially the documented order is:
|
||||
* <ol>
|
||||
* <li>FilterConfig.getInitParameter</li>
|
||||
* <li>ServletContext.getInitParameter</li>
|
||||
* <li>java:comp/env/cas/SHORTFILTERNAME/{propertyName}</li>
|
||||
* <li>java:comp/env/cas/{propertyName}</li>
|
||||
* <li>Default Value</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* @param filterConfig the Filter Configuration.
|
||||
* @param propertyName the property to retrieve.
|
||||
* @param defaultValue the default value if the property is not found.
|
||||
* @return the property value, following the above conventions. It will always return the more specific value (i.e.
|
||||
* filter vs. context).
|
||||
*/
|
||||
protected final String getPropertyFromInitParams(final FilterConfig filterConfig, final String propertyName,
|
||||
final String defaultValue) {
|
||||
final String value = filterConfig.getInitParameter(propertyName);
|
||||
private ConfigurationStrategy configurationStrategy;
|
||||
|
||||
if (CommonUtils.isNotBlank(value)) {
|
||||
if ("renew".equals(propertyName)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Renew MUST be specified via context parameter or JNDI environment to avoid misconfiguration.");
|
||||
}
|
||||
logger.info("Property [{}] loaded from FilterConfig.getInitParameter with value [{}]", propertyName, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
final String value2 = filterConfig.getServletContext().getInitParameter(propertyName);
|
||||
|
||||
if (CommonUtils.isNotBlank(value2)) {
|
||||
logger.info("Property [{}] loaded from ServletContext.getInitParameter with value [{}]", propertyName,
|
||||
value2);
|
||||
return value2;
|
||||
}
|
||||
InitialContext context;
|
||||
try {
|
||||
context = new InitialContext();
|
||||
} catch (final NamingException e) {
|
||||
logger.warn(e.getMessage(), e);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
final String shortName = this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".") + 1);
|
||||
final String value3 = loadFromContext(context, "java:comp/env/cas/" + shortName + "/" + propertyName);
|
||||
|
||||
if (CommonUtils.isNotBlank(value3)) {
|
||||
logger.info("Property [{}] loaded from JNDI Filter Specific Property with value [{}]", propertyName, value3);
|
||||
return value3;
|
||||
}
|
||||
|
||||
final String value4 = loadFromContext(context, "java:comp/env/cas/" + propertyName);
|
||||
|
||||
if (CommonUtils.isNotBlank(value4)) {
|
||||
logger.info("Property [{}] loaded from JNDI with value [{}]", propertyName, value4);
|
||||
return value4;
|
||||
}
|
||||
|
||||
logger.info("Property [{}] not found. Using default value [{}]", propertyName, defaultValue);
|
||||
return defaultValue;
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
final String configurationStrategyName = filterConfig.getServletContext().getInitParameter(CONFIGURATION_STRATEGY_KEY);
|
||||
this.configurationStrategy = ReflectUtils.newInstance(ConfigurationStrategyName.resolveToConfigurationStrategy(configurationStrategyName));
|
||||
this.configurationStrategy.init(filterConfig, getClass());
|
||||
}
|
||||
|
||||
protected final boolean parseBoolean(final String value) {
|
||||
return ((value != null) && value.equalsIgnoreCase("true"));
|
||||
protected final boolean getBoolean(final ConfigurationKey<Boolean> configurationKey) {
|
||||
return this.configurationStrategy.getBoolean(configurationKey);
|
||||
}
|
||||
|
||||
protected final String loadFromContext(final InitialContext context, final String path) {
|
||||
try {
|
||||
return (String) context.lookup(path);
|
||||
} catch (final NamingException e) {
|
||||
return null;
|
||||
}
|
||||
protected final String getString(final ConfigurationKey<String> configurationKey) {
|
||||
return this.configurationStrategy.getString(configurationKey);
|
||||
}
|
||||
|
||||
public final void setIgnoreInitConfiguration(boolean ignoreInitConfiguration) {
|
||||
protected final long getLong(final ConfigurationKey<Long> configurationKey) {
|
||||
return this.configurationStrategy.getLong(configurationKey);
|
||||
}
|
||||
|
||||
protected final int getInt(final ConfigurationKey<Integer> configurationKey) {
|
||||
return this.configurationStrategy.getInt(configurationKey);
|
||||
}
|
||||
|
||||
protected final <T> Class<? extends T> getClass(final ConfigurationKey<Class<? extends T>> configurationKey) {
|
||||
return this.configurationStrategy.getClass(configurationKey);
|
||||
}
|
||||
|
||||
public final void setIgnoreInitConfiguration(final boolean ignoreInitConfiguration) {
|
||||
this.ignoreInitConfiguration = ignoreInitConfiguration;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -24,7 +24,6 @@ import org.jasig.cas.client.validation.Assertion;
|
|||
* Static holder that places Assertion in a ThreadLocal.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11728 $ $Date: 2007-09-26 14:20:43 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public class AssertionHolder {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -28,17 +28,18 @@ import org.jasig.cas.client.validation.Assertion;
|
|||
* Places the assertion in a ThreadLocal such that other resources can access it that do not have access to the web tier session.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11728 $ $Date: 2007-09-26 14:20:43 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class AssertionThreadLocalFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpSession session = request.getSession(false);
|
||||
final Assertion assertion = (Assertion) (session == null ? request
|
||||
|
|
@ -53,6 +54,7 @@ public final class AssertionThreadLocalFilter implements Filter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,15 +18,7 @@
|
|||
*/
|
||||
package org.jasig.cas.client.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
|
||||
import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
|
||||
|
|
@ -35,11 +27,27 @@ import org.jasig.cas.client.validation.ProxyListEditor;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Common utilities so that we don't need to include Commons Lang.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class CommonUtils {
|
||||
|
|
@ -58,14 +66,20 @@ public final class CommonUtils {
|
|||
|
||||
private static final HttpURLConnectionFactory DEFAULT_URL_CONNECTION_FACTORY = new HttpsURLConnectionFactory();
|
||||
|
||||
private CommonUtils() {
|
||||
// nothing to do
|
||||
private static final String SERVICE_PARAMETER_NAMES;
|
||||
|
||||
static {
|
||||
final Set<String> serviceParameterSet = new HashSet<String>(4);
|
||||
for (final Protocol protocol : Protocol.values()) {
|
||||
serviceParameterSet.add(protocol.getServiceParameterName());
|
||||
}
|
||||
SERVICE_PARAMETER_NAMES = serviceParameterSet.toString()
|
||||
.replaceAll("\\[|\\]", "")
|
||||
.replaceAll("\\s", "");
|
||||
}
|
||||
|
||||
public static String formatForUtcTime(final Date date) {
|
||||
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
return dateFormat.format(date);
|
||||
private CommonUtils() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,7 +113,7 @@ public final class CommonUtils {
|
|||
* Assert that the statement is true, otherwise throw an exception with the
|
||||
* provided message.
|
||||
*
|
||||
* @param cond the codition to assert is true.
|
||||
* @param cond the condition to assert is true.
|
||||
* @param message the message to display if the condition is not true.
|
||||
*/
|
||||
public static void assertTrue(final boolean cond, final String message) {
|
||||
|
|
@ -108,6 +122,20 @@ public final class CommonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that the statement is true, otherwise throw an exception with the
|
||||
* provided message.
|
||||
*
|
||||
* @param cond the condition to assert is false.
|
||||
* @param message the message to display if the condition is not false.
|
||||
*/
|
||||
public static void assertFalse(final boolean cond, final String message) {
|
||||
if (cond) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the String is null or of length 0.
|
||||
*
|
||||
|
|
@ -115,7 +143,7 @@ public final class CommonUtils {
|
|||
* @return true if its null or length of 0, false otherwise.
|
||||
*/
|
||||
public static boolean isEmpty(final String string) {
|
||||
return string == null || string.length() == 0;
|
||||
return string == null || string.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -137,7 +165,7 @@ public final class CommonUtils {
|
|||
* @return true if its blank, false otherwise.
|
||||
*/
|
||||
public static boolean isBlank(final String string) {
|
||||
return isEmpty(string) || string.trim().length() == 0;
|
||||
return isEmpty(string) || string.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -159,21 +187,38 @@ public final class CommonUtils {
|
|||
* @param serviceUrl the actual service's url.
|
||||
* @param renew whether we should send renew or not.
|
||||
* @param gateway where we should send gateway or not.
|
||||
* @param method the method used by the CAS server to send the user back to the application.
|
||||
* @return the fully constructed redirect url.
|
||||
*/
|
||||
public static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName,
|
||||
final String serviceUrl, final boolean renew, final boolean gateway) {
|
||||
final String serviceUrl, final boolean renew, final boolean gateway, final String method) {
|
||||
return casServerLoginUrl + (casServerLoginUrl.contains("?") ? "&" : "?") + serviceParameterName + "="
|
||||
+ urlEncode(serviceUrl) + (renew ? "&renew=true" : "") + (gateway ? "&gateway=true" : "");
|
||||
+ urlEncode(serviceUrl) + (renew ? "&renew=true" : "") + (gateway ? "&gateway=true" : "")
|
||||
+ (method != null ? "&method=" + method : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct redirect url to a CAS server.
|
||||
*
|
||||
* @param casServerLoginUrl the cas server login url
|
||||
* @param serviceParameterName the service parameter name
|
||||
* @param serviceUrl the service url
|
||||
* @param renew the renew
|
||||
* @param gateway the gateway
|
||||
* @return the string
|
||||
*/
|
||||
public static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName,
|
||||
final String serviceUrl, final boolean renew, final boolean gateway) {
|
||||
return constructRedirectUrl(casServerLoginUrl, serviceParameterName, serviceUrl, renew, gateway, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Url encode a value using UTF-8 encoding.
|
||||
*
|
||||
*
|
||||
* @param value the value to encode.
|
||||
* @return the encoded value.
|
||||
*/
|
||||
public static String urlEncode(String value) {
|
||||
public static String urlEncode(final String value) {
|
||||
try {
|
||||
return URLEncoder.encode(value, "UTF-8");
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
|
|
@ -182,8 +227,8 @@ public final class CommonUtils {
|
|||
}
|
||||
|
||||
public static void readAndRespondToProxyReceptorRequest(final HttpServletRequest request,
|
||||
final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage)
|
||||
throws IOException {
|
||||
final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage)
|
||||
throws IOException {
|
||||
final String proxyGrantingTicketIou = request.getParameter(PARAM_PROXY_GRANTING_TICKET_IOU);
|
||||
|
||||
final String proxyGrantingTicket = request.getParameter(PARAM_PROXY_GRANTING_TICKET);
|
||||
|
|
@ -194,12 +239,12 @@ public final class CommonUtils {
|
|||
}
|
||||
|
||||
LOGGER.debug("Received proxyGrantingTicketId [{}] for proxyGrantingTicketIou [{}]", proxyGrantingTicket,
|
||||
proxyGrantingTicketIou);
|
||||
proxyGrantingTicketIou);
|
||||
|
||||
proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
|
||||
|
||||
LOGGER.debug("Successfully saved proxyGrantingTicketId [{}] for proxyGrantingTicketIou [{}]",
|
||||
proxyGrantingTicket, proxyGrantingTicketIou);
|
||||
proxyGrantingTicket, proxyGrantingTicketIou);
|
||||
|
||||
response.getWriter().write("<?xml version=\"1.0\"?>");
|
||||
response.getWriter().write("<casClient:proxySuccess xmlns:casClient=\"http://www.yale.edu/tp/casClient\" />");
|
||||
|
|
@ -208,7 +253,7 @@ public final class CommonUtils {
|
|||
protected static String findMatchingServerName(final HttpServletRequest request, final String serverName) {
|
||||
final String[] serverNames = serverName.split(" ");
|
||||
|
||||
if (serverNames == null || serverNames.length == 0 || serverNames.length == 1) {
|
||||
if (serverNames.length == 0 || serverNames.length == 1) {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
|
|
@ -216,11 +261,7 @@ public final class CommonUtils {
|
|||
final String xHost = request.getHeader("X-Forwarded-Host");
|
||||
|
||||
final String comparisonHost;
|
||||
if (xHost != null && host == "localhost") {
|
||||
comparisonHost = xHost;
|
||||
} else {
|
||||
comparisonHost = host;
|
||||
}
|
||||
comparisonHost = (xHost != null) ? xHost : host;
|
||||
|
||||
if (comparisonHost == null) {
|
||||
return serverName;
|
||||
|
|
@ -237,86 +278,99 @@ public final class CommonUtils {
|
|||
return serverNames[0];
|
||||
}
|
||||
|
||||
private static boolean serverNameContainsPort(final boolean containsScheme, final String serverName) {
|
||||
if (!containsScheme && serverName.contains(":")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final int schemeIndex = serverName.indexOf(":");
|
||||
final int portIndex = serverName.lastIndexOf(":");
|
||||
return schemeIndex != portIndex;
|
||||
}
|
||||
|
||||
private static boolean requestIsOnStandardPort(final HttpServletRequest request) {
|
||||
final int serverPort = request.getServerPort();
|
||||
return serverPort == 80 || serverPort == 443;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a service url from the HttpServletRequest or from the given
|
||||
* serviceUrl. Prefers the serviceUrl provided if both a serviceUrl and a
|
||||
* serviceName.
|
||||
*
|
||||
* @param request the HttpServletRequest
|
||||
* @param response the HttpServletResponse
|
||||
* @param service the configured service url (this will be used if not null)
|
||||
* @param serverNames the server name to use to constuct the service url if the service param is empty. Note, prior to CAS Client 3.3, this was a single value.
|
||||
* As of 3.3, it can be a space-separated value. We keep it as a single value, but will convert it to an array internally to get the matching value. This keeps backward compatability with anything using this public
|
||||
* method.
|
||||
* @param artifactParameterName the artifact parameter name to remove (i.e. ticket)
|
||||
* @param encode whether to encode the url or not (i.e. Jsession).
|
||||
* @return the service url to use.
|
||||
*/
|
||||
* Constructs a service url from the HttpServletRequest or from the given
|
||||
* serviceUrl. Prefers the serviceUrl provided if both a serviceUrl and a
|
||||
* serviceName. Compiles a list of all service parameters for supported protocols
|
||||
* and removes them all from the query string.
|
||||
*
|
||||
* @param request the HttpServletRequest
|
||||
* @param response the HttpServletResponse
|
||||
* @param service the configured service url (this will be used if not null)
|
||||
* @param serverNames the server name to use to construct the service url if the service param is empty. Note, prior to CAS Client 3.3, this was a single value.
|
||||
* As of 3.3, it can be a space-separated value. We keep it as a single value, but will convert it to an array internally to get the matching value. This keeps backward compatability with anything using this public
|
||||
* method.
|
||||
* @param artifactParameterName the artifact parameter name to remove (i.e. ticket)
|
||||
* @param encode whether to encode the url or not (i.e. Jsession).
|
||||
* @return the service url to use.
|
||||
*/
|
||||
@Deprecated
|
||||
public static String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response,
|
||||
final String service, final String serverNames, final String artifactParameterName, final boolean encode) {
|
||||
final String service, final String serverNames,
|
||||
final String artifactParameterName, final boolean encode) {
|
||||
return constructServiceUrl(request, response, service, serverNames, SERVICE_PARAMETER_NAMES
|
||||
, artifactParameterName, encode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a service url from the HttpServletRequest or from the given
|
||||
* serviceUrl. Prefers the serviceUrl provided if both a serviceUrl and a
|
||||
* serviceName.
|
||||
*
|
||||
* @param request the HttpServletRequest
|
||||
* @param response the HttpServletResponse
|
||||
* @param service the configured service url (this will be used if not null)
|
||||
* @param serverNames the server name to use to construct the service url if the service param is empty. Note, prior to CAS Client 3.3, this was a single value.
|
||||
* As of 3.3, it can be a space-separated value. We keep it as a single value, but will convert it to an array internally to get the matching value. This keeps backward compatability with anything using this public
|
||||
* method.
|
||||
* @param serviceParameterName the service parameter name to remove (i.e. service)
|
||||
* @param artifactParameterName the artifact parameter name to remove (i.e. ticket)
|
||||
* @param encode whether to encode the url or not (i.e. Jsession).
|
||||
* @return the service url to use.
|
||||
*/
|
||||
public static String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response,
|
||||
final String service, final String serverNames, final String serviceParameterName,
|
||||
final String artifactParameterName, final boolean encode) {
|
||||
if (CommonUtils.isNotBlank(service)) {
|
||||
return encode ? response.encodeURL(service) : service;
|
||||
}
|
||||
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
|
||||
final String serverName = findMatchingServerName(request, serverNames);
|
||||
final URIBuilder originalRequestUrl = new URIBuilder(request.getRequestURL().toString(), encode);
|
||||
originalRequestUrl.setParameters(request.getQueryString());
|
||||
|
||||
boolean containsScheme = true;
|
||||
final URIBuilder builder;
|
||||
if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
|
||||
buffer.append(request.isSecure() ? "https://" : "http://");
|
||||
containsScheme = false;
|
||||
final String scheme = request.isSecure() ? "https://" : "http://";
|
||||
builder = new URIBuilder(scheme + serverName, encode);
|
||||
} else {
|
||||
builder = new URIBuilder(serverName, encode);
|
||||
}
|
||||
|
||||
buffer.append(serverName);
|
||||
|
||||
if (!serverNameContainsPort(containsScheme, serverName) && !requestIsOnStandardPort(request)) {
|
||||
buffer.append(":");
|
||||
buffer.append(request.getServerPort());
|
||||
if (builder.getPort() == -1 && !requestIsOnStandardPort(request)) {
|
||||
builder.setPort(request.getServerPort());
|
||||
}
|
||||
|
||||
buffer.append(request.getRequestURI());
|
||||
builder.setEncodedPath(builder.getEncodedPath() + request.getRequestURI());
|
||||
|
||||
if (CommonUtils.isNotBlank(request.getQueryString())) {
|
||||
final int location = request.getQueryString().indexOf(artifactParameterName + "=");
|
||||
|
||||
if (location == 0) {
|
||||
final String returnValue = encode ? response.encodeURL(buffer.toString()) : buffer.toString();
|
||||
LOGGER.debug("serviceUrl generated: {}", returnValue);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
buffer.append("?");
|
||||
|
||||
if (location == -1) {
|
||||
buffer.append(request.getQueryString());
|
||||
} else if (location > 0) {
|
||||
final int actualLocation = request.getQueryString().indexOf("&" + artifactParameterName + "=");
|
||||
|
||||
if (actualLocation == -1) {
|
||||
buffer.append(request.getQueryString());
|
||||
} else if (actualLocation > 0) {
|
||||
buffer.append(request.getQueryString().substring(0, actualLocation));
|
||||
final List<String> serviceParameterNames = Arrays.asList(serviceParameterName.split(","));
|
||||
if (!serviceParameterNames.isEmpty() && !originalRequestUrl.getQueryParams().isEmpty()) {
|
||||
for (final URIBuilder.BasicNameValuePair pair : originalRequestUrl.getQueryParams()) {
|
||||
final String name = pair.getName();
|
||||
if (!name.equals(artifactParameterName) && !serviceParameterNames.contains(name)) {
|
||||
if (name.contains("&") || name.contains("=")) {
|
||||
final URIBuilder encodedParamBuilder = new URIBuilder();
|
||||
encodedParamBuilder.setParameters(name);
|
||||
for (final URIBuilder.BasicNameValuePair pair2 : encodedParamBuilder.getQueryParams()) {
|
||||
final String name2 = pair2.getName();
|
||||
if (!name2.equals(artifactParameterName) && !serviceParameterNames.contains(name2)) {
|
||||
builder.addParameter(name2, pair2.getValue());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
builder.addParameter(name, pair.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String returnValue = encode ? response.encodeURL(buffer.toString()) : buffer.toString();
|
||||
final String result = builder.toString();
|
||||
final String returnValue = encode ? response.encodeURL(result) : result;
|
||||
LOGGER.debug("serviceUrl generated: {}", returnValue);
|
||||
return returnValue;
|
||||
}
|
||||
|
|
@ -338,13 +392,13 @@ public final class CommonUtils {
|
|||
* @return the value of the parameter.
|
||||
*/
|
||||
public static String safeGetParameter(final HttpServletRequest request, final String parameter,
|
||||
final List<String> parameters) {
|
||||
final List<String> parameters) {
|
||||
if ("POST".equals(request.getMethod()) && parameters.contains(parameter)) {
|
||||
LOGGER.debug("safeGetParameter called on a POST HttpServletRequest for Restricted Parameters. Cannot complete check safely. Reverting to standard behavior for this Parameter");
|
||||
return request.getParameter(parameter);
|
||||
}
|
||||
return request.getQueryString() == null || !request.getQueryString().contains(parameter) ? null : request
|
||||
.getParameter(parameter);
|
||||
.getParameter(parameter);
|
||||
}
|
||||
|
||||
public static String safeGetParameter(final HttpServletRequest request, final String parameter) {
|
||||
|
|
@ -363,8 +417,8 @@ public final class CommonUtils {
|
|||
public static String getResponseFromServer(final String constructedUrl, final String encoding) {
|
||||
try {
|
||||
return getResponseFromServer(new URL(constructedUrl), DEFAULT_URL_CONNECTION_FACTORY, encoding);
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +436,7 @@ public final class CommonUtils {
|
|||
* @return the response.
|
||||
*/
|
||||
public static String getResponseFromServer(final URL constructedUrl, final HttpURLConnectionFactory factory,
|
||||
final String encoding) {
|
||||
final String encoding) {
|
||||
|
||||
HttpURLConnection conn = null;
|
||||
InputStreamReader in = null;
|
||||
|
|
@ -402,8 +456,14 @@ public final class CommonUtils {
|
|||
}
|
||||
|
||||
return builder.toString();
|
||||
} catch (final Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final SSLException e) {
|
||||
LOGGER.error("SSL error getting response from host: {} : Error Message: {}", constructedUrl.getHost(), e.getMessage(), e);
|
||||
throw new RuntimeException(e);
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error("Error getting response from host: [{}] with path: [{}] and protocol: [{}] Error Message: {}",
|
||||
constructedUrl.getHost(), constructedUrl.getPath(), constructedUrl.getProtocol(), e.getMessage(), e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
closeQuietly(in);
|
||||
|
|
@ -432,7 +492,7 @@ public final class CommonUtils {
|
|||
public static void sendRedirect(final HttpServletResponse response, final String url) {
|
||||
try {
|
||||
response.sendRedirect(url);
|
||||
} catch (final Exception e) {
|
||||
} catch (final IOException e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +501,7 @@ public final class CommonUtils {
|
|||
/**
|
||||
* Unconditionally close a {@link Closeable}. Equivalent to {@link java.io.Closeable#close()}close(), except any exceptions
|
||||
* will be ignored. This is typically used in finally blocks.
|
||||
* @param resource
|
||||
* @param resource the resource to close
|
||||
*/
|
||||
public static void closeQuietly(final Closeable resource) {
|
||||
try {
|
||||
|
|
@ -452,4 +512,236 @@ public final class CommonUtils {
|
|||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Converts a String to a boolean (optimised for performance).</p>
|
||||
*
|
||||
* <p>{@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}
|
||||
* (case insensitive) will return {@code true}. Otherwise,
|
||||
* {@code false} is returned.</p>
|
||||
*
|
||||
* <p>This method performs 4 times faster (JDK1.4) than
|
||||
* {@code Boolean.valueOf(String)}. However, this method accepts
|
||||
* 'on' and 'yes', 't', 'y' as true values.
|
||||
*
|
||||
* <pre>
|
||||
* BooleanUtils.toBoolean(null) = false
|
||||
* BooleanUtils.toBoolean("true") = true
|
||||
* BooleanUtils.toBoolean("TRUE") = true
|
||||
* BooleanUtils.toBoolean("tRUe") = true
|
||||
* BooleanUtils.toBoolean("on") = true
|
||||
* BooleanUtils.toBoolean("yes") = true
|
||||
* BooleanUtils.toBoolean("false") = false
|
||||
* BooleanUtils.toBoolean("x gti") = false
|
||||
* BooleanUtils.toBooleanObject("y") = true
|
||||
* BooleanUtils.toBooleanObject("n") = false
|
||||
* BooleanUtils.toBooleanObject("t") = true
|
||||
* BooleanUtils.toBooleanObject("f") = false
|
||||
* </pre>
|
||||
*
|
||||
* @param str the String to check
|
||||
* @return the boolean value of the string, {@code false} if no match or the String is null
|
||||
*/
|
||||
public static boolean toBoolean(final String str) {
|
||||
return toBooleanObject(str) == Boolean.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Converts a String to a Boolean.</p>
|
||||
*
|
||||
* <p>{@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}
|
||||
* (case insensitive) will return {@code true}.
|
||||
* {@code 'false'}, {@code 'off'}, {@code 'n'}, {@code 'f'} or {@code 'no'}
|
||||
* (case insensitive) will return {@code false}.
|
||||
* Otherwise, {@code null} is returned.</p>
|
||||
*
|
||||
* <p>NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean. </p>
|
||||
*
|
||||
* <pre>
|
||||
* // N.B. case is not significant
|
||||
* BooleanUtils.toBooleanObject(null) = null
|
||||
* BooleanUtils.toBooleanObject("true") = Boolean.TRUE
|
||||
* BooleanUtils.toBooleanObject("T") = Boolean.TRUE // i.e. T[RUE]
|
||||
* BooleanUtils.toBooleanObject("false") = Boolean.FALSE
|
||||
* BooleanUtils.toBooleanObject("f") = Boolean.FALSE // i.e. f[alse]
|
||||
* BooleanUtils.toBooleanObject("No") = Boolean.FALSE
|
||||
* BooleanUtils.toBooleanObject("n") = Boolean.FALSE // i.e. n[o]
|
||||
* BooleanUtils.toBooleanObject("on") = Boolean.TRUE
|
||||
* BooleanUtils.toBooleanObject("ON") = Boolean.TRUE
|
||||
* BooleanUtils.toBooleanObject("off") = Boolean.FALSE
|
||||
* BooleanUtils.toBooleanObject("oFf") = Boolean.FALSE
|
||||
* BooleanUtils.toBooleanObject("yes") = Boolean.TRUE
|
||||
* BooleanUtils.toBooleanObject("Y") = Boolean.TRUE // i.e. Y[ES]
|
||||
* BooleanUtils.toBooleanObject("blue") = null
|
||||
* BooleanUtils.toBooleanObject("true ") = null // trailing space (too long)
|
||||
* BooleanUtils.toBooleanObject("ono") = null // does not match on or no
|
||||
* </pre>
|
||||
*
|
||||
* @param str the String to check; upper and lower case are treated as the same
|
||||
* @return the Boolean value of the string, {@code null} if no match or {@code null} input
|
||||
*/
|
||||
public static Boolean toBooleanObject(final String str) {
|
||||
// Previously used equalsIgnoreCase, which was fast for interned 'true'.
|
||||
// Non interned 'true' matched 15 times slower.
|
||||
//
|
||||
// Optimisation provides same performance as before for interned 'true'.
|
||||
// Similar performance for null, 'false', and other strings not length 2/3/4.
|
||||
// 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
|
||||
if (str == "true") {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
switch (str.length()) {
|
||||
case 1: {
|
||||
final char ch0 = str.charAt(0);
|
||||
if (ch0 == 'y' || ch0 == 'Y' ||
|
||||
ch0 == 't' || ch0 == 'T') {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if (ch0 == 'n' || ch0 == 'N' ||
|
||||
ch0 == 'f' || ch0 == 'F') {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
final char ch0 = str.charAt(0);
|
||||
final char ch1 = str.charAt(1);
|
||||
if ((ch0 == 'o' || ch0 == 'O') &&
|
||||
(ch1 == 'n' || ch1 == 'N')) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if ((ch0 == 'n' || ch0 == 'N') &&
|
||||
(ch1 == 'o' || ch1 == 'O')) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
final char ch0 = str.charAt(0);
|
||||
final char ch1 = str.charAt(1);
|
||||
final char ch2 = str.charAt(2);
|
||||
if ((ch0 == 'y' || ch0 == 'Y') &&
|
||||
(ch1 == 'e' || ch1 == 'E') &&
|
||||
(ch2 == 's' || ch2 == 'S')) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if ((ch0 == 'o' || ch0 == 'O') &&
|
||||
(ch1 == 'f' || ch1 == 'F') &&
|
||||
(ch2 == 'f' || ch2 == 'F')) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
final char ch0 = str.charAt(0);
|
||||
final char ch1 = str.charAt(1);
|
||||
final char ch2 = str.charAt(2);
|
||||
final char ch3 = str.charAt(3);
|
||||
if ((ch0 == 't' || ch0 == 'T') &&
|
||||
(ch1 == 'r' || ch1 == 'R') &&
|
||||
(ch2 == 'u' || ch2 == 'U') &&
|
||||
(ch3 == 'e' || ch3 == 'E')) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
final char ch0 = str.charAt(0);
|
||||
final char ch1 = str.charAt(1);
|
||||
final char ch2 = str.charAt(2);
|
||||
final char ch3 = str.charAt(3);
|
||||
final char ch4 = str.charAt(4);
|
||||
if ((ch0 == 'f' || ch0 == 'F') &&
|
||||
(ch1 == 'a' || ch1 == 'A') &&
|
||||
(ch2 == 'l' || ch2 == 'L') &&
|
||||
(ch3 == 's' || ch3 == 'S') &&
|
||||
(ch4 == 'e' || ch4 == 'E')) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convert a <code>String</code> to a <code>long</code>, returning a
|
||||
* default value if the conversion fails.</p>
|
||||
*
|
||||
* <p>If the string is <code>null</code>, the default value is returned.</p>
|
||||
*
|
||||
* <pre>
|
||||
* NumberUtils.toLong(null, 1L) = 1L
|
||||
* NumberUtils.toLong("", 1L) = 1L
|
||||
* NumberUtils.toLong("1", 0L) = 1L
|
||||
* </pre>
|
||||
*
|
||||
* @param str the string to convert, may be null
|
||||
* @param defaultValue the default value
|
||||
* @return the long represented by the string, or the default if conversion fails
|
||||
*/
|
||||
public static long toLong(final String str, final long defaultValue) {
|
||||
if (str == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(str);
|
||||
} catch (final NumberFormatException nfe) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convert a <code>String</code> to an <code>int</code>, returning a
|
||||
* default value if the conversion fails.</p>
|
||||
*
|
||||
* <p>If the string is <code>null</code>, the default value is returned.</p>
|
||||
*
|
||||
* <pre>
|
||||
* NumberUtils.toInt(null, 1) = 1
|
||||
* NumberUtils.toInt("", 1) = 1
|
||||
* NumberUtils.toInt("1", 0) = 1
|
||||
* </pre>
|
||||
*
|
||||
* @param str the string to convert, may be null
|
||||
* @param defaultValue the default value
|
||||
* @return the int represented by the string, or the default if conversion fails
|
||||
*/
|
||||
public static int toInt(final String str, final int defaultValue) {
|
||||
if (str == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(str);
|
||||
} catch (final NumberFormatException nfe) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string as-is, unless it's <code>null</code>;
|
||||
* in this case an empty string is returned.
|
||||
*
|
||||
* @param string a possibly <code>null</code> string
|
||||
* @return a non-<code>null</code> string
|
||||
*/
|
||||
public static String nullToEmpty(final String string) {
|
||||
return string == null ? "" : string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trailing slash to the given uri, if it doesn't already have one.
|
||||
*
|
||||
* @param uri a string that may or may not end with a slash
|
||||
* @return the same string, except with a slash suffix (if necessary).
|
||||
*/
|
||||
public static String addTrailingSlash(final String uri) {
|
||||
return uri.endsWith("/") ? uri : uri + "/";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -31,7 +31,6 @@ import org.slf4j.LoggerFactory;
|
|||
* the associated filter is executed. Otherwise, the normal chain is executed.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11729 $ $Date: 2006-09-26 14:22:30 -0400 (Tue, 26 Sep 2006) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class DelegatingFilter implements Filter {
|
||||
|
|
@ -78,10 +77,12 @@ public final class DelegatingFilter implements Filter {
|
|||
this.exactMatch = exactMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
|
|
@ -108,6 +109,7 @@ public final class DelegatingFilter implements Filter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
// nothing to do here.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -24,22 +24,22 @@ import java.util.Enumeration;
|
|||
import java.util.List;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Filters that redirects to the supplied url based on an exception. Exceptions and the urls are configured via
|
||||
* init filter name/param values.
|
||||
* <p>
|
||||
* <p/>
|
||||
* If there is an exact match the filter uses that value. If there's a non-exact match (i.e. inheritance), then the filter
|
||||
* uses the last value that matched.
|
||||
* <p>
|
||||
* <p/>
|
||||
* If there is no match it will redirect to a default error page. The default exception is configured via the "defaultErrorRedirectPage" property.
|
||||
*
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision$ $Date$
|
||||
* @since 3.1.4
|
||||
*
|
||||
*/
|
||||
public final class ErrorRedirectFilter implements Filter {
|
||||
|
||||
|
|
@ -49,17 +49,19 @@ public final class ErrorRedirectFilter implements Filter {
|
|||
|
||||
private String defaultErrorRedirectPage;
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
final HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (final ServletException e) {
|
||||
final Throwable t = e.getCause();
|
||||
} catch (final Exception e) {
|
||||
final Throwable t = extractErrorToCompare(e);
|
||||
ErrorHolder currentMatch = null;
|
||||
for (final ErrorHolder errorHolder : this.errors) {
|
||||
if (errorHolder.exactMatch(t)) {
|
||||
|
|
@ -78,6 +80,23 @@ public final class ErrorRedirectFilter implements Filter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine which error to use for comparison. If there is an {@link Throwable#getCause()} then that will be used. Otherwise, the original throwable is used.
|
||||
*
|
||||
* @param throwable the throwable to look for a root cause.
|
||||
* @return the throwable to use for comparison. MUST NOT BE NULL.
|
||||
*/
|
||||
private Throwable extractErrorToCompare(final Throwable throwable) {
|
||||
final Throwable cause = throwable.getCause();
|
||||
|
||||
if (cause != null) {
|
||||
return cause;
|
||||
}
|
||||
|
||||
return throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
this.defaultErrorRedirectPage = filterConfig.getInitParameter("defaultErrorRedirectPage");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
|
||||
/**
|
||||
|
|
@ -43,7 +44,6 @@ import org.jasig.cas.client.validation.Assertion;
|
|||
*
|
||||
* @author Scott Battaglia
|
||||
* @author Marvin S. Addison
|
||||
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class HttpServletRequestWrapperFilter extends AbstractConfigurationFilter {
|
||||
|
|
@ -54,6 +54,7 @@ public final class HttpServletRequestWrapperFilter extends AbstractConfiguration
|
|||
/** Whether or not to ignore case in role membership queries */
|
||||
private boolean ignoreCase;
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// nothing to do
|
||||
}
|
||||
|
|
@ -63,8 +64,9 @@ public final class HttpServletRequestWrapperFilter extends AbstractConfiguration
|
|||
* <code>request.getRemoteUser</code> to the underlying Assertion object
|
||||
* stored in the user session.
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final AttributePrincipal principal = retrievePrincipalFromSessionOrRequest(servletRequest);
|
||||
|
||||
filterChain.doFilter(new CasHttpServletRequestWrapper((HttpServletRequest) servletRequest, principal),
|
||||
|
|
@ -81,9 +83,11 @@ public final class HttpServletRequestWrapperFilter extends AbstractConfiguration
|
|||
return assertion == null ? null : assertion.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
this.roleAttribute = getPropertyFromInitParams(filterConfig, "roleAttribute", null);
|
||||
this.ignoreCase = Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "ignoreCase", "false"));
|
||||
super.init(filterConfig);
|
||||
this.roleAttribute = getString(ConfigurationKeys.ROLE_ATTRIBUTE);
|
||||
this.ignoreCase = getBoolean(ConfigurationKeys.IGNORE_CASE);
|
||||
}
|
||||
|
||||
final class CasHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
|
@ -95,14 +99,17 @@ public final class HttpServletRequestWrapperFilter extends AbstractConfiguration
|
|||
this.principal = principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteUser() {
|
||||
return principal != null ? this.principal.getName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(final String role) {
|
||||
if (CommonUtils.isBlank(role)) {
|
||||
logger.debug("No valid role provided. Returning false.");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* IO utility class.
|
||||
*
|
||||
* @author Marvin S. Addison
|
||||
* @since 3.4
|
||||
*/
|
||||
public final class IOUtils {
|
||||
|
||||
/** UTF-8 character set. */
|
||||
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
|
||||
private IOUtils() { /** Utility class pattern. */ }
|
||||
|
||||
/**
|
||||
* Reads all data from the given stream as UTF-8 character data and closes it on completion or errors.
|
||||
*
|
||||
* @param in Input stream containing character data.
|
||||
*
|
||||
* @return String of all data in stream.
|
||||
*
|
||||
* @throws IOException On IO errors.
|
||||
*/
|
||||
public static String readString(final InputStream in) throws IOException {
|
||||
return readString(in, UTF8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all data from the given stream as character data in the given character set and closes it on completion
|
||||
* or errors.
|
||||
*
|
||||
* @param in Input stream containing character data.
|
||||
* @param charset Character set of data in stream.
|
||||
*
|
||||
* @return String of all data in stream.
|
||||
*
|
||||
* @throws IOException On IO errors.
|
||||
*/
|
||||
public static String readString(final InputStream in, final Charset charset) throws IOException {
|
||||
final Reader reader = new InputStreamReader(in, charset);
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final CharBuffer buffer = CharBuffer.allocate(2048);
|
||||
try {
|
||||
while (reader.read(buffer) > -1) {
|
||||
buffer.flip();
|
||||
builder.append(buffer);
|
||||
}
|
||||
} finally {
|
||||
closeQuietly(reader);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally close a {@link Closeable} resource. Errors on close are ignored.
|
||||
*
|
||||
* @param resource Resource to close.
|
||||
*/
|
||||
public static void closeQuietly(final Closeable resource) {
|
||||
try {
|
||||
if (resource != null) {
|
||||
resource.close();
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.util;
|
||||
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Namespace context implementation backed by a map of XML prefixes to namespace URIs.
|
||||
*
|
||||
* @author Marvin S. Addison
|
||||
* @since 3.4
|
||||
*/
|
||||
public class MapNamespaceContext implements NamespaceContext {
|
||||
|
||||
private final Map<String, String> namespaceMap;
|
||||
|
||||
/**
|
||||
* Creates a new instance from an array of namespace delcarations.
|
||||
*
|
||||
* @param namespaceDeclarations An array of namespace declarations of the form prefix->uri.
|
||||
*/
|
||||
public MapNamespaceContext(final String ... namespaceDeclarations) {
|
||||
namespaceMap = new HashMap<String, String>();
|
||||
int index;
|
||||
String key;
|
||||
String value;
|
||||
for (final String decl : namespaceDeclarations) {
|
||||
index = decl.indexOf('-');
|
||||
key = decl.substring(0, index);
|
||||
value = decl.substring(index + 2);
|
||||
namespaceMap.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance from a map.
|
||||
*
|
||||
* @param namespaceMap Map of XML namespace prefixes (keys) to URIs (values).
|
||||
*/
|
||||
public MapNamespaceContext(final Map<String, String> namespaceMap) {
|
||||
this.namespaceMap = namespaceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespaceURI(final String prefix) {
|
||||
return namespaceMap.get(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix(final String namespaceURI) {
|
||||
for (final Map.Entry<String, String> entry : namespaceMap.entrySet()) {
|
||||
if (entry.getValue().equalsIgnoreCase(namespaceURI)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator getPrefixes(final String namespaceURI) {
|
||||
return Collections.singleton(getPrefix(namespaceURI)).iterator();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.util;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* Utility class to parse private keys.
|
||||
*
|
||||
* @author Jerome LELEU
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public class PrivateKeyUtils {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PrivateKeyUtils.class);
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public static PrivateKey createKey(final String path, final String algorithm) {
|
||||
final PrivateKey key = readPemPrivateKey(path);
|
||||
if (key == null) {
|
||||
return readDERPrivateKey(path, algorithm);
|
||||
} else {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
private static PrivateKey readPemPrivateKey(final String path) {
|
||||
LOGGER.debug("Attempting to read as PEM [{}]", path);
|
||||
final File file = new File(path);
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
isr = new FileReader(file);
|
||||
br = new BufferedReader(isr);
|
||||
final PEMParser pp = new PEMParser(br);
|
||||
final PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject();
|
||||
final KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
|
||||
return kp.getPrivate();
|
||||
} catch (final Exception e) {
|
||||
LOGGER.error("Unable to read key", e);
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (br != null) {
|
||||
br.close();
|
||||
}
|
||||
if (isr != null) {
|
||||
isr.close();
|
||||
}
|
||||
} catch (final IOException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
private static PrivateKey readDERPrivateKey(final String path, final String algorithm) {
|
||||
LOGGER.debug("Attempting to read key as DER [{}]", path);
|
||||
final File file = new File(path);
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
final long byteLength = file.length();
|
||||
final byte[] bytes = new byte[(int) byteLength];
|
||||
fis.read(bytes, 0, (int) byteLength);
|
||||
final PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(bytes);
|
||||
final KeyFactory factory = KeyFactory.getInstance(algorithm);
|
||||
return factory.generatePrivate(privSpec);
|
||||
} catch (final Exception e) {
|
||||
LOGGER.error("Unable to read key", e);
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (fis != null) {
|
||||
fis.close();
|
||||
}
|
||||
} catch (final IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -22,6 +22,7 @@ import java.beans.BeanInfo;
|
|||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
|
|
@ -148,4 +149,35 @@ public final class ReflectUtils {
|
|||
throw new RuntimeException("Error setting property " + propertyName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the given declared field on the target object or any of its superclasses.
|
||||
*
|
||||
* @param fieldName Name of field to get.
|
||||
* @param target Target object that possesses field.
|
||||
*
|
||||
* @return Field value.
|
||||
*/
|
||||
public static Object getField(final String fieldName, final Object target) {
|
||||
Class<?> clazz = target.getClass();
|
||||
Field field = null;
|
||||
do {
|
||||
try {
|
||||
field = clazz.getDeclaredField(fieldName);
|
||||
} catch (final NoSuchFieldException e) {
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
} while (field == null && clazz != null);
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException(fieldName + " does not exist on " + target);
|
||||
}
|
||||
try {
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
return field.get(target);
|
||||
} catch (final Exception e) {
|
||||
throw new IllegalArgumentException("Error getting field " + fieldName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.util;
|
||||
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.*;
|
||||
|
||||
/**
|
||||
* Thread local XPath expression.
|
||||
*
|
||||
* @author Marvin S. Addison
|
||||
* @since 3.4
|
||||
*/
|
||||
public class ThreadLocalXPathExpression extends ThreadLocal<XPathExpression> implements XPathExpression {
|
||||
|
||||
/** XPath expression */
|
||||
private final String expression;
|
||||
|
||||
/** Namespace context. */
|
||||
private final NamespaceContext context;
|
||||
|
||||
/**
|
||||
* Creates a new instance from an XPath expression and namespace context.
|
||||
*
|
||||
* @param xPath XPath expression.
|
||||
* @param context Namespace context for handling namespace prefix to URI mappings.
|
||||
*/
|
||||
public ThreadLocalXPathExpression(final String xPath, final NamespaceContext context) {
|
||||
this.expression = xPath;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(final Object o, final QName qName) throws XPathExpressionException {
|
||||
return get().evaluate(o, qName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String evaluate(final Object o) throws XPathExpressionException {
|
||||
return get().evaluate(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(final InputSource inputSource, final QName qName) throws XPathExpressionException {
|
||||
return get().evaluate(inputSource, qName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String evaluate(final InputSource inputSource) throws XPathExpressionException {
|
||||
return get().evaluate(inputSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the XPath expression and returns the result coerced to a string.
|
||||
*
|
||||
* @param o Object on which to evaluate the expression; typically a DOM node.
|
||||
*
|
||||
* @return Evaluation result as a string.
|
||||
*
|
||||
* @throws XPathExpressionException On XPath evaluation errors.
|
||||
*/
|
||||
public String evaluateAsString(final Object o) throws XPathExpressionException {
|
||||
return (String) evaluate(o, XPathConstants.STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the XPath expression and returns the result coerced to a node list.
|
||||
*
|
||||
* @param o Object on which to evaluate the expression; typically a DOM node.
|
||||
*
|
||||
* @return Evaluation result as a node list.
|
||||
*
|
||||
* @throws XPathExpressionException On XPath evaluation errors.
|
||||
*/
|
||||
public NodeList evaluateAsNodeList(final Object o) throws XPathExpressionException {
|
||||
return (NodeList) evaluate(o, XPathConstants.NODESET);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XPathExpression initialValue() {
|
||||
try {
|
||||
final XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
xPath.setNamespaceContext(context);
|
||||
return xPath.compile(expression);
|
||||
} catch (final XPathExpressionException e) {
|
||||
throw new IllegalArgumentException("Invalid XPath expression");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,682 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A utility class borrowed from apache http-client to build uris.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.4
|
||||
*/
|
||||
public final class URIBuilder {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(URIBuilder.class);
|
||||
private static final Pattern IPV6_STD_PATTERN = Pattern.compile("^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$");
|
||||
|
||||
private String scheme;
|
||||
private String encodedSchemeSpecificPart;
|
||||
private String encodedAuthority;
|
||||
private String userInfo;
|
||||
private String encodedUserInfo;
|
||||
private String host;
|
||||
private int port;
|
||||
private String path;
|
||||
private String encodedPath;
|
||||
private String encodedQuery;
|
||||
private List<BasicNameValuePair> queryParams;
|
||||
private String query;
|
||||
private boolean encode;
|
||||
private String fragment;
|
||||
private String encodedFragment;
|
||||
|
||||
/**
|
||||
* Constructs an empty instance.
|
||||
*/
|
||||
public URIBuilder() {
|
||||
super();
|
||||
this.port = -1;
|
||||
}
|
||||
|
||||
public URIBuilder(final boolean encode) {
|
||||
this();
|
||||
setEncode(encode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance from the string which must be a valid URI.
|
||||
*
|
||||
* @param string a valid URI in string form
|
||||
* @throws RuntimeException if the input is not a valid URI
|
||||
*/
|
||||
public URIBuilder(final String string) {
|
||||
super();
|
||||
try {
|
||||
digestURI(new URI(string));
|
||||
} catch (final URISyntaxException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public URIBuilder(final String string, final boolean encode) {
|
||||
super();
|
||||
try {
|
||||
setEncode(encode);
|
||||
digestURI(new URI(string));
|
||||
} catch (final URISyntaxException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct an instance from the provided URI.
|
||||
*
|
||||
* @param uri the uri to digest
|
||||
*/
|
||||
public URIBuilder(final URI uri) {
|
||||
super();
|
||||
digestURI(uri);
|
||||
}
|
||||
|
||||
private List<BasicNameValuePair> parseQuery(final String query) {
|
||||
|
||||
try {
|
||||
final Charset utf8 = Charset.forName("UTF-8");
|
||||
if (query != null && !query.isEmpty()) {
|
||||
final List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
|
||||
final String[] parametersArray = query.split("&");
|
||||
|
||||
for (final String parameter : parametersArray) {
|
||||
final int firstIndex = parameter.indexOf("=");
|
||||
if (firstIndex != -1) {
|
||||
final String paramName = parameter.substring(0, firstIndex);
|
||||
final String decodedParamName = URLDecoder.decode(paramName, utf8.name());
|
||||
|
||||
final String paramVal = parameter.substring(firstIndex + 1);
|
||||
final String decodedParamVal = URLDecoder.decode(paramVal, utf8.name());
|
||||
|
||||
list.add(new BasicNameValuePair(decodedParamName, decodedParamVal));
|
||||
} else {
|
||||
// Either we do not have a query parameter, or it might be encoded; take it verbaitm
|
||||
final String[] parameterCombo = parameter.split("=");
|
||||
if (parameterCombo.length >= 1) {
|
||||
final String key = URLDecoder.decode(parameterCombo[0], utf8.name());
|
||||
final String val = parameterCombo.length == 2 ? URLDecoder.decode(parameterCombo[1], utf8.name()) : "";
|
||||
list.add(new BasicNameValuePair(key, val));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
return new ArrayList<BasicNameValuePair>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link URI} instance.
|
||||
*/
|
||||
public URI build() {
|
||||
try {
|
||||
return new URI(buildString());
|
||||
} catch (final URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isIPv6Address(final String input) {
|
||||
return IPV6_STD_PATTERN.matcher(input).matches();
|
||||
}
|
||||
|
||||
private String buildString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (this.scheme != null) {
|
||||
sb.append(this.scheme).append(':');
|
||||
}
|
||||
if (this.encodedSchemeSpecificPart != null) {
|
||||
sb.append(this.encodedSchemeSpecificPart);
|
||||
} else {
|
||||
if (this.encodedAuthority != null) {
|
||||
sb.append("//").append(this.encodedAuthority);
|
||||
} else if (this.host != null) {
|
||||
sb.append("//");
|
||||
if (this.encodedUserInfo != null) {
|
||||
sb.append(this.encodedUserInfo).append("@");
|
||||
} else if (this.userInfo != null) {
|
||||
sb.append(encodeUserInfo(this.userInfo)).append("@");
|
||||
}
|
||||
if (isIPv6Address(this.host)) {
|
||||
sb.append("[").append(this.host).append("]");
|
||||
} else {
|
||||
sb.append(this.host);
|
||||
}
|
||||
if (this.port >= 0) {
|
||||
sb.append(":").append(this.port);
|
||||
}
|
||||
}
|
||||
if (this.encodedPath != null) {
|
||||
sb.append(normalizePath(this.encodedPath));
|
||||
} else if (this.path != null) {
|
||||
sb.append(encodePath(normalizePath(this.path)));
|
||||
}
|
||||
if (this.encodedQuery != null) {
|
||||
sb.append("?").append(this.encodedQuery);
|
||||
} else if (this.queryParams != null && !this.queryParams.isEmpty()) {
|
||||
sb.append("?").append(encodeUrlForm(this.queryParams));
|
||||
} else if (this.query != null) {
|
||||
sb.append("?").append(encodeUric(this.query));
|
||||
}
|
||||
}
|
||||
if (this.encodedFragment != null) {
|
||||
sb.append("#").append(this.encodedFragment);
|
||||
} else if (this.fragment != null) {
|
||||
sb.append("#").append(encodeUric(this.fragment));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public URIBuilder digestURI(final URI uri) {
|
||||
this.scheme = uri.getScheme();
|
||||
this.encodedSchemeSpecificPart = uri.getRawSchemeSpecificPart();
|
||||
this.encodedAuthority = uri.getRawAuthority();
|
||||
this.host = uri.getHost();
|
||||
this.port = uri.getPort();
|
||||
this.encodedUserInfo = uri.getRawUserInfo();
|
||||
this.userInfo = uri.getUserInfo();
|
||||
this.encodedPath = uri.getRawPath();
|
||||
this.path = uri.getPath();
|
||||
this.encodedQuery = uri.getRawQuery();
|
||||
this.queryParams = parseQuery(uri.getRawQuery());
|
||||
this.encodedFragment = uri.getRawFragment();
|
||||
this.fragment = uri.getFragment();
|
||||
return this;
|
||||
}
|
||||
|
||||
private String encodeUserInfo(final String userInfo) {
|
||||
return this.encode ? CommonUtils.urlEncode(userInfo) : userInfo;
|
||||
}
|
||||
|
||||
private String encodePath(final String path) {
|
||||
return this.encode ? CommonUtils.urlEncode(path) : path;
|
||||
}
|
||||
|
||||
private String encodeUrlForm(final List<BasicNameValuePair> params) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (final BasicNameValuePair parameter : params) {
|
||||
final String encodedName = this.encode ? CommonUtils.urlEncode(parameter.getName()) : parameter.getName();
|
||||
final String encodedValue = this.encode ? CommonUtils.urlEncode(parameter.getValue()) : parameter.getValue();
|
||||
|
||||
if (result.length() > 0) {
|
||||
result.append("&");
|
||||
}
|
||||
result.append(encodedName);
|
||||
if (encodedValue != null) {
|
||||
result.append("=");
|
||||
result.append(encodedValue);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String encodeUric(final String fragment) {
|
||||
return this.encode ? CommonUtils.urlEncode(fragment) : fragment;
|
||||
}
|
||||
|
||||
public URIBuilder setEncode(final boolean encode) {
|
||||
this.encode = encode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI scheme.
|
||||
*/
|
||||
public URIBuilder setScheme(final String scheme) {
|
||||
this.scheme = scheme;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI user info. The value is expected to be unescaped and may contain non ASCII
|
||||
* characters.
|
||||
*/
|
||||
public URIBuilder setUserInfo(final String userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.encodedAuthority = null;
|
||||
this.encodedUserInfo = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI user info as a combination of username and password. These values are expected to
|
||||
* be unescaped and may contain non ASCII characters.
|
||||
*/
|
||||
public URIBuilder setUserInfo(final String username, final String password) {
|
||||
return setUserInfo(username + ':' + password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI host.
|
||||
*/
|
||||
public URIBuilder setHost(final String host) {
|
||||
this.host = host;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.encodedAuthority = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI port.
|
||||
*/
|
||||
public URIBuilder setPort(final int port) {
|
||||
this.port = port < 0 ? -1 : port;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.encodedAuthority = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI path. The value is expected to be unescaped and may contain non ASCII characters.
|
||||
*/
|
||||
public URIBuilder setPath(final String path) {
|
||||
this.path = path;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.encodedPath = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public URIBuilder setEncodedPath(final String path) {
|
||||
this.encodedPath = path;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes URI query.
|
||||
*/
|
||||
public URIBuilder removeQuery() {
|
||||
this.queryParams = null;
|
||||
this.query = null;
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI query parameters. The parameter name / values are expected to be unescaped
|
||||
* and may contain non ASCII characters.
|
||||
* <p>
|
||||
* Please note query parameters and custom query component are mutually exclusive. This method
|
||||
* will remove custom query if present.
|
||||
* </p>
|
||||
*/
|
||||
public URIBuilder setParameters(final List<BasicNameValuePair> nvps) {
|
||||
this.queryParams = new ArrayList<BasicNameValuePair>();
|
||||
this.queryParams.addAll(nvps);
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.query = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public URIBuilder setParameters(final String queryParameters) {
|
||||
this.queryParams = new ArrayList<BasicNameValuePair>();
|
||||
this.queryParams.addAll(parseQuery(queryParameters));
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.query = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds URI query parameters. The parameter name / values are expected to be unescaped
|
||||
* and may contain non ASCII characters.
|
||||
* <p>
|
||||
* Please note query parameters and custom query component are mutually exclusive. This method
|
||||
* will remove custom query if present.
|
||||
* </p>
|
||||
*/
|
||||
public URIBuilder addParameters(final List<BasicNameValuePair> nvps) {
|
||||
if (this.queryParams == null || this.queryParams.isEmpty()) {
|
||||
this.queryParams = new ArrayList<BasicNameValuePair>();
|
||||
}
|
||||
this.queryParams.addAll(nvps);
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.query = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI query parameters. The parameter name / values are expected to be unescaped
|
||||
* and may contain non ASCII characters.
|
||||
* <p>
|
||||
* Please note query parameters and custom query component are mutually exclusive. This method
|
||||
* will remove custom query if present.
|
||||
* </p>
|
||||
*/
|
||||
public URIBuilder setParameters(final BasicNameValuePair... nvps) {
|
||||
if (this.queryParams == null) {
|
||||
this.queryParams = new ArrayList<BasicNameValuePair>();
|
||||
} else {
|
||||
this.queryParams.clear();
|
||||
}
|
||||
for (final BasicNameValuePair nvp : nvps) {
|
||||
this.queryParams.add(nvp);
|
||||
}
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.query = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds parameter to URI query. The parameter name and value are expected to be unescaped
|
||||
* and may contain non ASCII characters.
|
||||
* <p>
|
||||
* Please note query parameters and custom query component are mutually exclusive. This method
|
||||
* will remove custom query if present.
|
||||
* </p>
|
||||
*/
|
||||
public URIBuilder addParameter(final String param, final String value) {
|
||||
if (this.queryParams == null) {
|
||||
this.queryParams = new ArrayList<BasicNameValuePair>();
|
||||
}
|
||||
this.queryParams.add(new BasicNameValuePair(param, value));
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.query = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets parameter of URI query overriding existing value if set. The parameter name and value
|
||||
* are expected to be unescaped and may contain non ASCII characters.
|
||||
* <p>
|
||||
* Please note query parameters and custom query component are mutually exclusive. This method
|
||||
* will remove custom query if present.
|
||||
* </p>
|
||||
*/
|
||||
public URIBuilder setParameter(final String param, final String value) {
|
||||
if (this.queryParams == null) {
|
||||
this.queryParams = new ArrayList<BasicNameValuePair>();
|
||||
}
|
||||
if (!this.queryParams.isEmpty()) {
|
||||
for (final Iterator<BasicNameValuePair> it = this.queryParams.iterator(); it.hasNext(); ) {
|
||||
final BasicNameValuePair nvp = it.next();
|
||||
if (nvp.getName().equals(param)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.queryParams.add(new BasicNameValuePair(param, value));
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.query = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears URI query parameters.
|
||||
*/
|
||||
public URIBuilder clearParameters() {
|
||||
this.queryParams = null;
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom URI query. The value is expected to be unescaped and may contain non ASCII
|
||||
* characters.
|
||||
* <p>
|
||||
* Please note query parameters and custom query component are mutually exclusive. This method
|
||||
* will remove query parameters if present.
|
||||
* </p>
|
||||
*/
|
||||
public URIBuilder setCustomQuery(final String query) {
|
||||
this.query = query;
|
||||
this.encodedQuery = null;
|
||||
this.encodedSchemeSpecificPart = null;
|
||||
this.queryParams = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets URI fragment. The value is expected to be unescaped and may contain non ASCII
|
||||
* characters.
|
||||
*/
|
||||
public URIBuilder setFragment(final String fragment) {
|
||||
this.fragment = fragment;
|
||||
this.encodedFragment = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public URIBuilder setEncodedFragment(final String fragment) {
|
||||
this.fragment = null;
|
||||
this.encodedFragment = fragment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public URIBuilder setEncodedQuery(final String query) {
|
||||
this.query = null;
|
||||
this.encodedFragment = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAbsolute() {
|
||||
return this.scheme != null;
|
||||
}
|
||||
|
||||
public boolean isOpaque() {
|
||||
return this.path == null;
|
||||
}
|
||||
|
||||
public String getScheme() {
|
||||
return this.scheme;
|
||||
}
|
||||
|
||||
public String getUserInfo() {
|
||||
return this.userInfo;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public String getEncodedPath() {
|
||||
return this.encodedPath;
|
||||
}
|
||||
|
||||
public List<BasicNameValuePair> getQueryParams() {
|
||||
if (this.queryParams != null) {
|
||||
return new ArrayList<BasicNameValuePair>(this.queryParams);
|
||||
}
|
||||
return new ArrayList<BasicNameValuePair>();
|
||||
|
||||
}
|
||||
|
||||
public String getFragment() {
|
||||
return this.fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return buildString();
|
||||
}
|
||||
|
||||
private static String normalizePath(final String path) {
|
||||
String s = path;
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
int n = 0;
|
||||
for (; n < s.length(); n++) {
|
||||
if (s.charAt(n) != '/') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n > 1) {
|
||||
s = s.substring(n - 1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final URIBuilder that = (URIBuilder) o;
|
||||
|
||||
if (port != that.port) return false;
|
||||
if (encode != that.encode) return false;
|
||||
if (scheme != null ? !scheme.equals(that.scheme) : that.scheme != null) return false;
|
||||
if (encodedSchemeSpecificPart != null ? !encodedSchemeSpecificPart.equals(that.encodedSchemeSpecificPart) : that.encodedSchemeSpecificPart != null)
|
||||
return false;
|
||||
if (encodedAuthority != null ? !encodedAuthority.equals(that.encodedAuthority) : that.encodedAuthority != null)
|
||||
return false;
|
||||
if (userInfo != null ? !userInfo.equals(that.userInfo) : that.userInfo != null) return false;
|
||||
if (encodedUserInfo != null ? !encodedUserInfo.equals(that.encodedUserInfo) : that.encodedUserInfo != null)
|
||||
return false;
|
||||
if (host != null ? !host.equals(that.host) : that.host != null) return false;
|
||||
if (path != null ? !path.equals(that.path) : that.path != null) return false;
|
||||
if (encodedPath != null ? !encodedPath.equals(that.encodedPath) : that.encodedPath != null) return false;
|
||||
if (encodedQuery != null ? !encodedQuery.equals(that.encodedQuery) : that.encodedQuery != null) return false;
|
||||
if (queryParams != null ? !queryParams.equals(that.queryParams) : that.queryParams != null) return false;
|
||||
if (query != null ? !query.equals(that.query) : that.query != null) return false;
|
||||
if (fragment != null ? !fragment.equals(that.fragment) : that.fragment != null) return false;
|
||||
return !(encodedFragment != null ? !encodedFragment.equals(that.encodedFragment) : that.encodedFragment != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = scheme != null ? scheme.hashCode() : 0;
|
||||
result = 31 * result + (encodedSchemeSpecificPart != null ? encodedSchemeSpecificPart.hashCode() : 0);
|
||||
result = 31 * result + (encodedAuthority != null ? encodedAuthority.hashCode() : 0);
|
||||
result = 31 * result + (userInfo != null ? userInfo.hashCode() : 0);
|
||||
result = 31 * result + (encodedUserInfo != null ? encodedUserInfo.hashCode() : 0);
|
||||
result = 31 * result + (host != null ? host.hashCode() : 0);
|
||||
result = 31 * result + port;
|
||||
result = 31 * result + (path != null ? path.hashCode() : 0);
|
||||
result = 31 * result + (encodedPath != null ? encodedPath.hashCode() : 0);
|
||||
result = 31 * result + (encodedQuery != null ? encodedQuery.hashCode() : 0);
|
||||
result = 31 * result + (queryParams != null ? queryParams.hashCode() : 0);
|
||||
result = 31 * result + (query != null ? query.hashCode() : 0);
|
||||
result = 31 * result + (encode ? 1 : 0);
|
||||
result = 31 * result + (fragment != null ? fragment.hashCode() : 0);
|
||||
result = 31 * result + (encodedFragment != null ? encodedFragment.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class BasicNameValuePair implements Cloneable, Serializable {
|
||||
private static final long serialVersionUID = -6437800749411518984L;
|
||||
|
||||
private final String name;
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Default Constructor taking a name and a value. The value may be null.
|
||||
*
|
||||
* @param name The name.
|
||||
* @param value The value.
|
||||
*/
|
||||
public BasicNameValuePair(final String name, final String value) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// don't call complex default formatting for a simple toString
|
||||
|
||||
if (this.value == null) {
|
||||
return name;
|
||||
}
|
||||
final int len = this.name.length() + 1 + this.value.length();
|
||||
final StringBuilder buffer = new StringBuilder(len);
|
||||
buffer.append(this.name);
|
||||
buffer.append("=");
|
||||
buffer.append(this.value);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (object == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (object instanceof BasicNameValuePair) {
|
||||
final BasicNameValuePair that = (BasicNameValuePair) object;
|
||||
return this.name.equals(that.name)
|
||||
&& this.value.equals(that.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 133 * this.name.hashCode() * this.value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -19,23 +19,26 @@
|
|||
package org.jasig.cas.client.util;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
/**
|
||||
* Common utilities for easily parsing XML without duplicating logic.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class XmlUtils {
|
||||
|
|
@ -45,6 +48,36 @@ public final class XmlUtils {
|
|||
*/
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(XmlUtils.class);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new namespace-aware DOM document object by parsing the given XML.
|
||||
*
|
||||
* @param xml XML content.
|
||||
*
|
||||
* @return DOM document.
|
||||
*/
|
||||
public static Document newDocument(final String xml) {
|
||||
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
final Map<String, Boolean> features = new HashMap<String, Boolean>();
|
||||
features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
features.put("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
for (final Map.Entry<String, Boolean> entry : features.entrySet()) {
|
||||
try {
|
||||
factory.setFeature(entry.getKey(), entry.getValue());
|
||||
} catch (final ParserConfigurationException e) {
|
||||
LOGGER.warn("Failed setting XML feature {}: {}", entry.getKey(), e);
|
||||
}
|
||||
}
|
||||
factory.setExpandEntityReferences(false);
|
||||
factory.setNamespaceAware(true);
|
||||
try {
|
||||
return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("XML parsing error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of an XML reader from the XMLReaderFactory.
|
||||
*
|
||||
|
|
@ -52,16 +85,20 @@ public final class XmlUtils {
|
|||
*/
|
||||
public static XMLReader getXmlReader() {
|
||||
try {
|
||||
final XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
|
||||
reader.setFeature("http://xml.org/sax/features/namespaces", true);
|
||||
reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
|
||||
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
return reader;
|
||||
final SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
return factory.newSAXParser().getXMLReader();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("Unable to create XMLReader", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the text for a group of elements. Each text element is an entry
|
||||
* in a list.
|
||||
|
|
@ -81,13 +118,15 @@ public final class XmlUtils {
|
|||
|
||||
private StringBuilder buffer = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void startElement(final String uri, final String localName, final String qName,
|
||||
final Attributes attributes) throws SAXException {
|
||||
final Attributes attributes) throws SAXException {
|
||||
if (localName.equals(element)) {
|
||||
this.foundElement = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
|
||||
if (localName.equals(element)) {
|
||||
this.foundElement = false;
|
||||
|
|
@ -96,7 +135,8 @@ public final class XmlUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
@Override
|
||||
public void characters(final char[] ch, final int start, final int length) throws SAXException {
|
||||
if (this.foundElement) {
|
||||
this.buffer.append(ch, start, length);
|
||||
}
|
||||
|
|
@ -132,20 +172,23 @@ public final class XmlUtils {
|
|||
|
||||
private boolean foundElement = false;
|
||||
|
||||
@Override
|
||||
public void startElement(final String uri, final String localName, final String qName,
|
||||
final Attributes attributes) throws SAXException {
|
||||
final Attributes attributes) throws SAXException {
|
||||
if (localName.equals(element)) {
|
||||
this.foundElement = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
|
||||
if (localName.equals(element)) {
|
||||
this.foundElement = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
@Override
|
||||
public void characters(final char[] ch, final int start, final int length) throws SAXException {
|
||||
if (this.foundElement) {
|
||||
builder.append(ch, start, length);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<!--
|
||||
|
||||
Licensed to Jasig under one or more contributor license
|
||||
Licensed to Apereo under one or more contributor license
|
||||
agreements. See the NOTICE file distributed with this work
|
||||
for additional information regarding copyright ownership.
|
||||
Jasig licenses this file to you under the Apache License,
|
||||
Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -34,13 +34,10 @@ public abstract class AbstractCasProtocolUrlBasedTicketValidator extends Abstrac
|
|||
super(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
protected final void setDisableXmlSchemaValidation(final boolean disable) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the response from the server by opening a connection and merely reading the response.
|
||||
*/
|
||||
@Override
|
||||
protected final String retrieveResponseFromServer(final URL validationUrl, final String ticket) {
|
||||
return CommonUtils.getResponseFromServer(validationUrl, getURLConnectionFactory(), getEncoding());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -25,6 +25,9 @@ import javax.net.ssl.HostnameVerifier;
|
|||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.ReflectUtils;
|
||||
|
|
@ -68,6 +71,10 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
*/
|
||||
private boolean useSession = true;
|
||||
|
||||
protected AbstractTicketValidationFilter(final Protocol protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to return the appropriate validator.
|
||||
*
|
||||
|
|
@ -81,12 +88,11 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
/**
|
||||
* Gets the ssl config to use for HTTPS connections
|
||||
* if one is configured for this filter.
|
||||
* @param filterConfig Servlet filter configuration.
|
||||
* @return Properties that can contains key/trust info for Client Side Certificates
|
||||
*/
|
||||
protected Properties getSSLConfig(final FilterConfig filterConfig) {
|
||||
protected Properties getSSLConfig() {
|
||||
final Properties properties = new Properties();
|
||||
final String fileName = getPropertyFromInitParams(filterConfig, "sslConfigFile", null);
|
||||
final String fileName = getString(ConfigurationKeys.SSL_CONFIG_FILE);
|
||||
|
||||
if (fileName != null) {
|
||||
FileInputStream fis = null;
|
||||
|
|
@ -106,14 +112,11 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
/**
|
||||
* Gets the configured {@link HostnameVerifier} to use for HTTPS connections
|
||||
* if one is configured for this filter.
|
||||
* @param filterConfig Servlet filter configuration.
|
||||
* @return Instance of specified host name verifier or null if none specified.
|
||||
*/
|
||||
protected HostnameVerifier getHostnameVerifier(final FilterConfig filterConfig) {
|
||||
final String className = getPropertyFromInitParams(filterConfig, "hostnameVerifier", null);
|
||||
logger.trace("Using hostnameVerifier parameter: {}", className);
|
||||
final String config = getPropertyFromInitParams(filterConfig, "hostnameVerifierConfig", null);
|
||||
logger.trace("Using hostnameVerifierConfig parameter: {}", config);
|
||||
protected HostnameVerifier getHostnameVerifier() {
|
||||
final Class<? extends HostnameVerifier> className = getClass(ConfigurationKeys.HOSTNAME_VERIFIER);
|
||||
final String config = getString(ConfigurationKeys.HOSTNAME_VERIFIER_CONFIG);
|
||||
if (className != null) {
|
||||
if (config != null) {
|
||||
return ReflectUtils.newInstance(className, config);
|
||||
|
|
@ -124,15 +127,11 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
|
||||
setExceptionOnValidationFailure(parseBoolean(getPropertyFromInitParams(filterConfig,
|
||||
"exceptionOnValidationFailure", "false")));
|
||||
logger.trace("Setting exceptionOnValidationFailure parameter: {}", this.exceptionOnValidationFailure);
|
||||
setRedirectAfterValidation(parseBoolean(getPropertyFromInitParams(filterConfig, "redirectAfterValidation",
|
||||
"true")));
|
||||
logger.trace("Setting redirectAfterValidation parameter: {}", this.redirectAfterValidation);
|
||||
setUseSession(parseBoolean(getPropertyFromInitParams(filterConfig, "useSession", "true")));
|
||||
logger.trace("Setting useSession parameter: {}", this.useSession);
|
||||
setExceptionOnValidationFailure(getBoolean(ConfigurationKeys.EXCEPTION_ON_VALIDATION_FAILURE));
|
||||
setRedirectAfterValidation(getBoolean(ConfigurationKeys.REDIRECT_AFTER_VALIDATION));
|
||||
setUseSession(getBoolean(ConfigurationKeys.USE_SESSION));
|
||||
|
||||
if (!this.useSession && this.redirectAfterValidation) {
|
||||
logger.warn("redirectAfterValidation parameter may not be true when useSession parameter is false. Resetting it to false in order to prevent infinite redirects.");
|
||||
|
|
@ -143,6 +142,7 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
super.initInternal(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
CommonUtils.assertNotNull(this.ticketValidator, "ticketValidator cannot be null.");
|
||||
|
|
@ -188,8 +188,9 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
// nothing to do here.
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
|
||||
if (!preFilter(servletRequest, servletResponse, filterChain)) {
|
||||
return;
|
||||
|
|
@ -254,4 +255,4 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
public final void setUseSession(final boolean useSession) {
|
||||
this.useSession = useSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -71,8 +71,8 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
|
|||
* @param casServerUrlPrefix the location of the CAS server.
|
||||
*/
|
||||
protected AbstractUrlBasedTicketValidator(final String casServerUrlPrefix) {
|
||||
this.casServerUrlPrefix = casServerUrlPrefix;
|
||||
CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
|
||||
CommonUtils.assertNotNull(casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
|
||||
this.casServerUrlPrefix = CommonUtils.addTrailingSlash(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -90,13 +90,6 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
|
|||
*/
|
||||
protected abstract String getUrlSuffix();
|
||||
|
||||
/**
|
||||
* Disable XML Schema validation. Note, setting this to true may not be reversable. Defaults to false. Setting it to false
|
||||
* after setting it to true may not have any affect.
|
||||
*
|
||||
* @param disabled whether to disable or not.
|
||||
*/
|
||||
protected abstract void setDisableXmlSchemaValidation(boolean disabled);
|
||||
|
||||
/**
|
||||
* Constructs the URL to send the validation request to.
|
||||
|
|
@ -131,12 +124,9 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
|
|||
int i = 0;
|
||||
|
||||
buffer.append(this.casServerUrlPrefix);
|
||||
if (!this.casServerUrlPrefix.endsWith("/")) {
|
||||
buffer.append("/");
|
||||
}
|
||||
buffer.append(suffix);
|
||||
|
||||
for (Map.Entry<String, String> entry : urlParameters.entrySet()) {
|
||||
for (final Map.Entry<String, String> entry : urlParameters.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
final String value = entry.getValue();
|
||||
|
||||
|
|
@ -191,6 +181,7 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
|
|||
|
||||
protected abstract String retrieveResponseFromServer(URL validationUrl, String ticket);
|
||||
|
||||
@Override
|
||||
public final Assertion validate(final String ticket, final String service) throws TicketValidationException {
|
||||
final String validationUrl = constructValidationUrl(ticket, service);
|
||||
logger.debug("Constructing validation url: {}", validationUrl);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -101,32 +101,39 @@ public final class AssertionImpl implements Assertion {
|
|||
CommonUtils.assertNotNull(this.attributes, "attributes cannot be null.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getAuthenticationDate() {
|
||||
return this.authenticationDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getValidFromDate() {
|
||||
return this.validFromDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getValidUntilDate() {
|
||||
return this.validUntilDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributePrincipal getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
if (this.validFromDate == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Date now = new Date();
|
||||
return this.validFromDate.before(now) && (this.validUntilDate == null || this.validUntilDate.after(now));
|
||||
return (this.validFromDate.before(now) || this.validFromDate.equals(now))
|
||||
&& (this.validUntilDate == null || this.validUntilDate.after(now) || this.validUntilDate.equals(now));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -19,29 +19,37 @@
|
|||
package org.jasig.cas.client.validation;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
|
||||
import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
|
||||
|
||||
/**
|
||||
* Implementation of AbstractTicketValidatorFilter that instanciates a Cas10TicketValidator.
|
||||
* Implementation of AbstractTicketValidatorFilter that creates a Cas10TicketValidator.
|
||||
* <p>Deployers can provide the "casServerPrefix" and the "renew" attributes via the standard context or filter init
|
||||
* parameters.
|
||||
*
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision$ $Date$
|
||||
* @since 3.1
|
||||
*/
|
||||
public class Cas10TicketValidationFilter extends AbstractTicketValidationFilter {
|
||||
|
||||
protected final TicketValidator getTicketValidator(final FilterConfig filterConfig) {
|
||||
final String casServerUrlPrefix = getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null);
|
||||
final Cas10TicketValidator validator = new Cas10TicketValidator(casServerUrlPrefix);
|
||||
validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
|
||||
public Cas10TicketValidationFilter() {
|
||||
super(Protocol.CAS1);
|
||||
}
|
||||
|
||||
final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig),
|
||||
getSSLConfig(filterConfig));
|
||||
@Override
|
||||
protected final TicketValidator getTicketValidator(final FilterConfig filterConfig) {
|
||||
final String casServerUrlPrefix = getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX);
|
||||
final Cas10TicketValidator validator = new Cas10TicketValidator(casServerUrlPrefix);
|
||||
validator.setRenew(getBoolean(ConfigurationKeys.RENEW));
|
||||
|
||||
final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(),
|
||||
getSSLConfig());
|
||||
validator.setURLConnectionFactory(factory);
|
||||
validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null));
|
||||
validator.setEncoding(getString(ConfigurationKeys.ENCODING));
|
||||
|
||||
return validator;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -35,10 +35,12 @@ public final class Cas10TicketValidator extends AbstractCasProtocolUrlBasedTicke
|
|||
super(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getUrlSuffix() {
|
||||
return "validate";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Assertion parseResponseFromServer(final String response) throws TicketValidationException {
|
||||
if (!response.startsWith("yes")) {
|
||||
throw new TicketValidationException("CAS Server could not validate ticket.");
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -19,20 +19,27 @@
|
|||
package org.jasig.cas.client.validation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
import org.jasig.cas.client.configuration.ConfigurationKeys;
|
||||
import org.jasig.cas.client.proxy.*;
|
||||
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
|
||||
import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.PrivateKeyUtils;
|
||||
import org.jasig.cas.client.util.ReflectUtils;
|
||||
|
||||
import static org.jasig.cas.client.configuration.ConfigurationKeys.*;
|
||||
|
||||
/**
|
||||
* Creates either a CAS20ProxyTicketValidator or a CAS20ServiceTicketValidator depending on whether any of the
|
||||
* proxy parameters are set.
|
||||
* <p>
|
||||
* <p/>
|
||||
* This filter can also pass additional parameters to the ticket validator. Any init parameter not included in the
|
||||
* reserved list {@link org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter#RESERVED_INIT_PARAMS}.
|
||||
*
|
||||
|
|
@ -40,20 +47,20 @@ import org.jasig.cas.client.util.ReflectUtils;
|
|||
* @author Brad Cupit (brad [at] lsu {dot} edu)
|
||||
* @version $Revision$ $Date$
|
||||
* @since 3.1
|
||||
*
|
||||
*/
|
||||
public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketValidationFilter {
|
||||
|
||||
private static final String[] RESERVED_INIT_PARAMS = new String[] { "proxyGrantingTicketStorageClass",
|
||||
"proxyReceptorUrl", "acceptAnyProxy", "allowedProxyChains", "casServerUrlPrefix", "proxyCallbackUrl",
|
||||
"renew", "exceptionOnValidationFailure", "redirectAfterValidation", "useSession", "serverName", "service",
|
||||
"artifactParameterName", "serviceParameterName", "encodeServiceUrl", "millisBetweenCleanUps",
|
||||
"hostnameVerifier", "encoding", "config", "ticketValidatorClass" };
|
||||
|
||||
private static final int DEFAULT_MILLIS_BETWEEN_CLEANUPS = 60 * 1000;
|
||||
private static final String[] RESERVED_INIT_PARAMS = new String[]{ARTIFACT_PARAMETER_NAME.getName(), SERVER_NAME.getName(), SERVICE.getName(), RENEW.getName(), LOGOUT_PARAMETER_NAME.getName(),
|
||||
ARTIFACT_PARAMETER_OVER_POST.getName(), EAGERLY_CREATE_SESSIONS.getName(), ENCODE_SERVICE_URL.getName(), SSL_CONFIG_FILE.getName(), ROLE_ATTRIBUTE.getName(), IGNORE_CASE.getName(),
|
||||
CAS_SERVER_LOGIN_URL.getName(), GATEWAY.getName(), AUTHENTICATION_REDIRECT_STRATEGY_CLASS.getName(), GATEWAY_STORAGE_CLASS.getName(), CAS_SERVER_URL_PREFIX.getName(), ENCODING.getName(),
|
||||
TOLERANCE.getName(), IGNORE_PATTERN.getName(), IGNORE_URL_PATTERN_TYPE.getName(), HOSTNAME_VERIFIER.getName(), HOSTNAME_VERIFIER_CONFIG.getName(),
|
||||
EXCEPTION_ON_VALIDATION_FAILURE.getName(), REDIRECT_AFTER_VALIDATION.getName(), USE_SESSION.getName(), SECRET_KEY.getName(), CIPHER_ALGORITHM.getName(), PROXY_RECEPTOR_URL.getName(),
|
||||
PROXY_GRANTING_TICKET_STORAGE_CLASS.getName(), MILLIS_BETWEEN_CLEAN_UPS.getName(), ACCEPT_ANY_PROXY.getName(), ALLOWED_PROXY_CHAINS.getName(), TICKET_VALIDATOR_CLASS.getName(),
|
||||
PROXY_CALLBACK_URL.getName(), RELAY_STATE_PARAMETER_NAME.getName(), METHOD.getName(), PRIVATE_KEY_PATH.getName(), PRIVATE_KEY_ALGORITHM.getName()
|
||||
};
|
||||
|
||||
/**
|
||||
* The URL to send to the CAS server as the URL that will process proxying requests on the CAS client.
|
||||
* The URL to send to the CAS server as the URL that will process proxying requests on the CAS client.
|
||||
*/
|
||||
private String proxyReceptorUrl;
|
||||
|
||||
|
|
@ -63,25 +70,40 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
|
|||
|
||||
private int millisBetweenCleanUps;
|
||||
|
||||
protected Class<? extends Cas20ServiceTicketValidator> defaultServiceTicketValidatorClass;
|
||||
|
||||
protected Class<? extends Cas20ProxyTicketValidator> defaultProxyTicketValidatorClass;
|
||||
|
||||
private PrivateKey privateKey;
|
||||
|
||||
/**
|
||||
* Storage location of ProxyGrantingTickets and Proxy Ticket IOUs.
|
||||
*/
|
||||
private ProxyGrantingTicketStorage proxyGrantingTicketStorage = new ProxyGrantingTicketStorageImpl();
|
||||
|
||||
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
|
||||
setProxyReceptorUrl(getPropertyFromInitParams(filterConfig, "proxyReceptorUrl", null));
|
||||
public Cas20ProxyReceivingTicketValidationFilter() {
|
||||
this(Protocol.CAS2);
|
||||
this.defaultServiceTicketValidatorClass = Cas20ServiceTicketValidator.class;
|
||||
this.defaultProxyTicketValidatorClass = Cas20ProxyTicketValidator.class;
|
||||
}
|
||||
|
||||
final String proxyGrantingTicketStorageClass = getPropertyFromInitParams(filterConfig,
|
||||
"proxyGrantingTicketStorageClass", null);
|
||||
protected Cas20ProxyReceivingTicketValidationFilter(final Protocol protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
|
||||
setProxyReceptorUrl(getString(ConfigurationKeys.PROXY_RECEPTOR_URL));
|
||||
|
||||
final Class<? extends ProxyGrantingTicketStorage> proxyGrantingTicketStorageClass = getClass(ConfigurationKeys.PROXY_GRANTING_TICKET_STORAGE_CLASS);
|
||||
|
||||
if (proxyGrantingTicketStorageClass != null) {
|
||||
this.proxyGrantingTicketStorage = ReflectUtils.newInstance(proxyGrantingTicketStorageClass);
|
||||
|
||||
if (this.proxyGrantingTicketStorage instanceof AbstractEncryptedProxyGrantingTicketStorageImpl) {
|
||||
final AbstractEncryptedProxyGrantingTicketStorageImpl p = (AbstractEncryptedProxyGrantingTicketStorageImpl) this.proxyGrantingTicketStorage;
|
||||
final String cipherAlgorithm = getPropertyFromInitParams(filterConfig, "cipherAlgorithm",
|
||||
AbstractEncryptedProxyGrantingTicketStorageImpl.DEFAULT_ENCRYPTION_ALGORITHM);
|
||||
final String secretKey = getPropertyFromInitParams(filterConfig, "secretKey", null);
|
||||
final String cipherAlgorithm = getString(ConfigurationKeys.CIPHER_ALGORITHM);
|
||||
final String secretKey = getString(ConfigurationKeys.SECRET_KEY);
|
||||
|
||||
p.setCipherAlgorithm(cipherAlgorithm);
|
||||
|
||||
|
|
@ -95,12 +117,13 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
|
|||
}
|
||||
}
|
||||
|
||||
logger.trace("Setting proxyReceptorUrl parameter: {}", this.proxyReceptorUrl);
|
||||
this.millisBetweenCleanUps = Integer.parseInt(getPropertyFromInitParams(filterConfig, "millisBetweenCleanUps",
|
||||
Integer.toString(DEFAULT_MILLIS_BETWEEN_CLEANUPS)));
|
||||
this.millisBetweenCleanUps = getInt(ConfigurationKeys.MILLIS_BETWEEN_CLEAN_UPS);
|
||||
|
||||
this.privateKey = buildPrivateKey(getString(PRIVATE_KEY_PATH), getString(PRIVATE_KEY_ALGORITHM));
|
||||
super.initInternal(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
CommonUtils.assertNotNull(this.proxyGrantingTicketStorage, "proxyGrantingTicketStorage cannot be null.");
|
||||
|
|
@ -115,13 +138,20 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
|
|||
this.timer.schedule(this.timerTask, this.millisBetweenCleanUps, this.millisBetweenCleanUps);
|
||||
}
|
||||
|
||||
private <T> T createNewTicketValidator(final String ticketValidatorClass, final String casServerUrlPrefix,
|
||||
final Class<T> clazz) {
|
||||
if (CommonUtils.isBlank(ticketValidatorClass)) {
|
||||
private <T> T createNewTicketValidator(final Class<? extends Cas20ServiceTicketValidator> ticketValidatorClass, final String casServerUrlPrefix,
|
||||
final Class<T> clazz) {
|
||||
if (ticketValidatorClass == null) {
|
||||
return ReflectUtils.newInstance(clazz, casServerUrlPrefix);
|
||||
}
|
||||
|
||||
return ReflectUtils.newInstance(ticketValidatorClass, casServerUrlPrefix);
|
||||
return (T) ReflectUtils.newInstance(ticketValidatorClass, casServerUrlPrefix);
|
||||
}
|
||||
|
||||
public static PrivateKey buildPrivateKey(final String keyPath, final String keyAlgorithm) {
|
||||
if (keyPath != null) {
|
||||
return PrivateKeyUtils.createKey(keyPath, keyAlgorithm);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -130,39 +160,39 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
|
|||
* @param filterConfig the Filter Configuration object.
|
||||
* @return a fully constructed TicketValidator.
|
||||
*/
|
||||
@Override
|
||||
protected final TicketValidator getTicketValidator(final FilterConfig filterConfig) {
|
||||
final String allowAnyProxy = getPropertyFromInitParams(filterConfig, "acceptAnyProxy", null);
|
||||
final String allowedProxyChains = getPropertyFromInitParams(filterConfig, "allowedProxyChains", null);
|
||||
final String casServerUrlPrefix = getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null);
|
||||
final String ticketValidatorClass = getPropertyFromInitParams(filterConfig, "ticketValidatorClass", null);
|
||||
final boolean allowAnyProxy = getBoolean(ConfigurationKeys.ACCEPT_ANY_PROXY);
|
||||
final String allowedProxyChains = getString(ConfigurationKeys.ALLOWED_PROXY_CHAINS);
|
||||
final String casServerUrlPrefix = getString(ConfigurationKeys.CAS_SERVER_URL_PREFIX);
|
||||
final Class<? extends Cas20ServiceTicketValidator> ticketValidatorClass = getClass(ConfigurationKeys.TICKET_VALIDATOR_CLASS);
|
||||
final Cas20ServiceTicketValidator validator;
|
||||
|
||||
if (CommonUtils.isNotBlank(allowAnyProxy) || CommonUtils.isNotBlank(allowedProxyChains)) {
|
||||
if (allowAnyProxy || CommonUtils.isNotBlank(allowedProxyChains)) {
|
||||
final Cas20ProxyTicketValidator v = createNewTicketValidator(ticketValidatorClass, casServerUrlPrefix,
|
||||
Cas20ProxyTicketValidator.class);
|
||||
v.setAcceptAnyProxy(parseBoolean(allowAnyProxy));
|
||||
this.defaultProxyTicketValidatorClass);
|
||||
v.setAcceptAnyProxy(allowAnyProxy);
|
||||
v.setAllowedProxyChains(CommonUtils.createProxyList(allowedProxyChains));
|
||||
validator = v;
|
||||
} else {
|
||||
validator = createNewTicketValidator(ticketValidatorClass, casServerUrlPrefix,
|
||||
Cas20ServiceTicketValidator.class);
|
||||
this.defaultServiceTicketValidatorClass);
|
||||
}
|
||||
validator.setProxyCallbackUrl(getPropertyFromInitParams(filterConfig, "proxyCallbackUrl", null));
|
||||
validator.setProxyCallbackUrl(getString(ConfigurationKeys.PROXY_CALLBACK_URL));
|
||||
validator.setProxyGrantingTicketStorage(this.proxyGrantingTicketStorage);
|
||||
|
||||
final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig),
|
||||
getSSLConfig(filterConfig));
|
||||
final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(),
|
||||
getSSLConfig());
|
||||
validator.setURLConnectionFactory(factory);
|
||||
|
||||
validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getPropertyFromInitParams(filterConfig,
|
||||
"encoding", null), factory));
|
||||
validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
|
||||
validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null));
|
||||
validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getString(ConfigurationKeys.ENCODING), factory));
|
||||
validator.setRenew(getBoolean(ConfigurationKeys.RENEW));
|
||||
validator.setEncoding(getString(ConfigurationKeys.ENCODING));
|
||||
|
||||
final Map<String, String> additionalParameters = new HashMap<String, String>();
|
||||
final List<String> params = Arrays.asList(RESERVED_INIT_PARAMS);
|
||||
|
||||
for (final Enumeration<?> e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
|
||||
for (final Enumeration<?> e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
|
||||
final String s = (String) e.nextElement();
|
||||
|
||||
if (!params.contains(s)) {
|
||||
|
|
@ -170,10 +200,13 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
|
|||
}
|
||||
}
|
||||
|
||||
validator.setPrivateKey(this.privateKey);
|
||||
|
||||
validator.setCustomParameters(additionalParameters);
|
||||
return validator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
this.timer.cancel();
|
||||
|
|
@ -182,8 +215,9 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
|
|||
/**
|
||||
* This processes the ProxyReceptor request before the ticket validation code executes.
|
||||
*/
|
||||
@Override
|
||||
protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
final String requestUri = request.getRequestURI();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jasig.cas.client.validation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.jasig.cas.client.util.XmlUtils;
|
||||
|
||||
|
|
@ -45,16 +46,32 @@ public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
|
|||
return this.allowedProxyChains;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getUrlSuffix() {
|
||||
return "proxyValidate";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customParseResponse(final String response, final Assertion assertion)
|
||||
throws TicketValidationException {
|
||||
final List<String> proxies = XmlUtils.getTextForElements(response, "proxy");
|
||||
final List<String> proxies = parseProxiesFromResponse(response);
|
||||
|
||||
if (proxies == null) {
|
||||
throw new InvalidProxyChainTicketValidationException(
|
||||
"Invalid proxy chain: No proxy could be retrieved from response. "
|
||||
+ "This indicates a problem with CAS validation. Review logs/configuration to find the root cause."
|
||||
);
|
||||
}
|
||||
// this means there was nothing in the proxy chain, which is okay
|
||||
if ((this.allowEmptyProxyChain && proxies.isEmpty()) || this.acceptAnyProxy) {
|
||||
if (this.allowEmptyProxyChain && proxies.isEmpty()) {
|
||||
logger.debug("Found an empty proxy chain, permitted by client configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.acceptAnyProxy) {
|
||||
logger.debug("Client configuration accepts any proxy. "
|
||||
+ "It is generally dangerous to use a non-proxied CAS filter "
|
||||
+ "specially for protecting resources that require proxy access.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -63,9 +80,17 @@ public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
|
|||
return;
|
||||
}
|
||||
|
||||
logger.warn("Proxies received from the CAS validation response are {}. "
|
||||
+ "However, none are allowed by allowed proxy chain of the client which is {}",
|
||||
Arrays.toString(proxiedList), this.allowedProxyChains);
|
||||
|
||||
throw new InvalidProxyChainTicketValidationException("Invalid proxy chain: " + proxies.toString());
|
||||
}
|
||||
|
||||
protected List<String> parseProxiesFromResponse(final String response) {
|
||||
return XmlUtils.getTextForElements(response, "proxy");
|
||||
}
|
||||
|
||||
public final void setAcceptAnyProxy(final boolean acceptAnyProxy) {
|
||||
this.acceptAnyProxy = acceptAnyProxy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -19,9 +19,13 @@
|
|||
package org.jasig.cas.client.validation;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.*;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
|
||||
import org.jasig.cas.client.proxy.Cas20ProxyRetriever;
|
||||
|
|
@ -43,6 +47,9 @@ import org.xml.sax.helpers.DefaultHandler;
|
|||
*/
|
||||
public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTicketValidator {
|
||||
|
||||
public static final String PGT_ATTRIBUTE = "proxyGrantingTicket";
|
||||
private static final String PGTIOU_PREFIX = "PGTIOU-";
|
||||
|
||||
/** The CAS 2.0 protocol proxy callback url. */
|
||||
private String proxyCallbackUrl;
|
||||
|
||||
|
|
@ -52,12 +59,14 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
|
|||
/** Implementation of the proxy retriever. */
|
||||
private ProxyRetriever proxyRetriever;
|
||||
|
||||
/** Private key for decryption */
|
||||
private PrivateKey privateKey;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the CAS 2.0 Service Ticket Validator with the supplied
|
||||
* CAS server url prefix.
|
||||
*
|
||||
* @param casServerUrlPrefix the CAS Server URL prefix.
|
||||
* @param urlFactory URL connection factory to use when communicating with the server
|
||||
*/
|
||||
public Cas20ServiceTicketValidator(final String casServerUrlPrefix) {
|
||||
super(casServerUrlPrefix);
|
||||
|
|
@ -69,30 +78,26 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
|
|||
*
|
||||
* @param urlParameters the Map containing the existing parameters to send to the server.
|
||||
*/
|
||||
@Override
|
||||
protected final void populateUrlAttributeMap(final Map<String, String> urlParameters) {
|
||||
urlParameters.put("pgtUrl", this.proxyCallbackUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getUrlSuffix() {
|
||||
return "serviceValidate";
|
||||
}
|
||||
|
||||
protected final Assertion parseResponseFromServer(final String response) throws TicketValidationException {
|
||||
final String error = XmlUtils.getTextForElement(response, "authenticationFailure");
|
||||
@Override
|
||||
protected Assertion parseResponseFromServer(final String response) throws TicketValidationException {
|
||||
final String error = parseAuthenticationFailureFromResponse(response);
|
||||
|
||||
if (CommonUtils.isNotBlank(error)) {
|
||||
throw new TicketValidationException(error);
|
||||
}
|
||||
|
||||
final String principal = XmlUtils.getTextForElement(response, "user");
|
||||
final String proxyGrantingTicketIou = XmlUtils.getTextForElement(response, "proxyGrantingTicket");
|
||||
|
||||
final String proxyGrantingTicket;
|
||||
if (CommonUtils.isBlank(proxyGrantingTicketIou) || this.proxyGrantingTicketStorage == null) {
|
||||
proxyGrantingTicket = null;
|
||||
} else {
|
||||
proxyGrantingTicket = this.proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou);
|
||||
}
|
||||
final String principal = parsePrincipalFromResponse(response);
|
||||
final String proxyGrantingTicket = retrieveProxyGrantingTicket(response);
|
||||
|
||||
if (CommonUtils.isEmpty(principal)) {
|
||||
throw new TicketValidationException("No principal was found in the response from the CAS server.");
|
||||
|
|
@ -101,6 +106,7 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
|
|||
final Assertion assertion;
|
||||
final Map<String, Object> attributes = extractCustomAttributes(response);
|
||||
if (CommonUtils.isNotBlank(proxyGrantingTicket)) {
|
||||
attributes.remove(PGT_ATTRIBUTE);
|
||||
final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes,
|
||||
proxyGrantingTicket, this.proxyRetriever);
|
||||
assertion = new AssertionImpl(attributePrincipal);
|
||||
|
|
@ -113,6 +119,52 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
|
|||
return assertion;
|
||||
}
|
||||
|
||||
protected String retrieveProxyGrantingTicket(final String response) {
|
||||
final List<String> values = XmlUtils.getTextForElements(response, PGT_ATTRIBUTE);
|
||||
for (final String value : values) {
|
||||
if (value != null) {
|
||||
if (value.startsWith(PGTIOU_PREFIX)) {
|
||||
return retrieveProxyGrantingTicketFromStorage(value);
|
||||
} else {
|
||||
return retrieveProxyGrantingTicketViaEncryption(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String retrieveProxyGrantingTicketFromStorage(final String pgtIou) {
|
||||
if (this.proxyGrantingTicketStorage != null) {
|
||||
return this.proxyGrantingTicketStorage.retrieve(pgtIou);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String retrieveProxyGrantingTicketViaEncryption(final String encryptedPgt) {
|
||||
if (this.privateKey != null) {
|
||||
try {
|
||||
final Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
|
||||
final byte[] cred64 = new Base64().decode(encryptedPgt);
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
final byte[] cipherData = cipher.doFinal(cred64);
|
||||
final String pgt = new String(cipherData);
|
||||
logger.debug("Decrypted PGT: {}", pgt);
|
||||
return pgt;
|
||||
} catch (final Exception e) {
|
||||
logger.error("Unable to decrypt PGT", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String parsePrincipalFromResponse(final String response) {
|
||||
return XmlUtils.getTextForElement(response, "user");
|
||||
}
|
||||
|
||||
protected String parseAuthenticationFailureFromResponse(final String response) {
|
||||
return XmlUtils.getTextForElement(response, "authenticationFailure");
|
||||
}
|
||||
|
||||
/**
|
||||
* Default attribute parsing of attributes that look like the following:
|
||||
* <cas:attributes>
|
||||
|
|
@ -246,4 +298,12 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
|
|||
return this.attributes;
|
||||
}
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKey(final PrivateKey privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation;
|
||||
|
||||
import org.jasig.cas.client.Protocol;
|
||||
|
||||
/**
|
||||
* Creates either a Cas30ProxyTicketValidator or a Cas30ServiceTicketValidator depending on whether any of the
|
||||
* proxy parameters are set.
|
||||
* <p/>
|
||||
* This filter can also pass additional parameters to the ticket validator. Any init parameter not included in the
|
||||
* reserved list {@link org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter#RESERVED_INIT_PARAMS}.
|
||||
*
|
||||
* @author Jerome Leleu
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public class Cas30ProxyReceivingTicketValidationFilter extends Cas20ProxyReceivingTicketValidationFilter {
|
||||
|
||||
public Cas30ProxyReceivingTicketValidationFilter() {
|
||||
super(Protocol.CAS3);
|
||||
this.defaultServiceTicketValidatorClass = Cas30ServiceTicketValidator.class;
|
||||
this.defaultProxyTicketValidatorClass = Cas30ProxyTicketValidator.class;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation;
|
||||
|
||||
/**
|
||||
* Service and proxy tickets validation service for the CAS protocol v3.
|
||||
*
|
||||
* @author Jerome Leleu
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public class Cas30ProxyTicketValidator extends Cas20ProxyTicketValidator {
|
||||
|
||||
public Cas30ProxyTicketValidator(final String casServerUrlPrefix) {
|
||||
super(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getUrlSuffix() {
|
||||
return "p3/proxyValidate";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation;
|
||||
|
||||
import org.jasig.cas.client.util.XmlUtils;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Service tickets validation service for the CAS protocol v3.
|
||||
*
|
||||
* @author Jerome Leleu
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public class Cas30ServiceTicketValidator extends Cas20ServiceTicketValidator {
|
||||
|
||||
public Cas30ServiceTicketValidator(final String casServerUrlPrefix) {
|
||||
super(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getUrlSuffix() {
|
||||
return "p3/serviceValidate";
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom attribute extractor that will account for inlined CAS attributes. Useful when CAS is acting as
|
||||
* as SAML 2 IdP and returns SAML attributes with names that contains namespaces.
|
||||
*
|
||||
* @param xml the XML to parse.
|
||||
* @return - Map of attributes
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> extractCustomAttributes(final String xml) {
|
||||
final Document document = XmlUtils.newDocument(xml);
|
||||
|
||||
// Check if attributes are inlined. If not return default super method results
|
||||
final NodeList attributeList = document.getElementsByTagName("cas:attribute");
|
||||
if (attributeList.getLength() == 0) {
|
||||
return super.extractCustomAttributes(xml);
|
||||
}
|
||||
|
||||
final HashMap<String, Object> attributes = new HashMap<String, Object>();
|
||||
|
||||
for (int i = 0; i < attributeList.getLength(); i++) {
|
||||
final Node casAttributeNode = attributeList.item(i);
|
||||
final NamedNodeMap nodeAttributes = casAttributeNode.getAttributes();
|
||||
final String name = nodeAttributes.getNamedItem("name").getNodeValue();
|
||||
final String value = nodeAttributes.getNamedItem("value").getTextContent();
|
||||
final Object mapValue = attributes.get(name);
|
||||
if (mapValue != null) {
|
||||
if (mapValue instanceof List) {
|
||||
((List) mapValue).add(value);
|
||||
} else {
|
||||
final LinkedList<Object> list = new LinkedList<Object>();
|
||||
list.add(mapValue);
|
||||
list.add(value);
|
||||
attributes.put(name, list);
|
||||
}
|
||||
} else {
|
||||
attributes.put(name, value);
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -19,9 +19,13 @@
|
|||
package org.jasig.cas.client.validation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.jasig.cas.client.authentication.ExactUrlPatternMatcherStrategy;
|
||||
import org.jasig.cas.client.authentication.RegexUrlPatternMatcherStrategy;
|
||||
import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Holding class for the proxy list to make Spring configuration easier.
|
||||
|
|
@ -32,24 +36,62 @@ import org.jasig.cas.client.util.CommonUtils;
|
|||
*/
|
||||
public final class ProxyList {
|
||||
|
||||
private final List<String[]> proxyChains;
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final List<List<UrlPatternMatcherStrategy>> proxyChains;
|
||||
|
||||
public ProxyList(final List<String[]> proxyChains) {
|
||||
CommonUtils.assertNotNull(proxyChains, "List of proxy chains cannot be null.");
|
||||
this.proxyChains = proxyChains;
|
||||
|
||||
this.proxyChains = new ArrayList<List<UrlPatternMatcherStrategy>>();
|
||||
|
||||
for (final String[] list : proxyChains) {
|
||||
final List<UrlPatternMatcherStrategy> chain = new ArrayList<UrlPatternMatcherStrategy>();
|
||||
|
||||
for (final String item : list) {
|
||||
if (item.startsWith("^")) {
|
||||
chain.add(new RegexUrlPatternMatcherStrategy(item));
|
||||
} else {
|
||||
chain.add(new ExactUrlPatternMatcherStrategy(item));
|
||||
}
|
||||
}
|
||||
|
||||
this.proxyChains.add(chain);
|
||||
}
|
||||
}
|
||||
|
||||
public ProxyList() {
|
||||
this(new ArrayList<String[]>());
|
||||
}
|
||||
|
||||
public boolean contains(String[] proxiedList) {
|
||||
for (final String[] list : this.proxyChains) {
|
||||
if (Arrays.equals(proxiedList, list)) {
|
||||
return true;
|
||||
public boolean contains(final String[] proxiedList) {
|
||||
StringBuilder loggingOutput;
|
||||
|
||||
for (final List<UrlPatternMatcherStrategy> proxyChain : this.proxyChains) {
|
||||
loggingOutput = new StringBuilder();
|
||||
|
||||
if (proxyChain.size() == proxiedList.length) {
|
||||
for (int linkIndex = 0; linkIndex < proxyChain.size(); linkIndex++) {
|
||||
final String linkToTest = proxiedList[linkIndex];
|
||||
loggingOutput.append(linkToTest);
|
||||
|
||||
if (proxyChain.get(linkIndex).matches(linkToTest)) {
|
||||
//If we are at the last link, we found a good proxyChain.
|
||||
if (linkIndex == proxyChain.size() - 1) {
|
||||
logger.info("Proxy chain matched: {}", loggingOutput.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.warn("Proxy chain did not match at {}. Skipping to next allowedProxyChain", loggingOutput.toString());
|
||||
break;
|
||||
}
|
||||
loggingOutput.append("->");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn("No proxy chain matched the allowedProxyChains list.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
@ -36,6 +36,7 @@ import org.jasig.cas.client.util.CommonUtils;
|
|||
*/
|
||||
public final class ProxyListEditor extends PropertyEditorSupport {
|
||||
|
||||
@Override
|
||||
public void setAsText(final String text) throws IllegalArgumentException {
|
||||
final BufferedReader reader = new BufferedReader(new StringReader(text));
|
||||
final List<String[]> proxyChains = new ArrayList<String[]>();
|
||||
|
|
|
|||
|
|
@ -1,288 +0,0 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.Interval;
|
||||
import org.opensaml.Configuration;
|
||||
import org.opensaml.DefaultBootstrap;
|
||||
import org.opensaml.common.IdentifierGenerator;
|
||||
import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
|
||||
import org.opensaml.saml1.core.*;
|
||||
import org.opensaml.ws.soap.soap11.Envelope;
|
||||
import org.opensaml.xml.ConfigurationException;
|
||||
import org.opensaml.xml.io.Unmarshaller;
|
||||
import org.opensaml.xml.io.UnmarshallerFactory;
|
||||
import org.opensaml.xml.io.UnmarshallingException;
|
||||
import org.opensaml.xml.parse.BasicParserPool;
|
||||
import org.opensaml.xml.parse.XMLParserException;
|
||||
import org.opensaml.xml.schema.XSAny;
|
||||
import org.opensaml.xml.schema.XSString;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* TicketValidator that can understand validating a SAML artifact. This includes the SOAP request/response.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @since 3.1
|
||||
*/
|
||||
public final class Saml11TicketValidator extends AbstractUrlBasedTicketValidator {
|
||||
|
||||
static {
|
||||
try {
|
||||
// we really only need to do this once, so this is why its here.
|
||||
DefaultBootstrap.bootstrap();
|
||||
} catch (final ConfigurationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Time tolerance to allow for time drifting. */
|
||||
private long tolerance = 1000L;
|
||||
|
||||
private final BasicParserPool basicParserPool;
|
||||
|
||||
private final IdentifierGenerator identifierGenerator;
|
||||
|
||||
public Saml11TicketValidator(final String casServerUrlPrefix) {
|
||||
super(casServerUrlPrefix);
|
||||
this.basicParserPool = new BasicParserPool();
|
||||
this.basicParserPool.setNamespaceAware(true);
|
||||
|
||||
try {
|
||||
this.identifierGenerator = new SecureRandomIdentifierGenerator();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getUrlSuffix() {
|
||||
return "samlValidate";
|
||||
}
|
||||
|
||||
protected void populateUrlAttributeMap(final Map<String, String> urlParameters) {
|
||||
final String service = urlParameters.get("service");
|
||||
urlParameters.remove("service");
|
||||
urlParameters.remove("ticket");
|
||||
urlParameters.put("TARGET", service);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDisableXmlSchemaValidation(final boolean disabled) {
|
||||
if (disabled) {
|
||||
this.basicParserPool.setSchema(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] getBytes(final String text) {
|
||||
try {
|
||||
return CommonUtils.isNotBlank(getEncoding()) ? text.getBytes(getEncoding()) : text.getBytes();
|
||||
} catch (final Exception e) {
|
||||
return text.getBytes();
|
||||
}
|
||||
}
|
||||
|
||||
protected Assertion parseResponseFromServer(final String response) throws TicketValidationException {
|
||||
try {
|
||||
|
||||
final Document responseDocument = this.basicParserPool.parse(new ByteArrayInputStream(getBytes(response)));
|
||||
final Element responseRoot = responseDocument.getDocumentElement();
|
||||
final UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
|
||||
final Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(responseRoot);
|
||||
final Envelope envelope = (Envelope) unmarshaller.unmarshall(responseRoot);
|
||||
final Response samlResponse = (Response) envelope.getBody().getOrderedChildren().get(0);
|
||||
|
||||
final List<org.opensaml.saml1.core.Assertion> assertions = samlResponse.getAssertions();
|
||||
if (assertions.isEmpty()) {
|
||||
throw new TicketValidationException("No assertions found.");
|
||||
}
|
||||
|
||||
for (final org.opensaml.saml1.core.Assertion assertion : assertions) {
|
||||
|
||||
if (!isValidAssertion(assertion)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final AuthenticationStatement authenticationStatement = getSAMLAuthenticationStatement(assertion);
|
||||
|
||||
if (authenticationStatement == null) {
|
||||
throw new TicketValidationException("No AuthentiationStatement found in SAML Assertion.");
|
||||
}
|
||||
final Subject subject = authenticationStatement.getSubject();
|
||||
|
||||
if (subject == null) {
|
||||
throw new TicketValidationException("No Subject found in SAML Assertion.");
|
||||
}
|
||||
|
||||
final List<Attribute> attributes = getAttributesFor(assertion, subject);
|
||||
final Map<String, Object> personAttributes = new HashMap<String, Object>();
|
||||
for (final Attribute samlAttribute : attributes) {
|
||||
final List<?> values = getValuesFrom(samlAttribute);
|
||||
|
||||
personAttributes.put(samlAttribute.getAttributeName(), values.size() == 1 ? values.get(0) : values);
|
||||
}
|
||||
|
||||
final AttributePrincipal principal = new AttributePrincipalImpl(subject.getNameIdentifier()
|
||||
.getNameIdentifier(), personAttributes);
|
||||
|
||||
final Map<String, Object> authenticationAttributes = new HashMap<String, Object>();
|
||||
authenticationAttributes.put("samlAuthenticationStatement::authMethod",
|
||||
authenticationStatement.getAuthenticationMethod());
|
||||
|
||||
final DateTime notBefore = assertion.getConditions().getNotBefore();
|
||||
final DateTime notOnOrAfter = assertion.getConditions().getNotOnOrAfter();
|
||||
final DateTime authenticationInstant = authenticationStatement.getAuthenticationInstant();
|
||||
return new AssertionImpl(principal, notBefore.toDate(), notOnOrAfter.toDate(),
|
||||
authenticationInstant.toDate(), authenticationAttributes);
|
||||
}
|
||||
} catch (final UnmarshallingException e) {
|
||||
throw new TicketValidationException(e);
|
||||
} catch (final XMLParserException e) {
|
||||
throw new TicketValidationException(e);
|
||||
}
|
||||
|
||||
throw new TicketValidationException(
|
||||
"No Assertion found within valid time range. Either there's a replay of the ticket or there's clock drift. Check tolerance range, or server/client synchronization.");
|
||||
}
|
||||
|
||||
private boolean isValidAssertion(final org.opensaml.saml1.core.Assertion assertion) {
|
||||
final DateTime notBefore = assertion.getConditions().getNotBefore();
|
||||
final DateTime notOnOrAfter = assertion.getConditions().getNotOnOrAfter();
|
||||
|
||||
if (notBefore == null || notOnOrAfter == null) {
|
||||
logger.debug("Assertion has no bounding dates. Will not process.");
|
||||
return false;
|
||||
}
|
||||
|
||||
final DateTime currentTime = new DateTime(DateTimeZone.UTC);
|
||||
final Interval validityRange = new Interval(notBefore.minus(this.tolerance), notOnOrAfter.plus(this.tolerance));
|
||||
|
||||
if (validityRange.contains(currentTime)) {
|
||||
logger.debug("Current time is within the interval validity.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentTime.isBefore(validityRange.getStart())) {
|
||||
logger.debug("skipping assertion that's not yet valid...");
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug("skipping expired assertion...");
|
||||
return false;
|
||||
}
|
||||
|
||||
private AuthenticationStatement getSAMLAuthenticationStatement(final org.opensaml.saml1.core.Assertion assertion) {
|
||||
final List<AuthenticationStatement> statements = assertion.getAuthenticationStatements();
|
||||
|
||||
if (statements.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return statements.get(0);
|
||||
}
|
||||
|
||||
private List<Attribute> getAttributesFor(final org.opensaml.saml1.core.Assertion assertion, final Subject subject) {
|
||||
final List<Attribute> attributes = new ArrayList<Attribute>();
|
||||
for (final AttributeStatement attribute : assertion.getAttributeStatements()) {
|
||||
if (subject.getNameIdentifier().getNameIdentifier()
|
||||
.equals(attribute.getSubject().getNameIdentifier().getNameIdentifier())) {
|
||||
attributes.addAll(attribute.getAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private List<?> getValuesFrom(final Attribute attribute) {
|
||||
final List<Object> list = new ArrayList<Object>();
|
||||
for (final Object o : attribute.getAttributeValues()) {
|
||||
if (o instanceof XSAny) {
|
||||
list.add(((XSAny) o).getTextContent());
|
||||
} else if (o instanceof XSString) {
|
||||
list.add(((XSString) o).getValue());
|
||||
} else {
|
||||
list.add(o.toString());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected String retrieveResponseFromServer(final URL validationUrl, final String ticket) {
|
||||
final String MESSAGE_TO_SEND = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"><SOAP-ENV:Header/><SOAP-ENV:Body><samlp:Request xmlns:samlp=\"urn:oasis:names:tc:SAML:1.0:protocol\" MajorVersion=\"1\" MinorVersion=\"1\" RequestID=\""
|
||||
+ this.identifierGenerator.generateIdentifier()
|
||||
+ "\" IssueInstant=\""
|
||||
+ CommonUtils.formatForUtcTime(new Date())
|
||||
+ "\">"
|
||||
+ "<samlp:AssertionArtifact>"
|
||||
+ ticket
|
||||
+ "</samlp:AssertionArtifact></samlp:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>";
|
||||
HttpURLConnection conn = null;
|
||||
DataOutputStream out = null;
|
||||
BufferedReader in = null;
|
||||
|
||||
try {
|
||||
conn = this.getURLConnectionFactory().buildHttpURLConnection(validationUrl.openConnection());
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "text/xml");
|
||||
conn.setRequestProperty("Content-Length", Integer.toString(MESSAGE_TO_SEND.length()));
|
||||
conn.setRequestProperty("SOAPAction", "http://www.oasis-open.org/committees/security");
|
||||
conn.setUseCaches(false);
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
out = new DataOutputStream(conn.getOutputStream());
|
||||
out.writeBytes(MESSAGE_TO_SEND);
|
||||
out.flush();
|
||||
|
||||
in = new BufferedReader(CommonUtils.isNotBlank(getEncoding()) ? new InputStreamReader(
|
||||
conn.getInputStream(), Charset.forName(getEncoding())) : new InputStreamReader(
|
||||
conn.getInputStream()));
|
||||
final StringBuilder buffer = new StringBuilder(256);
|
||||
|
||||
String line;
|
||||
|
||||
while ((line = in.readLine()) != null) {
|
||||
buffer.append(line);
|
||||
}
|
||||
return buffer.toString();
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
CommonUtils.closeQuietly(out);
|
||||
CommonUtils.closeQuietly(in);
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTolerance(final long tolerance) {
|
||||
this.tolerance = tolerance;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig licenses this file to you under the Apache License,
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation.json;
|
||||
|
||||
import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter;
|
||||
|
||||
/**
|
||||
* Creates either a Cas30JsonServiceTicketValidator to validate tickets.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
*/
|
||||
public class Cas30JsonProxyReceivingTicketValidationFilter extends Cas30ProxyReceivingTicketValidationFilter {
|
||||
|
||||
public Cas30JsonProxyReceivingTicketValidationFilter() {
|
||||
super();
|
||||
this.defaultServiceTicketValidatorClass = Cas30JsonServiceTicketValidator.class;
|
||||
this.defaultProxyTicketValidatorClass = Cas30JsonProxyTicketValidator.class;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation.json;
|
||||
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.Cas30ProxyTicketValidator;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is {@link Cas30JsonProxyTicketValidator} that attempts to parse the CAS validation response
|
||||
* as JSON. Very similar to {@link Cas30JsonServiceTicketValidator}, it also honors proxies as the name suggests.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
*/
|
||||
public class Cas30JsonProxyTicketValidator extends Cas30ProxyTicketValidator {
|
||||
public Cas30JsonProxyTicketValidator(final String casServerUrlPrefix) {
|
||||
super(casServerUrlPrefix);
|
||||
setCustomParameters(Collections.singletonMap("format", "JSON"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Assertion parseResponseFromServer(final String response) throws TicketValidationException {
|
||||
try {
|
||||
final TicketValidationJsonResponse json = new JsonValidationResponseParser().parse(response);
|
||||
return json.getAssertion(getProxyGrantingTicketStorage(), getProxyRetriever());
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Unable parse the JSON response");
|
||||
return super.parseResponseFromServer(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> parseProxiesFromResponse(final String response) {
|
||||
try {
|
||||
final TicketValidationJsonResponse json = new JsonValidationResponseParser().parse(response);
|
||||
return json.getServiceResponse().getAuthenticationSuccess().getProxies();
|
||||
} catch (final Exception e) {
|
||||
logger.warn("Unable to locate proxies from the JSON response", e);
|
||||
return super.parseProxiesFromResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation.json;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is {@link Cas30JsonServiceTicketValidator} that attempts to parse the CAS validation response
|
||||
* as JSON. If the response is not formatted as JSON, it shall fallback to the XML default syntax.
|
||||
* The JSON response provides advantages in terms of naming and parsing CAS attributes that have special
|
||||
* names that otherwise may not be encoded as XML, such as the invalid {@code <cas:special:attribute>value</cas:special:attribute>}
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
*/
|
||||
public class Cas30JsonServiceTicketValidator extends Cas30ServiceTicketValidator {
|
||||
|
||||
public Cas30JsonServiceTicketValidator(final String casServerUrlPrefix) {
|
||||
super(casServerUrlPrefix);
|
||||
setCustomParameters(Collections.singletonMap("format", "JSON"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Assertion parseResponseFromServer(final String response) throws TicketValidationException {
|
||||
try {
|
||||
final TicketValidationJsonResponse json = new JsonValidationResponseParser().parse(response);
|
||||
return json.getAssertion(getProxyGrantingTicketStorage(), getProxyRetriever());
|
||||
} catch (final JsonProcessingException e) {
|
||||
logger.warn("Unable parse the JSON response. Falling back to XML", e);
|
||||
return super.parseResponseFromServer(response);
|
||||
} catch (final IOException e) {
|
||||
throw new TicketValidationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> extractCustomAttributes(final String xml) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation.json;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This is {@link JsonValidationResponseParser}.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
*/
|
||||
final class JsonValidationResponseParser {
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public JsonValidationResponseParser() {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
this.objectMapper.findAndRegisterModules();
|
||||
}
|
||||
|
||||
public TicketValidationJsonResponse parse(final String response) throws TicketValidationException, IOException {
|
||||
if (CommonUtils.isBlank(response)) {
|
||||
throw new TicketValidationException("Invalid JSON response; The response is empty");
|
||||
}
|
||||
|
||||
final TicketValidationJsonResponse json = this.objectMapper.readValue(response, TicketValidationJsonResponse.class);
|
||||
|
||||
final TicketValidationJsonResponse.CasServiceResponseAuthentication serviceResponse = json.getServiceResponse();
|
||||
if (serviceResponse.getAuthenticationFailure() != null
|
||||
&& serviceResponse.getAuthenticationSuccess() != null) {
|
||||
throw new TicketValidationException("Invalid JSON response; It indicates both a success "
|
||||
+ "and a failure event, which is indicative of a server error. The actual response is " + response);
|
||||
}
|
||||
|
||||
if (serviceResponse.getAuthenticationFailure() != null) {
|
||||
final String error = json.getServiceResponse().getAuthenticationFailure().getCode()
|
||||
+ " - " + serviceResponse.getAuthenticationFailure().getDescription();
|
||||
throw new TicketValidationException(error);
|
||||
}
|
||||
|
||||
final String principal = json.getServiceResponse().getAuthenticationSuccess().getUser();
|
||||
if (CommonUtils.isEmpty(principal)) {
|
||||
throw new TicketValidationException("No principal was found in the response from the CAS server.");
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* Licensed to Apereo under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Apereo licenses this file to you 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 the following location:
|
||||
*
|
||||
* http://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.jasig.cas.client.validation.json;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.jasig.cas.client.proxy.ProxyRetriever;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.AssertionImpl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is {@link TicketValidationJsonResponse}.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
*/
|
||||
final class TicketValidationJsonResponse {
|
||||
private final CasServiceResponseAuthentication serviceResponse;
|
||||
|
||||
@JsonCreator
|
||||
public TicketValidationJsonResponse(@JsonProperty("serviceResponse")
|
||||
final CasServiceResponseAuthentication serviceResponse) {
|
||||
this.serviceResponse = serviceResponse;
|
||||
}
|
||||
|
||||
public CasServiceResponseAuthentication getServiceResponse() {
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
Assertion getAssertion(final ProxyGrantingTicketStorage proxyGrantingTicketStorage,
|
||||
final ProxyRetriever proxyRetriever) {
|
||||
final String proxyGrantingTicketIou = getServiceResponse().getAuthenticationSuccess().getProxyGrantingTicket();
|
||||
final String proxyGrantingTicket;
|
||||
if (CommonUtils.isBlank(proxyGrantingTicketIou) || proxyGrantingTicketStorage == null) {
|
||||
proxyGrantingTicket = null;
|
||||
} else {
|
||||
proxyGrantingTicket = proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou);
|
||||
}
|
||||
|
||||
final Assertion assertion;
|
||||
final Map<String, Object> attributes = getServiceResponse().getAuthenticationSuccess().getAttributes();
|
||||
final String principal = getServiceResponse().getAuthenticationSuccess().getUser();
|
||||
if (CommonUtils.isNotBlank(proxyGrantingTicket)) {
|
||||
final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes,
|
||||
proxyGrantingTicket, proxyRetriever);
|
||||
assertion = new AssertionImpl(attributePrincipal);
|
||||
} else {
|
||||
assertion = new AssertionImpl(new AttributePrincipalImpl(principal, attributes));
|
||||
}
|
||||
return assertion;
|
||||
}
|
||||
|
||||
static class CasServiceResponseAuthentication {
|
||||
private final CasServiceResponseAuthenticationFailure authenticationFailure;
|
||||
private final CasServiceResponseAuthenticationSuccess authenticationSuccess;
|
||||
|
||||
@JsonCreator
|
||||
public CasServiceResponseAuthentication(@JsonProperty("authenticationFailure")
|
||||
final CasServiceResponseAuthenticationFailure authenticationFailure,
|
||||
@JsonProperty("authenticationSuccess")
|
||||
final CasServiceResponseAuthenticationSuccess authenticationSuccess) {
|
||||
this.authenticationFailure = authenticationFailure;
|
||||
this.authenticationSuccess = authenticationSuccess;
|
||||
}
|
||||
|
||||
public CasServiceResponseAuthenticationFailure getAuthenticationFailure() {
|
||||
return this.authenticationFailure;
|
||||
}
|
||||
|
||||
public CasServiceResponseAuthenticationSuccess getAuthenticationSuccess() {
|
||||
return this.authenticationSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
static class CasServiceResponseAuthenticationSuccess {
|
||||
private String user;
|
||||
private String proxyGrantingTicket;
|
||||
private List proxies;
|
||||
private Map attributes;
|
||||
|
||||
public String getUser() {
|
||||
return this.user;
|
||||
}
|
||||
|
||||
public void setUser(final String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getProxyGrantingTicket() {
|
||||
return this.proxyGrantingTicket;
|
||||
}
|
||||
|
||||
public void setProxyGrantingTicket(final String proxyGrantingTicket) {
|
||||
this.proxyGrantingTicket = proxyGrantingTicket;
|
||||
}
|
||||
|
||||
public List getProxies() {
|
||||
return this.proxies;
|
||||
}
|
||||
|
||||
public void setProxies(final List proxies) {
|
||||
this.proxies = proxies;
|
||||
}
|
||||
|
||||
public Map getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
public void setAttributes(final Map attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
}
|
||||
|
||||
static class CasServiceResponseAuthenticationFailure {
|
||||
private String code;
|
||||
private String description;
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public void setCode(final String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public void setDescription(final String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue