Compare commits

...

800 Commits

Author SHA1 Message Date
Alexander Buntakov c516025070
Merge pull request #1 from TouchInstinct/feature/skip-internal-ip
support internal requests skip
2019-12-27 18:49:12 +03:00
Alexander Buntakov 71e71f15ff support internal requests skip 2019-12-27 17:53:03 +03:00
dependabot-preview[bot] 448b08c43c build(deps): bump jetty.version (#409)
Bumps `jetty.version` from 9.4.24.v20191120 to 9.4.25.v20191220.

Updates `jetty-security` from 9.4.24.v20191120 to 9.4.25.v20191220
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.24.v20191120...jetty-9.4.25.v20191220)

Updates `jetty-webapp` from 9.4.24.v20191120 to 9.4.25.v20191220
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.24.v20191120...jetty-9.4.25.v20191220)

Updates `jetty-plus` from 9.4.24.v20191120 to 9.4.25.v20191220
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.24.v20191120...jetty-9.4.25.v20191220)

Updates `jetty-annotations` from 9.4.24.v20191120 to 9.4.25.v20191220
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.24.v20191120...jetty-9.4.25.v20191220)

Updates `apache-jsp` from 9.4.24.v20191120 to 9.4.25.v20191220
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.24.v20191120...jetty-9.4.25.v20191220)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-24 05:46:06 +00:00
dependabot-preview[bot] 06f87f85fc build(deps): bump maven-source-plugin from 3.2.0 to 3.2.1 (#408)
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.0...maven-source-plugin-3.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-23 05:41:20 +00:00
renovate[bot] f2c44b7e74 renovatebot(deps): update dependency org.apache.tomcat:tomcat-catalina to v7.0.99 (#406) 2019-12-17 09:33:26 +00:00
renovate[bot] 94d81c32ba renovatebot(deps): update slf4j.version to v1.7.30 (#405) 2019-12-16 21:42:40 +00:00
renovate[bot] a96a13c630 renovatebot(deps): update dependency org.apache.tomcat:tomcat-catalina to v8.5.50 (#403) 2019-12-12 12:46:16 +00:00
renovate[bot] 06f3ebc7c2 renovatebot(deps): update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.50 (#402) 2019-12-12 12:46:08 +00:00
renovate[bot] 0dce0aa69e renovatebot(deps): update tomcat.version to v9.0.30 (#401) 2019-12-12 10:02:06 +00:00
renovate[bot] 8a665e1cb1 renovatebot(deps): update spring boot to v2.2.2.release (#400) 2019-12-06 12:42:38 +00:00
renovate[bot] dce1a94d9a renovatebot(deps): update spring core to v5.2.2.release (#399) 2019-12-03 13:17:34 +00:00
Petr Bodnar 76fb6a4f9c README.md - Only list used properties for Single Log Out (#398)
* README.md - Only list used properties for Single Log Out

Properties `casServerUrlPrefix` and `frontLogoutParameterName` are not really read by the SLO filter. Mainly the 1st one has no usage in this filter by design.

* README.md - Only list used properties for Single Log Out

Also removing unused `casServerUrlPrefix` from the code examples.
2019-11-30 12:21:06 +04:00
dependabot-preview[bot] 8d38080354 build(deps): bump jetty.version (#397)
Bumps `jetty.version` from 9.4.22.v20191022 to 9.4.24.v20191120.

Updates `jetty-security` from 9.4.22.v20191022 to 9.4.24.v20191120
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.22.v20191022...jetty-9.4.24.v20191120)

Updates `jetty-webapp` from 9.4.22.v20191022 to 9.4.24.v20191120
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.22.v20191022...jetty-9.4.24.v20191120)

Updates `jetty-plus` from 9.4.22.v20191022 to 9.4.24.v20191120
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.22.v20191022...jetty-9.4.24.v20191120)

Updates `jetty-annotations` from 9.4.22.v20191022 to 9.4.24.v20191120
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.22.v20191022...jetty-9.4.24.v20191120)

Updates `apache-jsp` from 9.4.22.v20191022 to 9.4.24.v20191120
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.22.v20191022...jetty-9.4.24.v20191120)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-22 05:38:31 +00:00
renovate[bot] be803939d8 renovatebot(deps): update dependency org.apache.tomcat:tomcat-catalina to v8.5.49 (#393) 2019-11-21 13:42:30 +00:00
renovate[bot] af1bbb2f32 renovatebot(deps): update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.49 (#392) 2019-11-21 13:42:21 +00:00
renovate[bot] c5a5a9961b renovatebot(deps): update dependency com.fasterxml.jackson.core:jackson-databind to v2.10.1 (#390) 2019-11-21 13:42:15 +00:00
renovate[bot] 6e2fbec2a4 renovatebot(deps): update tomcat.version to v9.0.29 (#394) 2019-11-21 13:39:17 +00:00
Misagh Moayyed 638c2d6fe4
fix maven jar plugin version 2019-11-21 17:31:58 +04:00
dependabot-preview[bot] efd6dbb491 Bump maven-source-plugin from 3.1.0 to 3.2.0 (#387)
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.1.0...maven-source-plugin-3.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-07 13:22:49 +04:00
renovate[bot] 905ce61e82 renovatebot(deps): update dependency org.apache.maven.plugins:ma… (#383) 2019-11-07 13:22:32 +04:00
dependabot-preview[bot] 3ba892e482 Bump maven-jar-plugin from 3.1.1 to 3.2.0 (#385)
Bumps [maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.1.1...maven-jar-plugin-3.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-07 13:22:15 +04:00
Gahon 62cc93399f add central logout support for springboot (#388)
* add dependence to generated metadata for springboot

* add central logout support for springboot
2019-11-07 11:56:45 +04:00
renovate[bot] cd67d874a2 renovatebot(deps): update dependency org.springframework.boot:spring-boot-starter to v2.2.1.release (#389) 2019-11-07 00:58:45 +00:00
renovate[bot] 46381476e9 renovatebot(deps): update dependency org.jasig.cas.client:cas-client to v3.6.1 (#369) 2019-11-04 18:25:30 +00:00
renovate[bot] d2538f378d renovatebot(deps): update spring core to v5.2.1.release (#381) 2019-11-04 18:23:06 +00:00
dependabot-preview[bot] f14d836e03 Bump spring.version from 5.2.0.RELEASE to 5.2.1.RELEASE (#384)
Bumps `spring.version` from 5.2.0.RELEASE to 5.2.1.RELEASE.

Updates `spring-core` from 5.2.0.RELEASE to 5.2.1.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.0.RELEASE...v5.2.1.RELEASE)

Updates `spring-context` from 5.2.0.RELEASE to 5.2.1.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.0.RELEASE...v5.2.1.RELEASE)

Updates `spring-web` from 5.2.0.RELEASE to 5.2.1.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.0.RELEASE...v5.2.1.RELEASE)

Updates `spring-test` from 5.2.0.RELEASE to 5.2.1.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.0.RELEASE...v5.2.1.RELEASE)

Updates `spring-beans` from 5.2.0.RELEASE to 5.2.1.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.0.RELEASE...v5.2.1.RELEASE)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-04 18:23:02 +00:00
renovate[bot] e2e4ea9fa1 renovatebot(deps): update dependency org.apache.maven.plugins:ma… (#382) 2019-11-04 22:22:45 +04:00
dependabot-preview[bot] df89820368 Bump maven-assembly-plugin from 3.1.1 to 3.2.0 (#386)
Bumps [maven-assembly-plugin](https://github.com/apache/maven-assembly-plugin) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/apache/maven-assembly-plugin/releases)
- [Commits](https://github.com/apache/maven-assembly-plugin/compare/maven-assembly-plugin-3.1.1...maven-assembly-plugin-3.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-04 22:22:26 +04:00
Misagh Moayyed 3005cc8607
Update .mergify.yml 2019-11-04 22:21:59 +04:00
renovate[bot] e0374d61ac renovatebot(deps): update dependency joda-time:joda-time to v2.1… (#378) 2019-10-31 23:37:23 +04:00
renovate[bot] 360ff59ddd renovatebot(deps): update dependency org.apache.tomcat:tomcat-ca… (#372) 2019-10-31 23:37:03 +04:00
renovate[bot] 59f42b7edf renovatebot(deps): update tomcat.version to v9.0.27 (#370) 2019-10-31 23:36:44 +04:00
dependabot-preview[bot] 409bd553ba Bump jetty.version from 9.4.21.v20190926 to 9.4.22.v20191022 (#377)
Bumps `jetty.version` from 9.4.21.v20190926 to 9.4.22.v20191022.

Updates `jetty-security` from 9.4.21.v20190926 to 9.4.22.v20191022
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.21.v20190926...jetty-9.4.22.v20191022)

Updates `jetty-webapp` from 9.4.21.v20190926 to 9.4.22.v20191022
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.21.v20190926...jetty-9.4.22.v20191022)

Updates `jetty-plus` from 9.4.21.v20190926 to 9.4.22.v20191022
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.21.v20190926...jetty-9.4.22.v20191022)

Updates `jetty-annotations` from 9.4.21.v20190926 to 9.4.22.v20191022
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.21.v20190926...jetty-9.4.22.v20191022)

Updates `apache-jsp` from 9.4.21.v20190926 to 9.4.22.v20191022
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.21.v20190926...jetty-9.4.22.v20191022)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-31 23:36:23 +04:00
dependabot-preview[bot] 3ec16e8aaf Bump joda-time from 2.10.4 to 2.10.5 (#379)
Bumps [joda-time](https://github.com/JodaOrg/joda-time) from 2.10.4 to 2.10.5.
- [Release notes](https://github.com/JodaOrg/joda-time/releases)
- [Changelog](https://github.com/JodaOrg/joda-time/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/JodaOrg/joda-time/compare/v2.10.4...v2.10.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-31 23:35:14 +04:00
renovate[bot] 08bedcf889 renovatebot(deps): update slf4j.version to v1.7.29 (#380) 2019-10-31 23:34:59 +04:00
Misagh Moayyed da7ff03cff
Update .mergify.yml 2019-10-24 19:04:44 +04:00
renovate[bot] 5aaf09b3e4 renovatebot(deps): update dependency org.apache.tomcat.embed:tom… (#371) 2019-10-24 19:04:14 +04:00
dependabot-preview[bot] fd176bc1a7 Bump spring-boot-starter from 2.1.9.RELEASE to 2.2.0.RELEASE (#376)
Bumps [spring-boot-starter](https://github.com/spring-projects/spring-boot) from 2.1.9.RELEASE to 2.2.0.RELEASE.
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v2.1.9.RELEASE...v2.2.0.RELEASE)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-17 17:51:43 +04:00
renovate[bot] 9f09c15673 renovatebot(deps): update dependency org.bouncycastle:bcpkix-jdk15on to v1.64 (#373) 2019-10-12 10:20:46 +04:00
Misagh Moayyed e4c1df0280
[maven-release-plugin] prepare for next development iteration 2019-10-08 17:22:31 +04:00
Misagh Moayyed a00064d1d8
[maven-release-plugin] prepare release cas-client-3.6.1 2019-10-08 17:22:16 +04:00
Misagh Moayyed 21d5f37322
Updated: code cleanup and styling; fixes test cases 2019-10-08 17:20:43 +04:00
Misagh Moayyed 872fc49fb7
ensure API compatibility 2019-10-08 17:19:45 +04:00
Jérôme LELEU 18c79fcf00 [maven-release-plugin] prepare for next development iteration 2019-10-07 11:02:29 +02:00
Jérôme LELEU 9394a6e190 [maven-release-plugin] prepare release cas-client-3.6.0 2019-10-07 11:02:21 +02:00
LELEU Jérôme 3e99e678ca
fix notice and license issues (#368) 2019-10-07 10:25:43 +02:00
mergify[bot] 2beda557e1
Merge pull request #367 from apereo/renovate/spring-boot
renovatebot(deps): update dependency org.springframework.boot:spring-boot-starter to v2.1.9.release
2019-10-02 17:42:25 +00:00
Renovate Bot a233009f68
renovatebot(deps): update dependency org.springframework.boot:spring-boot-starter to v2.1.9.release 2019-10-02 17:29:14 +00:00
mergify[bot] e7d2c87668
Merge pull request #366 from apereo/dependabot/maven/jetty.version-9.4.21.v20190926
Bump jetty.version from 9.4.20.v20190813 to 9.4.21.v20190926
2019-10-02 06:54:38 +00:00
dependabot-preview[bot] 8a972d38e1
Bump jetty.version from 9.4.20.v20190813 to 9.4.21.v20190926
Bumps `jetty.version` from 9.4.20.v20190813 to 9.4.21.v20190926.

Updates `jetty-security` from 9.4.20.v20190813 to 9.4.21.v20190926
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.20.v20190813...jetty-9.4.21.v20190926)

Updates `jetty-webapp` from 9.4.20.v20190813 to 9.4.21.v20190926
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.20.v20190813...jetty-9.4.21.v20190926)

Updates `jetty-plus` from 9.4.20.v20190813 to 9.4.21.v20190926
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.20.v20190813...jetty-9.4.21.v20190926)

Updates `jetty-annotations` from 9.4.20.v20190813 to 9.4.21.v20190926
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.20.v20190813...jetty-9.4.21.v20190926)

Updates `apache-jsp` from 9.4.20.v20190813 to 9.4.21.v20190926
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.20.v20190813...jetty-9.4.21.v20190926)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-02 06:52:04 +00:00
mergify[bot] 2ac1e1b7a6
Merge pull request #365 from apereo/renovate/spring-core
renovatebot(deps): update spring core to v5.2.0.release
2019-09-30 11:26:29 +00:00
Renovate Bot bca6d9b830
renovatebot(deps): update spring core to v5.2.0.release 2019-09-30 10:39:50 +00:00
mergify[bot] 9e89fe960a
Merge pull request #364 from apereo/renovate/spring-core
renovatebot(deps): update spring core to v5.1.10.release
2019-09-28 14:07:13 +00:00
Renovate Bot 15567ef2a6
renovatebot(deps): update spring core to v5.1.10.release 2019-09-28 12:38:49 +00:00
mergify[bot] 5b47efa407
Merge pull request #363 from apereo/renovate/jackson.version
renovatebot(deps): update dependency com.fasterxml.jackson.core:jackson-databind to v2.10.0
2019-09-26 04:47:17 +00:00
Renovate Bot 3ff317846f
renovatebot(deps): update dependency com.fasterxml.jackson.core:jackson-databind to v2.10.0 2019-09-26 04:44:45 +00:00
mergify[bot] e39d35fbd7
Merge pull request #362 from apereo/renovate/jackson.version
renovatebot(deps): update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.10
2019-09-21 21:25:54 +00:00
Renovate Bot 0fbe33a7e5
renovatebot(deps): update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.10 2019-09-21 18:44:15 +00:00
mergify[bot] b531896715
Merge pull request #361 from apereo/renovate/joda-time-joda-time-2.x
renovatebot(deps): update dependency joda-time:joda-time to v2.10.4
2019-09-20 12:41:57 +00:00
Renovate Bot e3b109264c
renovatebot(deps): update dependency joda-time:joda-time to v2.10.4 2019-09-20 12:39:21 +00:00
mergify[bot] 81cdceca8f
Merge pull request #359 from apereo/renovate/tomcat.version
renovatebot(deps): update tomcat.version to v9.0.26
2019-09-20 01:44:36 +00:00
Renovate Bot 5b5ca68d05
renovatebot(deps): update tomcat.version to v9.0.26 2019-09-20 01:41:57 +00:00
mergify[bot] 2728f0597d
Merge pull request #358 from apereo/renovate/org.apache.tomcat-tomcat-catalina-8.x
renovatebot(deps): update dependency org.apache.tomcat:tomcat-catalina to v8.5.46
2019-09-20 01:41:32 +00:00
Renovate Bot 5bd4465298
renovatebot(deps): update dependency org.apache.tomcat:tomcat-catalina to v8.5.46 2019-09-20 00:15:58 +00:00
mergify[bot] 7d9ee60b73
Merge pull request #357 from apereo/renovate/org.apache.tomcat.embed-tomcat-embed-core-8.x
renovatebot(deps): update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.46
2019-09-20 00:15:33 +00:00
Renovate Bot 5f82143b00
renovatebot(deps): update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.46 2019-09-19 21:34:10 +00:00
mergify[bot] 1fad31d8b0
Merge pull request #356 from apereo/dependabot/maven/org.bouncycastle-bcpkix-jdk15on-1.63
Bump bcpkix-jdk15on from 1.62 to 1.63
2019-09-11 05:41:38 +00:00
dependabot-preview[bot] 3d391b62b8
Bump bcpkix-jdk15on from 1.62 to 1.63
Bumps [bcpkix-jdk15on](https://github.com/bcgit/bc-java) from 1.62 to 1.63.
- [Release notes](https://github.com/bcgit/bc-java/releases)
- [Changelog](https://github.com/bcgit/bc-java/blob/master/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-11 05:39:18 +00:00
mergify[bot] 913c412fba
Merge pull request #354 from apereo/renovate/spring-boot
renovatebot(deps): update dependency org.springframework.boot:spring-boot-starter to v2.1.8.release
2019-09-05 22:59:47 +00:00
Renovate Bot b355b526d6
renovatebot(deps): update dependency org.springframework.boot:spring-boot-starter to v2.1.8.release 2019-09-05 22:57:35 +00:00
mergify[bot] 858b0ca77d
Merge pull request #351 from apereo/renovate/javax.servlet-javax.servlet-api-4.x
renovatebot(deps): update dependency javax.servlet:javax.servlet-api to v4
2019-08-22 05:54:16 +00:00
Renovate Bot c00ee02f44
renovatebot(deps): update dependency javax.servlet:javax.servlet-api to v4 2019-08-22 05:52:05 +00:00
mergify[bot] 40848d251e
Merge pull request #350 from apereo/renovate/com.atlassian.user-atlassian-user-5.x
renovatebot(deps): update dependency com.atlassian.user:atlassian-user to v5
2019-08-22 05:51:40 +00:00
Renovate Bot a7b7660772
renovatebot(deps): update dependency com.atlassian.user:atlassian-user to v5 2019-08-22 05:49:27 +00:00
mergify[bot] 440f2edaa6
Merge pull request #349 from apereo/renovate/com.atlassian.seraph-atlassian-seraph-4.x
renovatebot(deps): update dependency com.atlassian.seraph:atlassian-seraph to v4
2019-08-22 05:49:00 +00:00
Renovate Bot 8667f0b946
renovatebot(deps): update dependency com.atlassian.seraph:atlassian-seraph to v4 2019-08-22 05:46:54 +00:00
renovate[bot] 60a8cb3825 Update dependency org.apache.tomcat:tomcat-catalina to v8.5.45 (#347) 2019-08-22 10:16:11 +04:30
Misagh Moayyed 11a53a6fc2
Update renovate.json 2019-08-22 10:15:46 +04:30
renovate[bot] 58a54c7372 Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.45 (#346) 2019-08-21 20:31:25 +04:30
renovate[bot] 53f34e175e Update tomcat.version to v9.0.24 (#344) 2019-08-18 08:04:29 +04:30
mergify[bot] 9279ab8d54
Merge pull request #343 from apereo/dependabot/maven/jetty.version-9.4.20.v20190813
Bump jetty.version from 9.4.18.v20190429 to 9.4.20.v20190813
2019-08-15 05:59:08 +00:00
dependabot-preview[bot] 6352b7991a
Bump jetty.version from 9.4.18.v20190429 to 9.4.20.v20190813
Bumps `jetty.version` from 9.4.18.v20190429 to 9.4.20.v20190813.

Updates `jetty-security` from 9.4.18.v20190429 to 9.4.20.v20190813
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.18.v20190429...jetty-9.4.20.v20190813)

Updates `jetty-webapp` from 9.4.18.v20190429 to 9.4.20.v20190813
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.18.v20190429...jetty-9.4.20.v20190813)

Updates `jetty-plus` from 9.4.18.v20190429 to 9.4.20.v20190813
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.18.v20190429...jetty-9.4.20.v20190813)

Updates `jetty-annotations` from 9.4.18.v20190429 to 9.4.20.v20190813
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.18.v20190429...jetty-9.4.20.v20190813)

Updates `apache-jsp` from 9.4.18.v20190429 to 9.4.20.v20190813
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.18.v20190429...jetty-9.4.20.v20190813)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-15 05:52:39 +00:00
mergify[bot] db9f0a3301
Merge pull request #342 from apereo/dependabot/maven/slf4j.version-1.7.28
Bump slf4j.version from 1.7.27 to 1.7.28
2019-08-12 07:59:51 +00:00
dependabot-preview[bot] 4c4202de24
Bump slf4j.version from 1.7.27 to 1.7.28
Bumps `slf4j.version` from 1.7.27 to 1.7.28.

Updates `slf4j-api` from 1.7.27 to 1.7.28
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.27...v_1.7.28)

Updates `jcl-over-slf4j` from 1.7.27 to 1.7.28
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.27...v_1.7.28)

Updates `slf4j-simple` from 1.7.27 to 1.7.28
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.27...v_1.7.28)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-12 06:52:55 +00:00
Misagh Moayyed 6f7ef142bc
add tomcat 9.0.x 2019-08-09 15:04:33 +04:30
Misagh Moayyed 7e34235578
fix license headers 2019-08-09 14:55:39 +04:30
mergify[bot] 07a700f531
Merge pull request #335 from apereo/dependabot/maven/spring.version-5.1.9.RELEASE
[Security] Bump spring.version from 3.1.3.RELEASE to 5.1.9.RELEASE
2019-08-08 19:57:20 +00:00
Misagh Moayyed 31756bd6fc
Merge branch 'master' into dependabot/maven/spring.version-5.1.9.RELEASE 2019-08-09 00:25:10 +04:30
Misagh Moayyed 95583500c0
Update dependency org.springframework.boot:spring-boot-starter t… (#338)
Update dependency org.springframework.boot:spring-boot-starter to v2.1.7.RELEASE
2019-08-08 22:22:26 +04:30
mergify[bot] c096b4c82b
Merge pull request #339 from apereo/dependabot/maven/org.springframework.boot-spring-boot-starter-2.1.7.RELEASE
Bump spring-boot-starter from 2.1.4.RELEASE to 2.1.7.RELEASE
2019-08-08 17:45:23 +00:00
dependabot-preview[bot] 63d638b452
Bump spring-boot-starter from 2.1.4.RELEASE to 2.1.7.RELEASE
Bumps [spring-boot-starter](https://github.com/spring-projects/spring-boot) from 2.1.4.RELEASE to 2.1.7.RELEASE.
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v2.1.4.RELEASE...v2.1.7.RELEASE)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-08 17:43:17 +00:00
Renovate Bot ee21f2874a
Update dependency org.springframework.boot:spring-boot-starter to v2.1.7.RELEASE 2019-08-08 17:42:26 +00:00
Misagh Moayyed 24c3f92030
updated 2019-08-08 22:11:54 +04:30
Misagh Moayyed 3b312e1cff
Merge pull request #340 from apereo/boot-module-javadoc-polish
Correct `@since`
2019-08-08 20:25:56 +04:30
Dmitriy Kopylenko 7f0b42df31 Correct @since 2019-08-08 08:42:09 -04:00
Misagh Moayyed 4d84e02c5f
updated 2019-08-07 21:41:29 +04:30
Misagh Moayyed ca5e5f1f06
add springboot autocfg support 2019-08-07 21:39:44 +04:30
Misagh Moayyed 387e7249e0 Merge branch 'master' of github.com:Jasig/java-cas-client 2019-08-07 19:10:37 +04:30
Misagh Moayyed 8a7e04d7cf
updated 2019-08-07 19:09:42 +04:30
Misagh Moayyed 11d3c21889
Update slf4j.version to v1.7.27 (#337)
Update slf4j.version to v1.7.27
2019-08-06 17:45:51 +04:30
Renovate Bot a51fd8f8f8
Update slf4j.version to v1.7.27 2019-08-06 09:38:46 +00:00
Misagh Moayyed 1a6da20b3e
Merge pull request #336 from apereo/renovate/jackson.version
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9.3
2019-08-06 06:24:53 +04:30
Renovate Bot 2a3adb4ec4
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9.3 2019-08-06 01:52:43 +00:00
Misagh Moayyed a5a7d30791
Merge branch 'master' into dependabot/maven/spring.version-5.1.9.RELEASE 2019-08-05 14:34:19 +04:30
Misagh Moayyed bab29c84f4
fix compile errors 2019-08-05 14:14:59 +04:30
Misagh Moayyed 8eaec09704
disable attlassian from build - unmaintained 2019-08-05 13:54:06 +04:30
dependabot-preview[bot] da07e4815b
[Security] Bump spring.version from 3.1.3.RELEASE to 5.1.9.RELEASE
Bumps `spring.version` from 3.1.3.RELEASE to 5.1.9.RELEASE.

Updates `spring-core` from 3.1.3.RELEASE to 5.1.9.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v3.1.3.RELEASE...v5.1.9.RELEASE)

Updates `spring-context` from 3.1.3.RELEASE to 5.1.9.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v3.1.3.RELEASE...v5.1.9.RELEASE)

Updates `spring-test` from 3.1.3.RELEASE to 5.1.9.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v3.1.3.RELEASE...v5.1.9.RELEASE)

Updates `spring-beans` from 3.1.3.RELEASE to 5.1.9.RELEASE
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v3.1.3.RELEASE...v5.1.9.RELEASE)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-05 06:38:36 +00:00
Misagh Moayyed de1f05dc8b
Merge pull request #334 from apereo/renovate/maven-com.fasterxml.jackson.core-jackson-databind-vulnerability
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9.2 [SECURITY]
2019-08-02 05:26:25 +04:30
Renovate Bot 1300774928
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9.2 [SECURITY] 2019-08-01 20:56:04 +00:00
Misagh Moayyed f946c2845b
Update dependency org.apache.tomcat:tomcat-catalina to v7.0.96 (#333)
Update dependency org.apache.tomcat:tomcat-catalina to v7.0.96
2019-07-29 22:37:59 +04:30
Renovate Bot 3cd4e12fa9
Update dependency org.apache.tomcat:tomcat-catalina to v7.0.96 2019-07-29 18:00:07 +00:00
Misagh Moayyed 3e5eeaabe1
Merge pull request #331 from larsgrefer/gh-329
Remove the unused 'casServerUrlPrefix' parameter
2019-07-26 08:54:28 +04:30
Lars Grefer fdc948b8ec Remove the unused 'casServerUrlPrefix' parameter
fixes #329
2019-07-25 22:54:58 +02:00
Misagh Moayyed 1966a26d6f
Update dependency commons-codec:commons-codec to v1.13 (#330)
Update dependency commons-codec:commons-codec to v1.13
2019-07-23 17:46:00 +04:30
Misagh Moayyed c2886ea70c
Update dependency org.apache.tomcat.embed:tomcat-embed-core to v… (#326)
Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.43
2019-07-23 17:44:45 +04:30
Renovate Bot 850a6c0373
Update dependency commons-codec:commons-codec to v1.13 2019-07-23 12:42:59 +00:00
Misagh Moayyed 764d2220d6
Merge pull request #327 from apereo/renovate/org.apache.tomcat-tomcat-catalina-8.x
Update dependency org.apache.tomcat:tomcat-catalina to v8.5.43
2019-07-18 09:42:37 +04:30
Misagh Moayyed 77abda055b
Create FUNDING.yml 2019-07-13 23:10:19 +04:30
Renovate Bot 505160b15e
Update dependency org.apache.tomcat:tomcat-catalina to v8.5.43 2019-07-09 15:53:24 +00:00
Renovate Bot fdab7aea5b
Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.43 2019-07-09 15:53:17 +00:00
Misagh Moayyed 9e95c8a10c
Bump maven-javadoc-plugin from 3.1.0 to 3.1.1 (#325)
Bump maven-javadoc-plugin from 3.1.0 to 3.1.1
2019-07-08 11:56:02 +04:30
Misagh Moayyed f7234f9aea
Update dependency org.apache.maven.plugins:maven-javadoc-plugin… (#324)
Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.1.1
2019-07-08 11:55:56 +04:30
Misagh Moayyed 0e4c82cc94
Merge pull request #323 from apereo/dependabot/maven/joda-time-joda-time-2.10.3
Bump joda-time from 2.10.2 to 2.10.3
2019-07-08 11:55:48 +04:30
dependabot-preview[bot] 8596db4de3
Bump maven-javadoc-plugin from 3.1.0 to 3.1.1
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.1.0...maven-javadoc-plugin-3.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-08 05:57:27 +00:00
Renovate Bot ccf8b89dee
Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.1.1 2019-07-07 09:49:25 +00:00
Misagh Moayyed 3f45530e0e
Merge pull request #322 from apereo/renovate/joda-time-joda-time-2.x
Update dependency joda-time:joda-time to v2.10.3
2019-07-05 10:21:42 +04:30
Misagh Moayyed 46341d3e42
Merge pull request #321 from apereo/renovate/com.fasterxml.jackson.core-jackson-databind-2.x
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9.1
2019-07-05 10:21:14 +04:30
dependabot-preview[bot] 9fabd9fbf1
Bump joda-time from 2.10.2 to 2.10.3
Bumps [joda-time](https://github.com/JodaOrg/joda-time) from 2.10.2 to 2.10.3.
- [Release notes](https://github.com/JodaOrg/joda-time/releases)
- [Changelog](https://github.com/JodaOrg/joda-time/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/JodaOrg/joda-time/compare/v2.10.2...v2.10.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-05 05:49:20 +00:00
Renovate Bot be29e420c0
Update dependency joda-time:joda-time to v2.10.3 2019-07-04 15:44:58 +00:00
Renovate Bot 2734d45f3e
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9.1 2019-07-03 01:36:11 +00:00
Misagh Moayyed 601959f85c
Update .travis.yml 2019-06-26 01:54:56 -07:00
Misagh Moayyed bf4e1e60b6 Update .travis.yml 2019-06-26 01:42:56 -07:00
Misagh Moayyed 0c041d5376 Update .travis.yml 2019-06-26 01:40:02 -07:00
Misagh Moayyed a7101b6cc8 Provide for secure XML processing. (#318)
Provide for secure XML processing.
2019-06-26 13:09:36 +04:30
Marvin S. Addison 7ce4cb8aa5 Provide for secure XML processing.
Follow recommendations at https://wiki.shibboleth.net/confluence/x/XoEYAw
which are consistent with recommendations on #191 to prevent XXE vectors.

Resolves #191
See https://github.com/apereo/java-cas-client/issues/191
2019-06-25 08:01:46 -04:00
Misagh Moayyed a95a98dd9b Merge pull request #313 from apereo/renovate/org.apache.tomcat.embed-tomcat-embed-core-8.x
Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.42
2019-06-14 08:32:07 +04:30
Renovate Bot a3dbe594c3 Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.42 2019-06-07 21:33:49 +00:00
Misagh Moayyed 49f9a4e309 Merge pull request #311 from apereo/renovate/org.bouncycastle-bcpkix-jdk15on-1.x
Update dependency org.bouncycastle:bcpkix-jdk15on to v1.62
2019-06-07 07:41:38 -07:00
Misagh Moayyed fd72cb6bfc Bump bcpkix-jdk15on from 1.61 to 1.62 (#312)
Bump bcpkix-jdk15on from 1.61 to 1.62
2019-06-07 07:41:23 -07:00
dependabot-preview[bot] 78b2997c5d Bump bcpkix-jdk15on from 1.61 to 1.62
Bumps [bcpkix-jdk15on](https://github.com/bcgit/bc-java) from 1.61 to 1.62.
- [Release notes](https://github.com/bcgit/bc-java/releases)
- [Changelog](https://github.com/bcgit/bc-java/blob/master/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-07 10:33:56 +00:00
Renovate Bot cfebf0acc7 Update dependency org.bouncycastle:bcpkix-jdk15on to v1.62 2019-06-07 04:36:32 +00:00
Misagh Moayyed 874958641a Merge pull request #307 from apereo/dependabot/maven/jetty.version-9.4.18.v20190429
Bump jetty.version from 9.2.14.v20151106 to 9.4.18.v20190429
2019-06-04 06:06:54 -07:00
Misagh Moayyed 691bf12697 Merge pull request #310 from apereo/dependabot/maven/net.sf.ehcache-ehcache-core-2.6.11
Bump ehcache-core from 2.2.0 to 2.6.11
2019-06-04 06:06:17 -07:00
Misagh Moayyed 4332186ea7 Merge pull request #308 from apereo/dependabot/maven/org.apache.maven.plugins-maven-source-plugin-3.1.0
Bump maven-source-plugin from 2.2.1 to 3.1.0
2019-06-04 06:04:38 -07:00
Hal Deadman 52274f828f Merge pull request #251 from inghamn/patch-1
Prioritize X-Forwarded-Host when choosing the service parameter
2019-05-29 19:15:12 -04:00
dependabot-preview[bot] 5c3d185e8d Bump ehcache-core from 2.2.0 to 2.6.11
Bumps ehcache-core from 2.2.0 to 2.6.11.
2019-05-28 10:50:55 +00:00
dependabot-preview[bot] 35d611b8e8 Bump maven-source-plugin from 2.2.1 to 3.1.0
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 2.2.1 to 3.1.0.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-2.2.1...maven-source-plugin-3.1.0)
2019-05-28 10:50:13 +00:00
dependabot-preview[bot] d940cfd417 Bump jetty.version from 9.2.14.v20151106 to 9.4.18.v20190429
Bumps `jetty.version` from 9.2.14.v20151106 to 9.4.18.v20190429.

Updates `jetty-security` from 9.2.14.v20151106 to 9.4.18.v20190429
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.2.14.v20151106...jetty-9.4.18.v20190429)

Updates `jetty-webapp` from 9.2.14.v20151106 to 9.4.18.v20190429
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.2.14.v20151106...jetty-9.4.18.v20190429)

Updates `jetty-plus` from 9.2.14.v20151106 to 9.4.18.v20190429
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.2.14.v20151106...jetty-9.4.18.v20190429)

Updates `jetty-annotations` from 9.2.14.v20151106 to 9.4.18.v20190429
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.2.14.v20151106...jetty-9.4.18.v20190429)

Updates `apache-jsp` from 9.2.14.v20151106 to 9.4.18.v20190429
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.2.14.v20151106...jetty-9.4.18.v20190429)
2019-05-27 13:32:43 +00:00
Misagh Moayyed 1d78f74b2a Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.41 (#299)
Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.41
2019-05-23 04:39:18 -07:00
Misagh Moayyed 12da0340a1 Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9 [SECURITY] (#302)
Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9 [SECURITY]
2019-05-23 04:38:44 -07:00
Renovate Bot e283a9a7a5 Update dependency com.fasterxml.jackson.core:jackson-databind to v2.9.9 [SECURITY] 2019-05-23 10:35:34 +00:00
Renovate Bot 1c29fa7ebd Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.41 2019-05-14 20:54:21 +00:00
Misagh Moayyed 7bea9bb258 Update dependency joda-time:joda-time to v2.10.2 (#297)
Update dependency joda-time:joda-time to v2.10.2
2019-05-09 09:03:56 -07:00
Renovate Bot 4ada1b1327 Update dependency joda-time:joda-time to v2.10.2 2019-05-09 14:39:32 +00:00
Misagh Moayyed 32d14893ae Merge pull request #292 from apereo/renovate/org.jasig.parent-jasig-parent-41.x
Update dependency org.jasig.parent:jasig-parent to v41
2019-05-02 20:00:06 -07:00
Misagh Moayyed 0f395b3a2c Merge pull request #294 from apereo/renovate/org.apache.maven.plugins-maven-compiler-plugin-3.x
Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.8.1
2019-05-02 19:59:45 -07:00
Misagh Moayyed 0e750de5f5 Merge pull request #295 from apereo/renovate/org.apache.maven.plugins-maven-surefire-plugin-2.x
Update dependency org.apache.maven.plugins:maven-surefire-plugin to v2.22.2
2019-05-02 19:59:13 -07:00
Renovate Bot 26479f3d99 Update dependency org.apache.maven.plugins:maven-surefire-plugin to v2.22.2 2019-05-02 20:54:26 +00:00
Renovate Bot 11e9b543e5 Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.8.1 2019-05-02 18:54:12 +00:00
Misagh Moayyed 5c2c6b00aa Update dependency org.apache.maven.plugins:maven-assembly-plugin to v3 (#288)
Update dependency org.apache.maven.plugins:maven-assembly-plugin to v3
2019-05-02 06:44:53 -07:00
Misagh Moayyed f0bd481a13 Update dependency org.apache.maven.plugins:maven-jar-plugin to v3 (#289)
Update dependency org.apache.maven.plugins:maven-jar-plugin to v3
2019-05-02 06:44:42 -07:00
Misagh Moayyed 8fb8e9d0e4 Merge pull request #277 from apereo/renovate/org.apache.tomcat.embed-tomcat-embed-core-8.x
Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.40
2019-05-02 06:44:30 -07:00
Misagh Moayyed 3213920bff Merge pull request #278 from apereo/renovate/org.apache.tomcat-catalina-6.x
Update dependency org.apache.tomcat:catalina to v6.0.53
2019-05-02 06:44:06 -07:00
Misagh Moayyed 01812e755d Update dependency org.slf4j:slf4j-simple to v1.7.26 (#283)
Update dependency org.slf4j:slf4j-simple to v1.7.26
2019-04-30 14:27:25 -07:00
Misagh Moayyed d35172dff9 Update dependency org.slf4j:jcl-over-slf4j to v1.7.26 (#281)
Update dependency org.slf4j:jcl-over-slf4j to v1.7.26
2019-04-30 14:27:11 -07:00
Misagh Moayyed 1999bd4670 Update dependency org.slf4j:slf4j-api to v1.7.26 (#282)
Update dependency org.slf4j:slf4j-api to v1.7.26
2019-04-30 14:26:58 -07:00
Renovate Bot 4f411c4342 Update dependency org.jasig.parent:jasig-parent to v41 2019-04-30 20:56:06 +00:00
Renovate Bot c6a46da7fa Update dependency org.apache.maven.plugins:maven-jar-plugin to v3 2019-04-30 19:40:11 +00:00
Renovate Bot c8c0d844b4 Update dependency org.apache.maven.plugins:maven-assembly-plugin to v3 2019-04-30 18:34:17 +00:00
Renovate Bot cf7e09b1c4 Update dependency org.slf4j:slf4j-simple to v1.7.26 2019-04-30 16:48:14 +00:00
Renovate Bot 68a0cc0433 Update dependency org.slf4j:slf4j-api to v1.7.26 2019-04-30 15:36:57 +00:00
Renovate Bot c8eb5b4e5a Update dependency org.slf4j:jcl-over-slf4j to v1.7.26 2019-04-30 15:36:50 +00:00
Renovate Bot 0f69d262e8 Update dependency org.apache.tomcat:catalina to v6.0.53 2019-04-30 13:15:29 +00:00
Renovate Bot 748a7172f5 Update dependency org.apache.tomcat.embed:tomcat-embed-core to v8.5.40 2019-04-30 13:15:22 +00:00
Misagh Moayyed d1c3660cda Update dependency javax.servlet:javax.servlet-api to v3.1.0 (#266)
Update dependency javax.servlet:javax.servlet-api to v3.1.0
2019-04-30 06:14:59 -07:00
Misagh Moayyed 78470351f6 Update dependency joda-time:joda-time to v2.10.1 (#267)
Update dependency joda-time:joda-time to v2.10.1
2019-04-30 06:14:50 -07:00
Misagh Moayyed 9e7ad3f046 Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.1.0 (#275)
Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.1.0
2019-04-30 06:14:37 -07:00
Misagh Moayyed 3688949646 Update dependency org.apache.maven.plugins:maven-surefire-plugin to v2.22.1 (#276)
Update dependency org.apache.maven.plugins:maven-surefire-plugin to v2.22.1
2019-04-30 06:14:29 -07:00
Renovate Bot a091c2795b Update dependency org.apache.maven.plugins:maven-surefire-plugin to v2.22.1 2019-04-30 12:49:37 +00:00
Renovate Bot 411a105fb1 Update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.1.0 2019-04-30 12:49:30 +00:00
Renovate Bot bd7ebc11c7 Update dependency joda-time:joda-time to v2.10.1 2019-04-30 11:26:23 +00:00
Renovate Bot 61c842124e Update dependency javax.servlet:javax.servlet-api to v3.1.0 2019-04-30 11:26:17 +00:00
Misagh Moayyed bb95fd733f Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.8.0 (#273)
Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.8.0
2019-04-30 04:25:46 -07:00
Misagh Moayyed 2b61ca1df3 Update dependency org.apache.maven.plugins:maven-enforcer-plugin to v1.4.1 (#274)
Update dependency org.apache.maven.plugins:maven-enforcer-plugin to v1.4.1
2019-04-30 04:25:38 -07:00
Misagh Moayyed b61487766c Update dependency junit:junit to v4.12 (#268)
Update dependency junit:junit to v4.12
2019-04-30 04:25:28 -07:00
Renovate Bot 1f6881829b Update dependency org.apache.maven.plugins:maven-enforcer-plugin to v1.4.1 2019-04-30 11:12:13 +00:00
Renovate Bot a8ec3de36e Update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.8.0 2019-04-30 11:12:07 +00:00
Renovate Bot a4cde4359e Update dependency junit:junit to v4.12 2019-04-30 11:12:01 +00:00
Misagh Moayyed 44adee82ec Update dependency net.spy:spymemcached to v2.12.3 (#271)
Update dependency net.spy:spymemcached to v2.12.3
2019-04-30 04:11:21 -07:00
Misagh Moayyed 97632483aa Update dependency org.apache.maven.plugins:maven-assembly-plugin to v2.6 (#272)
Update dependency org.apache.maven.plugins:maven-assembly-plugin to v2.6
2019-04-30 04:11:12 -07:00
Misagh Moayyed 2362481941 Update dependency log4j:log4j to v1.2.17 (#269)
Update dependency log4j:log4j to v1.2.17
2019-04-30 04:10:59 -07:00
Renovate Bot 733ce5ba5d Update dependency org.apache.maven.plugins:maven-assembly-plugin to v2.6 2019-04-30 10:51:11 +00:00
Renovate Bot 66742817cc Update dependency net.spy:spymemcached to v2.12.3 2019-04-30 10:51:01 +00:00
Renovate Bot 0e333ec040 Update dependency log4j:log4j to v1.2.17 2019-04-30 09:39:34 +00:00
Misagh Moayyed a09641b184 Update dependency commons-codec:commons-codec to v1.12 (#265)
Update dependency commons-codec:commons-codec to v1.12
2019-04-30 01:02:18 -07:00
Renovate Bot 28ffa12548 Update dependency commons-codec:commons-codec to v1.12 2019-04-30 07:46:54 +00:00
Misagh Moayyed f6f20da863 Merge pull request #262 from kmnasir/jackson-patch
Updating jackson version to 2.9.8
2019-04-30 00:46:38 -07:00
Misagh Moayyed 22e77d2d12 Configure Renovate (#263)
Configure Renovate
2019-04-30 00:46:23 -07:00
Renovate Bot 93dac9b3fe Add renovate.json 2019-04-30 07:43:52 +00:00
Misagh Moayyed db0b8f8a42 Merge pull request #261 from kberzinch/master
Add login attempt events to Atlassian integration
2019-04-11 01:16:55 -07:00
Kristaps Berzinch 1c5dee3edf Add login attempt events 2019-04-11 00:51:45 -04:00
LELEU Jérôme abacb75df2 Handle encrypted PGTs (#260)
* Handle encrypted PGTs

* add tests

* stick to Java 6 and use commons-codec for Base64

* Remove the encrypted PGT after a PGT has been retrieved

* use Bouncycastle to load PEM files

* update to latest BC dependency
2019-04-03 13:53:09 +02:00
LELEU Jérôme 96f51465a8 Merge pull request #259 from leleuj/method
Support the method parameter
2019-03-14 19:11:02 +01:00
Jérôme LELEU 58de00e34b Support the method parameter 2019-03-13 09:15:07 +01:00
Hal Deadman 8cc5ad182c Merge pull request #255 from apereo/hdeadman-patch-1
Update README.md
2019-02-01 17:24:44 -05:00
Hal Deadman e3f532acde Update README.md
Add required serverName init parameter to example for Cas10TicketValidationFilter
2019-02-01 17:22:11 -05:00
Misagh Moayyed 86b93cbb26 clean up 2019-01-31 01:43:33 -07:00
Misagh Moayyed cc756cb72d update readme; add full-regex 2019-01-31 01:39:55 -07:00
Misagh Moayyed e2798c09cb Merge pull request #253 from apereo/inlined-attributes
Extract inlined CAS attributes in protocol 3 Ticket Validator
2019-01-29 23:12:07 +03:30
tsschmidt f06895bc18 Refactored and added unit test. 2019-01-24 16:31:54 -08:00
tsschmidt 18d981efaa Refactor 2019-01-23 10:24:01 -08:00
tsschmidt 080405b4c0 Extract inlined CAS attributes in protocol 3 Ticket Validator 2019-01-23 08:26:35 -08:00
Misagh Moayyed 45d4180a7f Merge pull request #252 from alterdego/master
Fixed typos in README.md
2019-01-14 06:53:40 -06:00
Document Doctor 77c013b03b Fixed typos in README.md 2019-01-12 01:18:14 -05:00
Document Doctor 7513f94877 Fixed typos in README.md 2019-01-11 21:42:00 -05:00
Cliff Ingham 2b1b7a142a Prioritize X-Forwarded-Host when choosing the service parameter
Use X-Forwarded-Host whenever it's available.
2018-12-14 16:28:55 -05:00
Dmitriy Kopylenko ba50664582 [maven-release-plugin] prepare for next development iteration 2018-11-01 10:32:59 -04:00
Dmitriy Kopylenko bafe64e7cd [maven-release-plugin] prepare release cas-client-3.5.1 2018-11-01 10:32:53 -04:00
Misagh Moayyed b2e1643893 Update pom.xml 2018-10-20 23:08:22 +03:30
Misagh Moayyed e155261a6b Merge pull request #248 from SmithJosh/respect-path-in-servername-config
Include serverName path when constructing service url
2018-10-10 09:52:17 +03:30
Joshua Smith c39735729d Include serverName path when constructing service url
Commit be2a641 introduced a bug which overwrites the serverName path component
when constructing service urls. This makes it impossible to deploy a CAS-
protected application behind a reverse proxy with a path prefix.

Now, the path from the incoming request is appended to the serverName path
instead of overwriting it.
2018-10-02 13:29:30 -07:00
Misagh Moayyed 2a570b26f1 Merge pull request #239 from mattdrees/issue-210-preserve-entity-stream-for-non-logout-requests
Add option to prevent entity stream consumption
2018-07-25 23:47:05 +04:30
Matt Drees 1d4312b64f Rename logoutPath to logoutCallbackPath 2018-07-25 13:07:29 -06:00
Misagh Moayyed af78b8703f Merge branch 'master' into issue-210-preserve-entity-stream-for-non-logout-requests 2018-07-25 10:25:51 +04:30
Misagh Moayyed 0e943179f1 Merge pull request #241 from mattdrees/support-prefix-config-for-authentication-filter
Support casServerUrlPrefix config option for AuthenticationFilter
2018-07-25 10:24:35 +04:30
Matt Drees 72e9aa9378 Tweak logoutPath docs 2018-07-24 16:08:48 -06:00
Matt Drees c5d1b1ef84 Stop using "matches" terminology 2018-07-24 16:07:44 -06:00
Matt Drees 40dcc8b34a Move utility method to CommonUtils 2018-07-24 15:19:01 -06:00
Matt Drees ba5982e1eb Add option to prevent entity stream consumption
If someone's app cannot handle the SingleSignOutFilter's consumption of entity streams
(via a `request.getParameter()` call) on all requests,
they can use this option in conjunction with setting up a service logout URL at the CAS server.
The filter will now only consume the stream on requests to this path.

Fixes https://github.com/apereo/java-cas-client/issues/210.
2018-07-24 15:19:00 -06:00
Matt Drees b6f6b5de76 Support casServerUrlPrefix config option
`casServerUrlPrefix` is used for validation and single logout,
but before this commit it couldn't be used by the auth filter.
As a result, web.xml needed to (for the typical usecase)
contain at least two references to the cas server.

Now, only one context init-param reference is necessary,
as long as the login page is hosted at {prefix}/login
(which seems to be mandated by cas protocol spec).
2018-07-24 15:18:24 -06:00
Misagh Moayyed 93561a297f Merge pull request #178 from jalios/master
Fix #177 Every other request incorrectly gatewayed
2018-07-25 00:24:13 +04:30
Misagh Moayyed c979e64006 Merge pull request #240 from mattdrees/fix-race-condition-in-http-server-tests
Fix race condition in PublicTestHttpServer tests
2018-07-25 00:22:57 +04:30
Matt Drees 306ec75569 Fix race condition in PublicTestHttpServer tests
The previous code assumed the server would start listening on the socket before tests ran, but didn't enforce this.
2018-07-24 11:29:25 -06:00
Misagh Moayyed a061764ca1 fix tests 2018-07-17 11:50:10 +04:30
Misagh Moayyed 7fbac753ee fix tests 2018-07-17 11:42:41 +04:30
Misagh Moayyed 15100f3c39 fix tests; adjust log levels for tests 2018-07-17 11:33:03 +04:30
Misagh Moayyed 87ac085dfd Rename stale.yml to .github/stale.yml 2018-07-17 11:08:37 +04:30
Misagh Moayyed a34a397a68 Create stale.yml 2018-06-08 10:48:49 -07:00
kmnasir 94b23a7f2d Updating jackson version to 2.9.5
Due to following vulnerabilities
CVE-2017-15095
CVE-2017-17485
CVE-2018-7489
2018-05-31 12:03:47 -04:00
Misagh Moayyed c015e226ba Merge pull request #231 from Unicon/urlenc-queryparams
Handle un-encoded query strings in url parameters as embedded query strings
2018-03-08 15:58:35 +01:00
Misagh Moayyed 5d18b34159 Update .travis.yml 2018-02-02 20:15:20 +01:00
Misagh Moayyed ae50749c5f Update .travis.yml 2018-01-31 21:48:55 +03:30
Misagh Moayyed 3875c39a21 handle un-encoded query strings in url parameters 2018-01-31 14:11:00 +03:30
Dmitriy Kopylenko b208e94b93 [maven-release-plugin] prepare for next development iteration 2018-01-12 11:56:32 -05:00
Dmitriy Kopylenko c00da6bb81 [maven-release-plugin] prepare release cas-client-3.5.0 2018-01-12 11:56:28 -05:00
Dmitriy Kopylenko 486aa66587 prepare for the release 2018-01-12 11:46:12 -05:00
Dmitriy Kopylenko 527f60f334 Polishing 2018-01-11 10:41:28 -05:00
Misagh Moayyed c06facd9e1 Merge pull request #209 from tkd-yas/master
Fix missing parameter key in service url (#208)
2017-10-06 04:31:21 -07:00
Misagh Moayyed 962c8185ae Merge pull request #220 from mmoayyed/tomcat85x
Add support for tomcat 8.5.x
2017-10-06 04:30:25 -07:00
Misagh Moayyed 6280319d80 Fix travis URLs: point to apereo rather than jasig 2017-07-11 16:58:14 -07:00
Misagh Moayyed 2d6b80842b updated docs 2017-07-06 14:06:24 -07:00
Misagh Moayyed b8f2e0a32c Add support for tomcat 8.5.x 2017-07-06 14:01:21 -07:00
Scott 47efae9e92 Merge pull request #213 from lxbzmy/patch-1
Add JIRA Rest API support
2017-06-21 23:20:17 -04:00
Misagh Moayyed ef2baa8983 Fixed logging issue; returning null in case principal cannot be determined 2017-06-20 09:21:04 -07:00
Misagh Moayyed 9d57eb3655 Merge pull request #188 from eghm/master
Log an error message if CAS principal has no corresponding Confluence principal
2017-06-20 09:18:46 -07:00
Misagh Moayyed f341f50cd5 Merge pull request #212 from mmoayyed/json-validator
New Json ticket validator to accept CAS responses in JSON.
2017-06-20 09:16:37 -07:00
Scott 52edf95202 Merge pull request #214 from hdeadman/master
Improve error logging when getting response from CAS server fails
2017-06-02 12:38:55 -04:00
Hal Deadman f9202b9a8a Improve error logging when getting response fails 2017-06-02 10:59:16 -04:00
Misagh Moayyed b02a122e9d Merge pull request #156 from joeschweitzer/master
Return existing user if session is already authenticated
2017-06-01 21:06:42 -04:00
Misagh Moayyed ccf8e718b2 Apply changes after code review by @serac 2017-06-01 21:03:51 -04:00
Alex Lei 雷 91dd394a08 Add JIRA Rest API support
new JIRA 6 has rest api begin with url /rest when I use cas authentication filter which skip filter /rest ,there will be thrown exception:

java.lang.NullPointerException
    at com.atlassian.jira.security.login.JiraSeraphAuthenticator.getUserFromBasicAuthentication(JiraSeraphAuthenticator.java:149) 
    at com.atlassian.seraph.auth.DefaultAuthenticator.getUser(DefaultAuthenticator.java:339) [atlassian-seraph-3.0.3.jar:?]
    at org.jasig.cas.client.integration.atlassian.Jira44CasAuthenticator.getUser(Jira44CasAuthenticator.java:76) [cas-client-integration-atlassian-3.4.1.jar:3.4.1] 
    at com.atlassian.seraph.auth.AbstractAuthenticator.getUser(AbstractAuthenticator.java:45) [atlassian-seraph-3.0.3.jar:?]
    at com.atlassian.seraph.filter.BaseLoginFilter$SecurityHttpRequestWrapper.getUserPrincipal(BaseLoginFilter.java:238) [atlassian-seraph-3.0.3.jar:?]
    at com.atlassian.seraph.filter.BaseLoginFilter$SecurityHttpRequestWrapper.getRemoteUser(BaseLoginFilter.java:225) [atlassian-seraph-3.0.3.jar:?]
    at javax.servlet.http.HttpServletRequestWrapper.getRemoteUser(HttpServletRequestWrapper.java:168) [servlet-api.jar:?]
    at com.atlassian.jira.web.filters.accesslog.AccessLogFilter.preFilterCallStep(AccessLogFilter.java:175) [classes/:?]
    at com.atlassian.jira.web.filters.accesslog.AccessLogFilter.executeRequest(AccessLogFilter.java:86) [classes/:?]
    at com.atlassian.jira.web.filters.accesslog.AccessLogFilter.doFilter(AccessLogFilter.java:78) [classes/:?]

After hard debug work I found key program flow different from default authenitcator  :

in `com.atlassian.seraph.filter.BaseLoginFilter#SecurityHttpRequestWrapper#getUserPrincipal()`

public Principal getUserPrincipal() {
            return BaseLoginFilter.this.getAuthenticator().getClass().isAnnotationPresent(AuthenticationContextAwareAuthenticator.class)?BaseLoginFilter.this.getAuthenticationContext().getUser():BaseLoginFilter.this.getAuthenticator().getUser(this.delegateHttpServletRequest);
        }

The `AuthenticationContextAwareAuthenticator` annotation cause different flow.

So, add `AuthenticationContextAwareAuthenticator` annotation can slow problem.
2017-05-27 11:13:09 +08:00
Misagh Moayyed 6468166c40 Merge pull request #124 from leleuj/casc-121
Upgrade to Java 6
2017-05-24 09:23:51 -04:00
leleuj 6f84cc2356 merge with master 2017-05-24 08:36:57 +02:00
Misagh Moayyed f5a0ee6987 Merge pull request #187 from Unicon/Frontchannel-slo
Handle front-channel SLO
2017-05-22 12:25:15 -04:00
Misagh Moayyed e56e0d2aa0 Exclude transaction dependency 2017-05-22 09:19:54 -07:00
Misagh Moayyed dfb13e5397 add test cases 2017-05-18 14:09:11 -07:00
Misagh Moayyed 552b9f9fac Fix test cases with attribute encoding 2017-05-18 12:31:44 -07:00
Misagh Moayyed 1e1a0ec5e8 update readme 2017-05-17 16:50:13 -07:00
Misagh Moayyed 24f1f9c814 clean up JIRA dependencies so project can compile 2017-05-17 16:42:09 -07:00
Misagh Moayyed 059ec7d527 clean up JIRA dependencies so project can compile 2017-05-17 16:31:50 -07:00
Misagh Moayyed f2ea4129bd allow extension points for JSON validation parsing. add filter and validator 2017-05-17 16:13:46 -07:00
Misagh Moayyed 88789ef358 allow extension points for JSON validation parsing. add filter and validator 2017-05-17 16:00:24 -07:00
Misagh Moayyed 5152f40be9 allow extension points for JSON validation parsing. add filter and validator 2017-05-17 15:59:20 -07:00
Misagh Moayyed 1fc896c458 allow extension points for JSON validation parsing. add filter and validator 2017-05-17 15:04:42 -07:00
Misagh Moayyed 1561da75ad Fix formatting issues with the markdown title 2017-04-25 09:28:10 -07:00
Yasuhiro Takada 834531c7a6 fix test faiiure 2017-04-17 20:36:40 +09:00
Yasuhiro Takada 2f7729a892 fix missing parameter key in service url when parameter value not provided. 2017-04-17 19:22:41 +09:00
Misagh Moayyed f998bb07c3 Merge pull request #200 from zhixiangli/master
add setter to ignoreUrlPatternMatcherStrategyClass
2017-01-05 19:29:56 +03:30
lizhixiang 47fb9c0fbb add setter to ignoreUrlPatternMatcherStrategyClass, with purpose of
injecting UrlPatternMatcherStrategy to AuthenticationFilter by Spring
IOC
2017-01-05 12:16:16 +08:00
Misagh Moayyed 4d1d62bd62 Merge pull request #184 from Unicon/Skew-assertion-date
Handle date equality when checking for assertion validity
2016-09-23 10:24:02 +03:30
eghm bad68332a6 Use parameterized log statement when logging CAS only principle. 2016-09-19 10:14:22 -10:00
eghm 2ae54e8d98 Log an error message if CAS principle has no corresponding Confluence principle. 2016-09-15 13:57:11 -10:00
Misagh Moayyed 6be07281d5 Fixed test cases 2016-09-09 16:22:32 +04:30
Misagh Moayyed 7db200e8c6 Updated front-channel SLO handling 2016-09-09 16:14:06 +04:30
Misagh Moayyed 527f0c6d28 Merge pull request #181 from Unicon/Tostring
Let ConfigurationKey toString() the name
2016-09-07 20:53:38 +04:30
Misagh Moayyed 7d5a9bc124 Merge pull request #185 from Unicon/Redundant-GroupId
Remove redundant groupId from POM defns
2016-09-07 20:53:21 +04:30
Misagh Moayyed 92371f794a Remove redundant groupId from POM defns 2016-09-07 16:12:34 +04:30
Misagh Moayyed 9e95ee5825 Handle date equality when checking for saml assertion validity 2016-09-07 16:10:16 +04:30
Scott 86a8f7395b Merge pull request #182 from Unicon/Refact
Minor code adjustments to CommonUtils to use String.isEmpty()
2016-09-07 07:30:43 -04:00
Misagh Moayyed 9d4cafd2c9 Let assertion validity checks to be more flexible
when comparing dates.
2016-09-07 15:47:04 +04:30
Misagh Moayyed 745fda6113 Minor code adjustments to CommonUtils to use String.isEmpty() 2016-09-07 15:38:46 +04:30
Misagh Moayyed aa6cab7d8d Merge pull request #180 from serac/logpt
Log proxy ticket returned from /proxy protocol endpoint.
2016-09-07 15:32:49 +04:30
Misagh Moayyed 9b71825e1a Let config keys log the name 2016-09-07 15:31:39 +04:30
Marvin S. Addison 2e27e09f3b Log proxy ticket returned from /proxy protocol endpoint. 2016-09-01 13:22:01 -04:00
Olivier Jaquemet b4d9570bdc Fix #177 Every other request incorrectly gatewayed
- ensure behavior of gateway is predictable (reentrant)
2016-08-09 10:27:27 +02:00
Marvin S. Addison 7cb5380e75 Issue #152 Jetty integration docs. 2016-05-24 07:53:15 -04:00
Scott e7292c78a0 Merge pull request #167 from geojs/issue-167
Wrong Maven groupId in README.md for Components
2016-05-16 12:54:07 -04:00
cobolgis 771288475f Recommended fix for #167. 2016-05-16 16:04:12 +02:00
Misagh Moayyed ee4a05d409 Merge pull request #166 from ceharris/patch-1
change git clone URL in README to reflect new org slug
2016-05-13 09:04:00 -07:00
Carl Harris f1cd2441ca change git clone URL to reflect new org slug 2016-05-13 11:03:11 -04:00
Scott 95c5d8ee73 Merge pull request #158 from BernhardLenz/cas-client-integration-tomcat-v8
Added Tomcat client v8 to readme and notice files
2016-04-01 00:05:51 -04:00
BernhardLenz f1908ba5fc Added Tomcat client v8 to readme and notice files 2016-03-28 09:02:46 -04:00
Joe Schweitzer 8e1a7789b1 Return existing user if session is already authenticated 2016-03-17 12:03:11 -04:00
Scott b20d4d241c Merge pull request #153 from serac/jetty
CAS Jetty Container Authentication Support
2016-03-08 07:20:51 -05:00
Marvin S. Addison bc586d7b4b Merge branch 'master' into jetty 2016-03-08 07:15:22 -05:00
Marvin S. Addison 06b566e2d6 Issue #152 Simplify ticket lookup. 2016-03-07 07:51:25 -05:00
Marvin S. Addison 3f0a1c6883 Issue #152 Fix javadoc typo. 2016-03-07 07:45:50 -05:00
Marvin S. Addison 812198b6a5 Issue #152 Use CommonUtils for null checks. 2016-03-07 07:45:26 -05:00
Scott 88d847102c Merge pull request #151 from BernhardLenz/cas-client-integration-tomcat-v8
Added cas-client-integration-tomcat-v8
2016-03-04 21:52:20 -05:00
Marvin S. Addison 40291a4478 Issue #152 Log authentication success at INFO. 2016-02-19 10:43:15 -05:00
Marvin S. Addison 184868b296 Issue #152 Add working Jetty context config files. 2016-02-12 16:40:05 -05:00
Marvin S. Addison 5a68c92268 Issue #152 Prevent dupe ticket validations.
The ticket parameter can linger in the URL after authentication.
Don't attempt ticket validation if we are already authenticated.
Fixes ticket validation failures on refresh and similar cases.
2016-02-12 16:20:56 -05:00
Marvin S. Addison f09ee1c0e7 Issue #152 Fix multiple ticket validation attempt. 2016-02-12 15:34:19 -05:00
Marvin S. Addison 971d4b4854 Issue #152 Remove unused jetty-maven-plugin. 2016-02-11 15:12:39 -05:00
Marvin S. Addison f04dedd9bb Issue #152 Use WeakReference to avoid resource leak.
We don't want to hold a reference to HttpSession objects in the
ticket-to-session mapping that would prevent orphaned or expired sessions
from being purged. WeakReference ensures that won't happen.
2016-02-11 15:08:00 -05:00
Marvin S. Addison 53dbb48882 Issue #152 Jetty container-based authn. 2016-02-11 14:53:14 -05:00
BernhardLenz 61bd0eeb86 Added cas-client-integration-tomcat-v8 2016-02-04 18:45:03 -05:00
Scott e4b767700a Merge pull request #143 from battags/CASC-127
CASC-127 Remove Commons Codec Dependency
2015-11-19 21:02:57 -05:00
Scott 346374ebc8 CASC-127 Remove Commons Codec Dependency
Problem: We rely on Commons Codec for some simple Base64 decoding/encoding, most of which is available in Java 1.6+
Solution: Set minimum version to Java 1.6 and rely on provided methods.

QA Notes: Unit tests pass
2015-11-18 21:58:06 -05:00
Misagh Moayyed 4b63e06418 updated docs on SSOFilter and ErrorRedirectFilter 2015-11-08 13:54:31 -07:00
Misagh Moayyed 32963967d4 updated docs on SSOFilter and ErrorRedirectFilter 2015-11-08 13:53:33 -07:00
Scott 9d9e5cad72 Merge pull request #142 from serac/issue-141-remove-content-length
Issue-141 Remove redundant Content-Length header.
2015-11-05 20:43:56 -05:00
Marvin S. Addison 598fb02dda Issue-141 Remove redundant Content-Length header. 2015-11-05 16:44:05 -05:00
Misagh Moayyed a417f78521 Fix badge link for maven version 2015-09-13 08:16:18 -07:00
Scott a5e2b8ae61 [maven-release-plugin] prepare for next development iteration 2015-09-13 00:23:55 -04:00
Scott 650cee05bc [maven-release-plugin] prepare release cas-client-3.4.1 2015-09-13 00:19:52 -04:00
Scott e5f933754b [maven-release-plugin] rollback the release of cas-client-3.4.1 2015-09-13 00:18:34 -04:00
Scott 1bdc456bf4 [maven-release-plugin] prepare for next development iteration 2015-09-13 00:13:20 -04:00
Scott 8067714256 Added missing license headers. 2015-09-13 00:11:09 -04:00
Scott 85b0454e8d Merge pull request #133 from battags/131
Issue #131 - ConfigurationStrategyName does not Properly Resolve Cust…
2015-09-10 09:27:08 -04:00
Scott 2eb132c0b4 Issue #131 - ConfigurationStrategyName does not Properly Resolve Custom classes
Problem: The assignable check was reversed, always resulting in a false return value.
Solution: Add test to confirm failure and then swap check.  Unit tests pass.
2015-09-09 23:30:53 -04:00
Scott 0022c622e1 Merge pull request #130 from mmoayyed/serviceurl-construction-method
Overload constructServiceUrl to keep backward compatibility
2015-08-19 22:28:58 -04:00
Misagh Moayyed ab105cdcfa initialize service parameter names once, statically 2015-08-19 08:51:28 -07:00
Misagh Moayyed 1f3a745ec8 overload constructServiceUrl to keep backward compatibility 2015-08-19 02:28:20 -07:00
Scott ba47157062 Merge pull request #128 from mmoayyed/uribuilder-tests
URIBuilder test cases
2015-08-13 07:37:08 -04:00
Misagh Moayyed 4f746b3b58 Update .travis.yml 2015-08-13 03:00:26 -07:00
Misagh Moayyed d7538dfd61 Update .travis.yml 2015-08-13 02:59:36 -07:00
LELEU Jérôme 335d3f3a3e Update .travis.yml 2015-08-13 11:36:24 +02:00
Misagh Moayyed 618a99a245 URIBuilder test cases 2015-08-12 12:36:50 -07:00
LELEU Jérôme 0d2740ec0c Merge pull request #125 from xuhuisheng/master
URIBuilder throws UnsupportedOperationException on adding/setting parameters
2015-08-10 10:35:13 +02:00
Xu Huisheng 69bba0c21a When serverName contains schema, the URIBuilder will throw an UnsupportedOperationException while adding a parameter. 2015-08-04 18:20:31 +08:00
Jérôme LELEU f0047eb8eb upgrade version to 3.5.0-SNAPSHOT 2015-08-03 12:53:19 +02:00
Jérôme LELEU 60b8ad70f8 Upgrade to Java 6 2015-07-31 17:02:21 +02:00
LELEU Jérôme d46e3c6220 Merge pull request #122 from leleuj/casc-119
Deploy SNAPSHOTs to Sonatype
2015-07-31 10:37:29 +02:00
Jérôme LELEU 8ff374b949 Revert "using the old Travis infrastructure (no container)"
This reverts commit ce06a4fd91.
2015-07-30 11:23:47 +02:00
Jérôme LELEU e9b79194d7 using the old Travis infrastructure (no container) 2015-07-30 11:05:12 +02:00
LELEU Jérôme 72685767f7 Merge pull request #123 from leleuj/casc-120
Update README with 3.4 features
2015-07-29 11:13:52 +02:00
Jérôme LELEU bb11bfa7c8 Update README with 3.4 features 2015-07-28 09:29:27 +02:00
Jérôme LELEU bdecba6431 Deploy SNAPSHOTs to Sonatype 2015-07-28 08:42:33 +02:00
Scott 67b4b26819 [maven-release-plugin] prepare for next development iteration 2015-07-21 22:57:28 -04:00
Scott f3d7156482 [maven-release-plugin] prepare release cas-client-3.4.0 2015-07-21 22:57:26 -04:00
Scott 8bab6d1f4e Fixed licenses 2015-07-21 22:42:41 -04:00
Scott 76ba57a541 Added missing license headers 2015-07-21 22:19:00 -04:00
Scott ec744b2c9f Updated NOTICE generation. 2015-07-21 22:16:53 -04:00
Misagh Moayyed 4db9948c19 Moved build to the new travis environment 2015-07-10 08:34:46 -07:00
Scott 0a7ffac846 Merge pull request #66 from Unicon/CASC-210
CASC-210: Added support for having regex expressions in the proxy (chaining) list.
2015-07-07 17:10:05 -04:00
Scott c8e50905bb Merge pull request #116 from Unicon/remove-lang
removed commons-lang dependency
2015-07-03 11:27:00 -04:00
Scott eaee34b361 Merge pull request #105 from mmoayyed/removing-service-param
Added uri builder to construct query params
2015-07-03 11:13:31 -04:00
Scott 6ce10daea0 Merge pull request #117 from lathspell/master
Add filter-mapping to web.xml filter examples
2015-07-03 09:22:29 -04:00
John Gasper f98e776869 casc-210: Merge branch 'master' of https://github.com/jasig/java-cas-client into CASC-210
Resolved Conflicts:
	cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java
2015-06-16 12:09:37 -07:00
Christian Brunotte df07758a89 missing "<" in example 2015-06-16 19:30:49 +02:00
Christian Brunotte 302822f361 Added <filter-mapping> to all web.xml <filter> examples. 2015-06-16 19:29:16 +02:00
Misagh Moayyed e1e12a5f3f removed since tags 2015-06-10 20:09:15 -07:00
Misagh Moayyed 8c77fc4eaf removed commons-lang dep 2015-06-10 20:04:12 -07:00
Scott 607d53a2aa Merge pull request #113 from Unicon/commons-lang3
Upgrade to commons-lang3
2015-06-08 22:56:07 -04:00
Misagh Moayyed 70b8aa8032 Merge pull request #112 from Unicon/depc-const
Deprecated unused DISABLE_XML_SCHEMA_VALIDATION
2015-06-07 20:48:35 -07:00
Misagh Moayyed 806672e525 Merge pull request #114 from Unicon/proxying-log-warn
Added additional logs to proxy validation
2015-06-07 20:48:26 -07:00
Misagh Moayyed 853450a8a6 added additional logs to proxy validation 2015-06-07 17:05:47 -07:00
Misagh Moayyed 05873137dc Update README.md 2015-06-07 13:29:05 -07:00
Misagh Moayyed 8bc89e648a Create .travis.yml 2015-06-07 13:27:32 -07:00
Misagh Moayyed f1ac21943d upgrade to commons-lang3 v3.4 2015-06-07 13:24:12 -07:00
Misagh Moayyed c6c106c375 deprecated unused const 2015-06-07 13:18:19 -07:00
Misagh Moayyed 0a6ce18150 updated param building 2015-06-05 15:17:04 -07:00
Misagh Moayyed 73e2a63a5b Merge branch 'master' into removing-service-param 2015-06-05 15:14:29 -07:00
Misagh Moayyed 77e5340c3c Update README.md 2015-05-24 18:59:20 +04:00
Misagh Moayyed 573976cda9 Update README.md 2015-05-23 23:09:30 +04:00
Misagh Moayyed dc028a6652 Update README.md 2015-05-23 23:08:50 +04:00
Misagh Moayyed 50fc28034d Update README.md 2015-05-23 22:50:52 +04:00
Misagh Moayyed 3c40922847 Update README.md 2015-05-23 22:50:09 +04:00
Misagh Moayyed d72913b53a Update README.md 2015-05-23 22:01:48 +04:00
Misagh Moayyed a31979920b Update README.md 2015-05-23 21:50:09 +04:00
Misagh Moayyed 8ec71aa2c6 Update README.md 2015-05-23 16:41:15 +04:00
Misagh Moayyed 74f0a209dd Update README.md 2015-05-23 16:40:15 +04:00
Misagh Moayyed f8f5b908d0 Create README.md 2015-05-23 02:46:17 +04:00
Misagh Moayyed d3ba9c0ae7 Delete README.txt 2015-05-23 02:45:28 +04:00
Misagh Moayyed f68281d0e4 added uri builder to construct query params 2015-05-13 03:44:13 -07:00
Marvin S. Addison 863038605f Merge pull request #101 from Jasig/no-opensaml
Remove OpenSAML and consolidate SAML components in support module
2015-05-12 09:29:02 -04:00
Marvin S. Addison f5b2275913 Issue #100 Bump minor version due to refactoring. 2015-05-11 12:09:00 -04:00
Marvin S. Addison 1edef62ecb Issue #100 Isolate JodaTime to SAML module. 2015-05-11 12:01:48 -04:00
Marvin S. Addison 7c58629958 Issue 100 Restore configuration key for backward compatibility. 2015-05-04 16:10:56 -04:00
Marvin S. Addison 70ed5fd8bb Add Marvin to SAML validator component authorship. 2015-05-04 16:07:47 -04:00
Marvin S. Addison 6e261e7251 Issue #100 Respond to code review feedback. 2015-04-20 10:34:28 -04:00
Scott 0652f4ee23 Merge pull request #93 from leleuj/CASC-217
CASC-217: Update the ticket validators to point to the new endpoint
2015-04-20 06:54:48 -04:00
Marvin S. Addison d8980535b7 Move SAML components into separate module. 2015-04-14 16:19:12 -04:00
Marvin S. Addison dd0818b84f Fix @since version. 2015-02-20 10:35:05 -05:00
Marvin S. Addison 4527671568 Sensible XPath processing optimizations. 2015-02-20 10:26:01 -05:00
Marvin S. Addison e998985732 SAML validation with XPath instead of OpenSAML. 2015-02-20 09:18:05 -05:00
Scott 6f7fe61780 Merge pull request #97 from battags/CASC-239
CASC-239 Saml11AuthenticationFilter Constructor was Private instead of Public
2015-01-25 19:11:28 -05:00
Scott db3610123f CASC-239 Saml11AuthenticationFilter Constructor was Private instead of Public. 2015-01-24 23:58:51 -05:00
Scott 380585d391 Merge pull request #96 from Jasig/conditional-opensaml-init
CASC-237 Make OpenSAML bootstrap conditional.
2015-01-20 08:34:08 -05:00
Marvin S. Addison 4aef368057 CASC-237 Make OpenSAML bootstrap conditional. 2015-01-17 11:25:03 -05:00
Scott 6de80009cf Merge pull request #94 from leleuj/casc-91
Issue-91: Introduce system properties configuration option
2015-01-07 08:48:41 -05:00
LELEU Jerome bec0e6bb2e Issue-91: Introduce system properties configuration option
First commit
2015-01-05 17:19:40 +01:00
LELEU Jerome 2a98556daa CASC-217: Update the ticket validators to point to the new endpoint
First commit
2015-01-05 15:55:33 +01:00
Scott f49c08ce93 Merge pull request #88 from battags/CASC-231
CASC-231 HttpsURLConnectonFactory is Not Serializable
2014-12-22 23:56:48 -05:00
Scott ec92d97518 Added license headers 2014-12-22 23:55:23 -05:00
Scott 34458db530 Merge branch 'master' into CASC-231 2014-12-22 23:54:46 -05:00
Scott 0b220c6f55 Merge pull request #89 from battags/CASC-200
CASC-200 Introduce Properties File Configuration Option
2014-12-22 22:10:50 -05:00
Scott 39f0f29dd9 CASC-200 Introduce Properties File Configuration Option
Problem: We can configure via JNDI, WebXML (or both) but not by properties file.
Solution: Introduce a method to use property files.
2014-12-07 14:14:08 -05:00
Scott d1da02f457 CASC-231 HttpsURLConnectonFactory is Not Serializable
Problem: THe HttpsURLConnectionFactory is not serializable, causing problems for clients that must serialize
the principal (which depends on a ProxyRetriever).

Solution: Make the HttpsURLConnectionFactory serializable.

QA Notes: added unit test to confirm serialize-deserialize
2014-12-07 13:32:14 -05:00
Scott d7ca6a098e Merge pull request #87 from battags/CASC-233
CASC-233 ErrorRedirectFilter Can throw Null Pointer Exception
2014-12-07 12:13:27 -05:00
Scott f17c4d6087 Merge pull request #86 from battags/CASC-200-rebasefail
CASC-200 Introduce Mechanism to Indicate Method of Configuration
2014-12-07 12:12:56 -05:00
Scott a780e39ab9 Merge branch 'master' into CASC-200-rebasefail
Conflicts:
	cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java
2014-12-07 12:11:42 -05:00
Scott Battaglia bef2a88603 Updated try/catch loop to log when a class is not found. 2014-11-30 17:09:09 -05:00
Scott Battaglia 3af5683dc1 Addressed formatting feedback as well as reserved keywords. 2014-11-26 22:58:12 -05:00
Scott Battaglia 5109132df3 Per feedback, scoped catch block to Exception instead of Throwable 2014-11-26 22:31:01 -05:00
Scott Battaglia 51a9192792 CASC-233 ErrorRedirectFilter Can throw Null Pointer Exception
Problem: the ErrorRedirectFilter assumes there is a root cause and will null pointer if there is not.
Solution: Only use the root cause if there is one, otherwise use the original exception.

QA Notes: Added unit test to confirm non-root cause error.
2014-11-20 16:29:29 -05:00
Scott Battaglia c7e66d7df2 Unused reference to Mockito 2014-11-20 16:03:19 -05:00
Scott Battaglia d011f5e64a Removed unused mockito dependency 2014-11-20 16:01:02 -05:00
Scott Battaglia 17f887595f Added missing javadoc for Protocol enumeration 2014-11-20 15:58:52 -05:00
Scott Battaglia 324b0919b6 Added additional keys that were new from the single signout refactor. 2014-11-20 15:31:31 -05:00
Scott Battaglia 461cdcd8fc CASC-200 Create a ConfigurationStrategy to allow for pluggable configurations.
Problem: The lookup strategy for configuration is hard-coded into the filter, making it impossible to replace or expand.
Solution: Pull the strategies into their own classees and make it configurable.  Default to the previous strategy.

QA Notes: The current unit tests work.  New unit tests for the configuration will have to be added once the design is approved.
2014-11-20 15:30:38 -05:00
Marvin S. Addison 4e3f761efe [maven-release-plugin] prepare for next development iteration 2014-08-15 08:52:01 -04:00
Marvin S. Addison 0174cfbbb5 [maven-release-plugin] prepare release cas-client-3.3.3 2014-08-15 08:51:04 -04:00
Marvin S. Addison f57f0ff096 Update notice files. 2014-08-15 08:48:05 -04:00
Scott 117f32006f Merge pull request #79 from battags/CASC-229
CASC-229 Make Front Channel SSO Optional so that backwards compatibility...
2014-08-13 10:13:45 -04:00
Scott db53818de7 Merge pull request #80 from battags/CASC-230
CASC-230 Call HttpServletRequest#logout() via Reflection to Improve Back...
2014-08-13 10:13:28 -04:00
Scott ecef8dd722 Merge pull request #78 from battags/CASC-225
CASC-225 Restore Removed Constructor for Backwards Compatibility
2014-08-13 10:13:20 -04:00
Scott Battaglia b34c4e104f Updated code to abstract the reflection logic a bit more behind a strategy interface. 2014-08-11 23:04:24 -04:00
Scott Battaglia a0f8845ecf CASC-230 Call HttpServletRequest#logout() via Reflection to Improve Backwards Compatibility with Spring Security 2014-08-11 22:50:23 -04:00
Scott Battaglia b18dbfe0a9 CASC-229 Make Front Channel SSO Optional so that backwards compatibility is maintained.
Problem: Spring Security adopters will fail to be able to drop in a new version of CAS Client for Java if this feature is enabled by default/required.
Solution: Force a fail-safe optional mode if the value is not provided.
2014-08-11 22:36:27 -04:00
Scott Battaglia 42ce676ef0 CASC-225 Restore Removed Constructor for Backwards Compatibility
Problem: We removed the two string constructor which breaks Spring Security compatibility.
Solution: Add it back as deprecated so that Spring Security can upgrade.
2014-08-11 22:09:27 -04:00
Scott Battaglia aa3e07bd79 [maven-release-plugin] prepare for next development iteration 2014-08-03 00:22:49 -04:00
Scott Battaglia 112f068607 [maven-release-plugin] prepare release cas-client-3.3.2 2014-08-03 00:22:14 -04:00
Scott Battaglia d191ac8ee6 Added missing license header. 2014-08-03 00:03:25 -04:00
Scott Battaglia 61a92c0e7f CASC-224 Replace URL with String to remain compatible with Spring Security 2014-07-20 20:31:35 -04:00
Scott 266eba7c2d Merge pull request #73 from battags/CASC-228
CASC-228 URL Encode Paramaters Passed to Server via Validate
2014-06-29 15:11:58 -04:00
Scott Battaglia 9de2be91a2 CASC-228 URL Encode Paramaters Passed to Server via Validate
Problem: We currently don't pass encoded values to the server, possibly resolving in parsing/extraction errors.
Solution: URL Encode all values instead of just the service url.

QA Notes: Added unit test.
2014-06-24 18:44:45 -04:00
Scott 566c8690c8 Merge pull request #72 from battags/CASC-223
CASC-223 Backwards Compatibility for Initializing Sign Out Handler in Filter
2014-05-22 22:03:26 -04:00
Scott aeaa76ce46 Merge pull request #71 from battags/CASC-224
CASC-224 Public API Method Removed without Deprecation
2014-05-12 22:34:01 -04:00
Scott Battaglia a44b4c1229 Removed no-longer valid test. 2014-05-06 23:17:32 -04:00
Scott Battaglia a4e984e4ea Synchronize the init method in case we have multiple concurrent requests at the same time. 2014-05-06 22:53:05 -04:00
Scott Battaglia 2c9090155a CASC-223 SingleSignOutFilter requires init method to be called which changes the contract with previous versions
Problem: Some clients such as Spring Security configure the filter via Spring configuration, meaning the handler's init method
is not called vai the Filter#init method.

Solution: For now, have an atomic boolean to determine if init was called or not and call it if necessary as part of the flow.
2014-05-06 22:35:55 -04:00
Scott Battaglia b4fbf23361 CASC-224 Public API Method Removed without Deprecation
Problem: Previous versions of the CAS Client remove a public API method without sufficient deprecation time resulting in
problems for clients who want to upgrade.

Solution: Add Method back and mark it as deprecated.
2014-05-06 22:12:59 -04:00
John Gasper c61dea96bf Formatting clean-up 2014-04-15 12:56:46 -07:00
John Gasper 99763ab2b6 Using Misagh's PatternMatcherStrategy to optimize proxy chain checks 2014-04-14 08:45:21 -07:00
John Gasper 7ac4c7afb7 Merge branch 'master' of https://github.com/jasig/java-cas-client into CASC-210 2014-04-11 15:17:29 -07:00
LELEU Jérôme 4e7bf66d68 Merge pull request #68 from leleuj/CASC-220
CASC-220: Support front channel SLO logout
2014-04-09 08:10:42 +02:00
Jérôme LELEU c4c3223140 CASC-220: Support front channel SLO logout
Update after new Misagh's comments
2014-04-07 18:54:40 +02:00
LELEU Jerome 4a0e960c32 CASC-220: Support front channel SLO logout
Updates after Marvin's code review
2014-04-01 16:46:19 +02:00
Jérôme LELEU 7069a4f6fb CASC-220: Support front channel SLO logout
Update after Scott's code review
2014-03-27 21:02:30 +01:00
Jérôme LELEU 6aa2379268 CASC-220: Support front channel SLO logout
Updates after Misagh's code review
2014-03-21 14:10:33 +01:00
Scott Battaglia 80f7f3647e [maven-release-plugin] prepare for next development iteration 2014-03-19 20:55:47 -04:00
Scott Battaglia 3373d7f767 [maven-release-plugin] prepare release cas-client-3.3.1 2014-03-19 20:55:38 -04:00
Scott Battaglia 896958337a Updated to parent pom 39 2014-03-19 20:50:45 -04:00
Scott Battaglia 72766daac5 Added in missing license header. 2014-03-18 19:26:45 -04:00
unknown 9714053f07 Merge remote-tracking branch 'upstream/master' into CASC-220 2014-03-18 08:16:29 +01:00
Misagh Moayyed 286105266f Merge pull request #67 from battags/CASC-214
CASC-214 Improve Service Url Construction to Add Non-Standard Ports
2014-03-17 09:15:29 -07:00
Misagh Moayyed f018f54c4c Merge pull request #64 from mmoayyed/CAS-219
CAS-219: Provide support for certain urls to be excluded from CAS filters
2014-03-17 00:21:53 -07:00
Misagh Moayyed ed4802f943 CASC-219: added final 2014-03-17 00:18:56 -07:00
LELEU Jerome 9b33321cc2 CASC-220: Support front channel SLO logout
specific front logout parameter + Tomcat valves update
2014-03-14 10:52:42 +01:00
LELEU Jerome 47f825871e CASC-220: Support front channel SLO logout
First commit
2014-03-13 19:03:41 +01:00
Misagh Moayyed d2b93a237f CASC-219: added exact-matcher strategy 2014-03-13 08:26:22 -07:00
Misagh Moayyed 0a8fd79a44 CASC-219: changed exact to contains 2014-03-13 03:20:39 -07:00
Misagh Moayyed 00ee9e378d CASC-219: renamed matcher class to match behavior 2014-03-12 07:37:59 -07:00
Misagh Moayyed 248643cf30 CASC-219: switched warn to error, fixed typo and this refs 2014-03-11 08:46:00 -07:00
Misagh Moayyed dfb3629dc2 CASC-219: updated internal map to be a static ref instead 2014-03-11 07:11:53 -07:00
Misagh Moayyed 511bce2471 CASC-219: allowed extensions for ignoring urls 2014-03-11 05:04:59 -07:00
Misagh Moayyed 3773fc9e54 CASC-219: updated javadocs and added map to keep track of pattern matchers 2014-03-11 04:24:27 -07:00
Misagh Moayyed b97d03d126 CASC-219: Cleaned up formatting issues 2014-03-10 05:22:44 -07:00
Scott Battaglia a4df6582ee Removed debug statements used to confirm private methods worked. 2014-03-09 23:18:14 -04:00
Scott Battaglia 75584a2c33 CASC-214 Improve Service Url Construction to Add Non-Standard Ports if Missing from Configuration
Problem: sometimes the port is missing from the configuration.  This generates the wrong service url.
Solution: Add the server port if the server configuration does not have one.
QA Notes: Added unit tests to confirm behavior (and old unit tests still pass)
2014-03-09 23:13:04 -04:00
John Gasper 0ef575ae84 Refactored the match logic and cache the regex patterns. 2014-03-07 16:11:00 -08:00
Misagh Moayyed 71b366cbf3 CASC-219: Provide support for certain urls to be excluded from CAS filters. 2014-03-07 11:17:14 -07:00
Misagh Moayyed b9ac92cf25 CASC-219: Provide support for certain urls to be excluded from CAS filters. 2014-03-07 01:52:50 -07:00
John Gasper 887da3bffd no message 2014-03-05 10:54:34 -08:00
John Gasper 90ccc41db3 Minor corrections. 2014-03-05 10:45:35 -08:00
John Gasper 80ff9857f0 Added support for having regex expressions in the proxy (chaining) list. 2014-03-05 10:17:59 -08:00
Misagh Moayyed 44d1413fa7 CAS-219: Provide support for certain urls to be excluded from CAS filters. 2014-03-02 03:03:24 -07:00
Misagh Moayyed c857e4610b CAS-219: Provide support for certain urls to be excluded from CAS filters. 2014-02-27 22:02:19 -07:00
Marvin S. Addison 590a79c6a6 Merge pull request #63 from battags/CASC-203
CASC-203 Properly Parse Response to Keep Line Breaks
2014-02-20 13:49:50 -05:00
Scott Battaglia 36b8db1e86 CASC-203 Properly Parse Response to Keep Line Breaks
Problem: The CAS Client uses a buffer reader which strips out the returned line breaks.
Solution: Switch to a normal input stream reader and add appropriate test.
2014-02-17 23:09:32 -05:00
Scott Battaglia 4d7b2517a9 [maven-release-plugin] prepare for next development iteration 2014-01-07 21:15:06 -05:00
Scott Battaglia 4d12772bc4 [maven-release-plugin] prepare release v3.3.0 2014-01-07 20:37:19 -05:00
Scott Battaglia 8262bc1fff Updated notice and pom 2014-01-07 20:31:34 -05:00
Scott Battaglia a199892c73 Updated notice file 2014-01-07 20:31:24 -05:00
Scott Battaglia 00a507d51b Updated Atlassian Maven Repository location 2014-01-07 20:04:57 -05:00
Scott Battaglia 19e5e0671b Added generated notice files 2014-01-07 20:00:30 -05:00
Scott Battaglia 2a2fc56031 Fixed licensing / exclusions. 2014-01-06 23:51:09 -05:00
Scott Battaglia 89e6bfd521 Fixed license files 2014-01-05 23:04:03 -05:00
Scott Battaglia 6ba3f6f884 Added missing license headers 2014-01-05 22:53:17 -05:00
Scott Battaglia d0d7fd684d Correct license header information. 2014-01-05 22:52:15 -05:00
Scott Battaglia 57d2d66a1d Updated pom.xml to the latest jasig-parent pom (38) 2014-01-05 22:36:38 -05:00
Scott Battaglia fe9dac934a [maven-release-plugin] rollback the release of v3.3.0 2014-01-05 22:06:46 -05:00
Scott Battaglia 577dafef0e Updated to Jasig Parent POM Version 37 and set up correct release version. 2013-12-29 17:17:26 -05:00
Scott Battaglia cef064f34b Updated pom.xml file to jasig-parent-36 2013-12-17 17:35:43 -05:00
Scott b3afc92fc7 Merge pull request #58 from serac/jaas-logout-fix
Destroy cached assertions in CasLoginModule#logout() method
2013-11-12 16:34:27 -08:00
Marvin S. Addison 5b1bd87e7a Put HttpServletRequest#logout() in separate try/catch block. 2013-10-28 16:07:28 -04:00
Marvin S. Addison 82c95aaf19 Respond to code review feedback.
1. Call HttpServletRequest#logout() on SLO callback since it is available.
2. Use final for local variables where possible.
2013-10-28 15:58:40 -04:00
Marvin S. Addison 328692bb40 Remove cached assertions on logout to prevent credential replay attack. 2013-10-24 12:57:25 -04:00
Scott 46416fe741 Merge pull request #57 from h0nIg/memcachedclient
use memcached interface instead of implementation / updated client library
2013-09-02 12:28:52 -07:00
Hans-Joachim Kliemeck 6b50b18d66 changed from provided to compile 2013-09-02 19:37:46 +02:00
Marvin S. Addison 575de47020 Merge pull request #56 from serac/CASC-174
CASC-174 Provide Programmatic JAAS Login Facility for JBoss 7
2013-08-26 04:23:25 -07:00
Hans-Joachim Kliemeck 259afc7a62 updated memcached version 2013-08-17 14:19:42 +02:00
Hans-Joachim Kliemeck b697a4b0ba use interface instead of implementation 2013-08-17 13:45:34 +02:00
Marvin S. Addison 5ce3bcb3d3 CASC-174 Remove @version javadoc tag. 2013-08-15 11:05:32 -04:00
Marvin S. Addison 75406c916e CASC-174 Remove JBoss verbiage from error message. 2013-08-01 14:10:38 -04:00
Marvin S. Addison 517f94bd97 CASC-174 Provide facility for Servlet 3.0 programmatic JAAS login.
Servlet3AuthenticationFilter supersede the JBoss-specific
WebAuthenticationFilter for JBoss 7. It should also provide support for
programmatic JAAS login for any container that is Servlet 3.0/JEE6
compliant.
2013-08-01 14:05:01 -04:00
Scott 526c65fb39 Merge pull request #54 from battags/master
Updated Jasig Parent POM Version
2013-06-26 17:50:14 -07:00
Scott Battaglia adb668d9ed Latest Jasig pom file 2013-06-26 20:48:55 -04:00
Scott 15103333e5 Merge pull request #52 from battags/CASC-211
CASC-211 Better Ticket Validation Error Logic
2013-06-20 16:31:59 -07:00
Scott Battaglia 8ab75b883a Renamed arguments 2013-06-20 19:28:35 -04:00
Scott 4b87b4a9f5 Merge pull request #53 from battags/XML-Fix
Switched to SaxParserFactory directly.  Unit tests pass.  CASC-212
2013-06-20 04:08:12 -07:00
Scott Battaglia 715659ebcf Switched to SaxParserFactory directly. Unit tests pass. CASC-212 2013-06-20 00:15:53 -04:00
Scott Battaglia a9d640b1b0 Fixed formatting again. 2013-06-19 23:16:17 -04:00
Scott Battaglia b802354fdb Changed default for exceptionOnValidationFailure and message.
This seems to have some formatting changes in it also for some reason.
2013-06-19 23:11:22 -04:00
Scott fddafb753f Merge pull request #51 from battags/master
[NOJIRA] Reformat to Eclipse Standard
2013-06-19 19:55:55 -07:00
Scott Battaglia 1993718cc7 Reformat all files using shared CAS Eclipse formatter. 2013-06-19 22:50:02 -04:00
Scott 180f1f803b Merge pull request #49 from battags/CASC-206
CASC-206 Added Authentication Redirect Strategy to support original use case and new Faces support
2013-06-19 19:30:28 -07:00
Scott Battaglia 9674ad8a45 Swithed to existing Reflection utils. Added supporting unit test. 2013-06-19 22:26:09 -04:00
Scott Battaglia 8a7e32e5be Merge branch 'master' into CASC-206 2013-06-19 22:25:18 -04:00
Scott d413ee5cf8 Merge pull request #50 from battags/CASC-207
CASC-207 - Converted to static logger for serializable class
2013-06-19 07:12:31 -07:00
Scott Battaglia 077e991ae6 CASC-207
Converted logger to static for de-serialization purposes.
2013-06-18 22:38:25 -04:00
Scott Battaglia 8643e85b1e Added missing javadoc 2013-06-18 22:07:50 -04:00
Scott Battaglia 73e36bf6d2 Fixed failing test case that was missing an import statement. 2013-06-18 21:57:22 -04:00
Scott Battaglia 8df9f0272b Added redirect strategy to support Faces. 2013-06-18 21:56:58 -04:00
Scott Battaglia 091f1d5f90 Merge branch 'master' of github.com:Jasig/java-cas-client 2013-06-18 21:08:50 -04:00
Scott 4802ad8c17 Merge pull request #47 from mores/CASC-208
[CASC-208] Prevent unnecessary log errors
2013-05-07 18:06:32 -07:00
mores 2b53bdf882 getSocketFactory() should only be called on a sslContext that has been initialized. 2013-05-06 13:46:47 -04:00
Scott c36c8e952c Merge pull request #45 from mores/CASC-205
[ CASC-205 ] Saml11TicketValidator unable to process type XSString
2013-04-25 06:45:10 -07:00
mores e6e0f907b8 Fix to allow client to work with Server 3.5.2 2013-04-25 09:11:11 -04:00
Misagh Moayyed 089fca4ca4 Merge pull request #40 from mmoayyed/CASC-180
CASC-180: Fix the issue with casting to http url connections and provide...
2013-03-11 13:35:54 -07:00
Misagh Moayyed 4f79cd1014 CASC-180: Renamed factory to be HttpURLConnectionFactory. 2013-03-10 20:51:27 -07:00
Misagh Moayyed 2e6df8c5b7 CASC-180: Fixed try/catch block issue with URL creation. 2013-03-09 15:00:45 -07:00
Misagh Moayyed 3964e739c0 CASC-180: Removed the default url connection factory, allowed proxy retrieval to use the configured factory instance. 2013-03-06 09:34:39 -07:00
Misagh Moayyed c34ff785dd CASC-180: Fix the issue with casting to http url connections and provide a default instance for the http url factory. 2013-03-04 14:17:55 -07:00
Marvin S. Addison ad5525d2e5 Merge pull request #39 from serac/casc-204
CASC-204 Prevent renew misconfiguration.
2013-03-04 09:51:51 -08:00
Marvin S. Addison 6e12f43b16 CASC-204 Prevent renew misconfiguration.
Prevent renew from being configured via filter init param, which can lead
to a half-configured state where authentication filter is configured for
renew without validation filter. With this change in place, renew MUST be
configured by a global configuration facility such as context parameter or
JNDI to ensure proper configuration.
2013-03-04 10:43:55 -05:00
Misagh Moayyed 3063afc756 Merge pull request #36 from mmoayyed/CASC-180
CASC-180: Add support for Client Side Certificates
2013-03-03 09:13:14 -08:00
Scott Battaglia 974c3beb67 Merge branch 'master' of github.com:battags/java-cas-client 2013-02-17 21:31:55 -05:00
Misagh Moayyed d102c50779 CASC-180 - Add support for Client Side Certificates
Moved url connection factory interface and its https impl into the ssl package.
2013-01-24 15:47:22 -07:00
Misagh Moayyed d1ae0f5bbf Fixed javadoc for unused parameter. 2013-01-24 12:07:22 -07:00
Misagh Moayyed b54cd179e2 CASC-180 - Add support for Client Side Certificates
In order to utilize client side certificates, this commit facilitates the creation of a SSLSocketFactory on HttpsURLConnection for the client. The configuration is encapsulated inside a url factory instance that applies the adjustments where necessary.

This commit is continuation of the posted pending pull on github that is at:
https://github.com/Jasig/java-cas-client/pull/26

...and applies the suggestions and fixes that were brought to light during the code review.
2013-01-24 12:01:47 -07:00
Scott cd4dcc9fc9 Merge pull request #35 from battags/CASC-202
CASC-202 Migrate Commons Logging to SLF4J

Migrated to SLF4J, updated License header to match main CAS project, and re-ran script.
2013-01-15 19:06:54 -08:00
Scott Battaglia b4367f595e Fix formatting of pom.xml and update licensing to match CAS project. 2013-01-15 22:04:16 -05:00
Scott Battaglia 2f9d384b1e CASC-202
convert Commons Logging to SLF4J.  Add Enforcer.
2013-01-11 23:25:52 -05:00
Scott Battaglia 06ccec017d CASC-202
migration to SLF4J
2013-01-11 22:23:49 -05:00
Scott Battaglia 105bd17b61 Merge branch 'master' into CASC-202 2013-01-08 23:34:01 -05:00
Scott Battaglia f2df7a8603 CASC-202
migrated some to SLF4J
2013-01-08 23:32:35 -05:00
Scott d69e083f28 Merge pull request #34 from battags/CASC-179
CASC-179
2013-01-08 05:18:40 -08:00
Scott 7acd9adc4b Merge pull request #32 from battags/CASC-196
CASC-196
2013-01-08 05:17:09 -08:00
Scott c3ad115f5f Merge pull request #1 from katelme/patch-1
CASC-196
2013-01-08 04:40:18 -08:00
David Ordás eed831191a re-add support for multi-valued attributes
Add tests for ensure re-add support for multi-valued attributes is working
2013-01-08 13:28:35 +01:00
Scott Battaglia 67bb0a6ef8 CASC-196
re-add support for multi-valued attributes
2013-01-07 23:10:24 -05:00
Scott Battaglia e95d867792 Merge branch 'master' into CASC-196 2013-01-07 22:56:07 -05:00
Scott Battaglia 5af7c331b7 CASC-179
added parameter to determine whether to create sessions.  Also, now properly does a return.
2013-01-07 22:51:45 -05:00
Scott 27d89ccb30 Merge pull request #28 from battags/CASC-192
CASC-192
2013-01-07 06:22:28 -08:00
Scott f733760e68 Merge pull request #30 from battags/CASC-168
CASC-168
2013-01-07 05:02:05 -08:00
Scott 9294fbdffd Merge pull request #29 from battags/CASC-191
CASC-191
2013-01-07 05:01:51 -08:00
Scott c26329d21b Merge pull request #27 from battags/CASC-195
CASC-195
2013-01-06 21:02:08 -08:00
Scott d347f65bc6 Merge pull request #33 from battags/master
NOJIRA fix minor missing final tags and javadoc.
2013-01-06 20:58:03 -08:00
Scott Battaglia 82c0207c25 NOJIRA fix minor missing final tags and javadoc. 2013-01-06 23:56:24 -05:00
Scott Battaglia 980d0ff116 CASC-196
real XML parsing example if using <cas:attributes>.  Updated tests to make sure it works if there are line breaks.
2013-01-06 23:40:46 -05:00
Scott Battaglia ac8a134192 CASC-168
added ability to specify class name in order to use a sub-class.
2013-01-06 19:36:37 -05:00
Scott Battaglia 5ad57084cc CASC-191
isValid method with simple implementation
2013-01-06 18:45:05 -05:00
Scott Battaglia 41e7258af3 CASC-192
cast to XSAny in order to actually get the text content.
2013-01-06 18:24:11 -05:00
Scott Battaglia dcd9bda3df CASC-195
null check in ProxyGrantingTicketStorageImpl.
2013-01-06 18:14:42 -05:00
Scott fc1eaa1665 Merge pull request #24 from mmoayyed/CASC-199
CASC-199: Allow for an additional option to exclude empty proxy chains.
2012-12-29 13:54:01 -08:00
Misagh Moayyed 5f1a30a314 CASC-199: Allow for an additional option to exclude empty proxy chains. 2012-12-10 21:10:10 -07:00
Scott 010939de74 Merge pull request #23 from dodok1/master
properly support Confluence 3.5 - 4.3
2012-11-11 15:38:00 -08:00
Jozef Kotlar 68eb4aef23 minor change digged out of DefaultAuthenticator 2012-11-05 20:59:56 +01:00
Jozef Kotlar a754b40b30 implemented authentificator for Confluence 3.5 for newer Seraph/Crowd infrastructure
- using getUserFromSession()
- propagating event
- based on https://bitbucket.org/jaysee00/example-confluence-sso-authenticator
- based on comment from https://jira.atlassian.com/browse/CONF-26547
2012-10-30 14:28:35 +01:00
Scott a708d22469 Merge pull request #20 from ecki/topic-ignorebin
.gitignore Eclipse's .project default output bin/ directory.
2012-10-06 05:37:59 -07:00
Bernd Eckenfels caa2fccd32 .gitignore Eclipse's .project default output bin/ directory. 2012-10-04 04:53:41 +02:00
Marvin S. Addison bc6229b00e Merge pull request #18 from battags/CASC-188
CASC-188 Provide Support for Wildcard Roles
2012-09-21 06:51:16 -07:00
Scott Battaglia 008debf267 CAS-188
provide default Tomcat behavior
2012-09-20 22:20:48 -04:00
Scott afa83081a6 Merge pull request #16 from ecki/topic-redirectfix
make default value of useRedirect visible. Add some JavaDoc
2012-09-20 19:19:04 -07:00
Bernd Eckenfels 3deac9e1a9 Corrected JavaDoc (force if useSession=false force redirect=false) 2012-09-21 04:11:22 +02:00
Bernd Eckenfels 5f1e5e0ed4 make default value of useRedirect visible. Add some JavaDoc for the
options.
2012-09-21 01:32:06 +02:00
Scott bacf0c6142 Merge pull request #13 from serac/casc-166
CASC-166 Fix race condition in cached assertion cleanup.
2012-08-01 18:59:09 -07:00
Marvin S. Addison ee2b719098 CASC-166 Address code review feedback.
Use ConcurrentHashMap to avoid explicit synchronization.
Use TimeUnit to allow more user-friendly configuration of the units of the cache timeout (e.g. MINUTES, SECONDS) and rename option from cacheTimeoutUnits to cacheTimeoutUnit for consistency.
2012-07-26 10:25:06 -04:00
Marvin S. Addison ec0c7d5162 CASC-166 Fix race condition in cached assertion cleanup.
Perform assertion cleanup on same thread as JAAS module invocations to ensure that cleanup of expired assertions occurs before the cache is interrogated. A verifying test case accompanies this fix. The test case required a new module option, cacheTimeoutUnits, in order to complete on a time scale suitable for unit tests.
2012-07-25 16:58:36 -04:00
Misagh Moayyed b2f038a174 Merge pull request #12 from battags/CASC-185
CASC-185 - Merged.
2012-07-25 09:34:46 -07:00
Scott Battaglia bae8e68f55 CASC-185
add authentication time to assertion and also actually use the validity period for Assertion.
2012-07-24 23:01:35 -04:00
Scott 2b9cec59be Merge pull request #11 from battags/CASC-169
CASC-169
2012-07-24 19:40:31 -07:00
Scott Battaglia 3816e29861 CASC-169
change to hashmap to allow values to be added
2012-07-24 22:39:06 -04:00
Scott eadf300985 Merge pull request #9 from battags/CASC-184
CASC-184 - upgrade to OpenSAML2, update XML parsing to work with old and new server code.
2012-07-24 19:15:34 -07:00
Scott Battaglia 6e3f802cba CASC-184
improved SAML support.  Also execute old AND new XML in the unit tests.

cr for the first round of changes: serac
2012-07-24 22:13:25 -04:00
Scott Battaglia 616bbfa403 CASC-184
upgrade to OpenSAML2
2012-07-23 22:09:09 -04:00
Scott e10299896a Merge pull request #8 from mmoayyed/CASC-182-1
CASC-182 - reset the redirectAfterValidation parameter to false when use...
2012-07-11 10:14:33 -07:00
Misagh Moayyed 37b4058640 CASC-182: Combined logging statements into one. 2012-07-11 10:12:20 -07:00
Misagh Moayyed 09ffc2c05d CASC-182 - reset the redirectAfterValidation parameter to false when useSession is false. 2012-07-10 14:52:20 -07:00
Scott Battaglia d0ecca4274 CAS-172
don't log proxy message when there is no PGTIOU
2012-04-23 00:00:56 -04:00
Scott Battaglia eff195aaa9 CASC-171
check x-forwarded host header
2012-04-22 23:38:22 -04:00
unknown 7302ca6a99 CASC-175
ensure state can be shared
2012-04-22 23:29:38 -04:00
Scott 81e81256e0 Merge pull request #2 from lavrovdv/master
Parsing the custom attributes using xml dom parser.
2012-04-22 17:07:22 -07:00
Scott 8673f2c294 Merge pull request #5 from Gleeble/master
Change to allow for Session Fixation Prevention
2012-04-15 17:29:03 -07:00
Adam Swift 5f3700670c Changed to allow usage with systems using Session Fixation fixes following a login 2012-04-13 16:39:41 -04:00
Scott 1775ae99ec Merge pull request #4 from yzhengyu/master
CASC-164 Fix for Jasig CAS client for Java not working in 4.4 and above
2012-04-03 18:35:27 -07:00
Zhengyu Yong 0f9909406f Jira44CasAuthenticator will handle authentication for versions 4.4 and up 2012-04-02 18:07:37 +08:00
Zhengyu Yong 992a081434 added dependency to jira-core version 4.4 2012-04-02 18:05:48 +08:00
lavrovdv 88c69a7caa Merge branch 'master' of https://github.com/lavrovdv/java-cas-client
Conflicts:
	cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java
	cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java
2012-03-15 11:09:09 +04:00
lavrovdv 4b454e1e2e Parsing the attributes using xml dom parser. 2012-03-15 11:04:47 +04:00
lavrovdv 78c6ac29f9 Parsing the attributes using xml dom parser. 2012-03-14 09:25:15 +04:00
lavrovdv 26e959c3d0 The result of parsing the xml document should not depend on the "\n" symbols. 2012-03-13 15:08:13 +04:00
Scott 7345e03a6f Merge pull request #1 from ZerothAngel/master
Tomcat integration: Store principal in session
2012-03-07 20:10:19 -08:00
Allan Saddi c4d63f74ca Also register the principal in the current session, if any. 2012-03-07 16:48:20 -08:00
Marvin S. Addison bbcd532924 Add gitignore file. 2012-03-07 09:49:56 -05:00
Marvin S. Addison de2ab6a3ad Update POM for GitHub and update other stale project information.
Reformat pom.xml for 2-space indentation.
2012-03-07 09:43:26 -05:00
Scott Battaglia a19c27f75b CASC-165
disable DTD reading.
2011-10-31 02:44:07 +00:00
Scott Battaglia 80693a3db9 CASC-157
added pre and post hooks
2011-09-22 02:02:03 +00:00
Scott Battaglia 477fc582f0 CASC-163
SSO filter supports ticket over POST.
2011-09-22 01:10:19 +00:00
Scott Battaglia 84aa06629f CASC-160
added a check to make sure we really wanted to gateway.
2011-09-22 00:55:15 +00:00
Scott Battaglia 5cd43c2139 CASC-101
additional protected getters
2011-09-12 04:12:37 +00:00
Scott Battaglia b1f623128c NOJIRA updated jasig parent 2011-09-11 18:24:29 +00:00
Scott Battaglia e56601db95 NOJIRA
disabled encryption test for now
2011-09-11 18:15:53 +00:00
Scott Battaglia 0d8c085d19 NOJIRA
enabled JBoss repo for now to get build working in Bamboo
2011-09-11 17:57:13 +00:00
Scott Battaglia 91046c779c NOJIRA
enabled JBoss repo for now to get build working in Bamboo
2011-09-11 17:13:56 +00:00
Scott Battaglia d754bc8d8c NOJIRA
ignore to get the CI to run.
2011-09-11 16:54:16 +00:00
Scott Battaglia fb42fefaf9 NOJIRA
fixed some bugs and updated pom to 3.3-SNAPSHOT
2011-09-11 16:46:53 +00:00
Scott Battaglia 97e6573e32 NOJIRA
accidental Java 1.6 dependency
2011-09-11 16:35:23 +00:00
Scott Battaglia e055585cf2 CASC-144
added support for multiple hosts with a space separated value
2011-09-11 16:15:30 +00:00
Scott Battaglia 3b6ccaac0a CASC-154
added method to AbstractCasFilter that can be overwritten in ticket validation and authentication to support other methods of retrieving the ticket.
2011-09-11 15:11:43 +00:00
Scott Battaglia 29165243a5 CASC-155
upgrade to Seraph 2.5 and attempt to fix class cast
2011-09-11 15:03:35 +00:00
Scott Battaglia 6a98fc61a5 CASC-156
call sendError
2011-07-31 19:01:17 +00:00
Scott Battaglia df6131ba7d CASC-151
added readme to explain the missing artifact issue.
2011-07-31 18:56:34 +00:00
Scott Battaglia 3d965426ac [maven-release-plugin] prepare for next development iteration 2011-07-10 23:44:18 +00:00
Scott Battaglia e0af12eeba [maven-release-plugin] prepare release cas-client-3.2.1 2011-07-10 23:43:33 +00:00
Scott Battaglia 413837e4df CASC-153
added check to make sure only serverName or serviceName is set, but not both.
2011-06-27 03:00:45 +00:00
Scott Battaglia f3b6ae5a4d CASC-149
parse the trailing slash on a path.  Added a javadoc to explain a bit better, as well as an INFO level message.
2011-06-27 02:58:51 +00:00
Scott Battaglia 49f556575e CASC-149
parse the trailing slash on a path.  Added test cases.
2011-06-21 02:33:15 +00:00
Scott Battaglia d5bc8e3757 CASC-148
update documentation about JNDI loading order.
2011-06-21 02:12:11 +00:00
Scott Battaglia 37ed0719e3 CASC-152
attach jars to source generation.
2011-06-21 02:07:18 +00:00
Scott Battaglia 7d4c35417f CASC-146
added encoding for SAML request.
2011-06-21 01:54:37 +00:00
Scott Battaglia 8941d96a99 CASC-147
ignore logout requests for multipart forms
2011-06-21 01:39:49 +00:00
Scott Battaglia e9569564d7 CASC-143
fix for the changes Atlassian made to seraph
2011-03-27 18:17:44 +00:00
Scott Battaglia 3b1c1ac85f CASC-139
generate correct identifier value.
2011-02-27 05:06:50 +00:00
Scott Battaglia 35a6b08dac CASC-141
applied patch for Tomcat 7.0.8 support.
2011-02-27 04:54:41 +00:00
Scott Battaglia 84ad620b34 CASC-138
added hostnameVerifier to the list of reserved keywords
2011-02-12 22:00:45 +00:00
Scott Battaglia 8c53e4b0e6 CASC-138
added hostnameVerifier to the list of reserved keywords
2011-02-12 22:00:06 +00:00
Scott Battaglia 90d6625e7f CASC-137
fix null pointer exception when the anyhostname verifier is used.
2011-02-12 18:30:25 +00:00
Scott Battaglia ec87c31ecd NOJIRA
switch to stringbuilder since we're on Java 5
2011-02-12 18:29:41 +00:00
Scott Battaglia 035a6f7a8e [maven-release-plugin] prepare for next development iteration 2010-12-08 04:22:32 +00:00
Scott Battaglia f6ff486939 [maven-release-plugin] prepare release cas-client-3.2.0 2010-12-08 04:22:21 +00:00
Scott Battaglia 18b70ee8ce NOJIRA
updated Atlassian dependencies and documented where to download provided jars
2010-12-08 04:16:23 +00:00
Scott Battaglia 2055d0891b NOJIRA
updated to say Jasig instead of JA-SIG
2010-12-08 02:47:08 +00:00
Scott Battaglia cbb51b0506 CASC-135
added encryption mechanism to distributed proxy granting ticket storage mechanisms
2010-11-27 23:23:24 +00:00
Scott Battaglia 4a36b023a6 CASC-134
change to get Attributes instead of just getAttribute in case there are multiple values.
2010-11-20 06:05:40 +00:00
Scott Battaglia befd53e456 CASC-128
ability to disable SAML 1.1 schema validation
2010-11-16 04:43:08 +00:00
Scott Battaglia 1abdee8399 CASC-133
fixed the fact that we were logging value3 when we meant to log value4.
2010-11-15 04:17:50 +00:00
Marvin S. Addison c6b1bc775a CASC-120
Add type parameters to fix unchecked compiler warnings where possible,
otherwise add SuppressWarnings("unchecked") compiler directive in a couple
places.
Use ReflectUtils.newInstance for creating new instances of objects from
class names.
2010-10-28 17:44:53 +00:00
Marvin S. Addison 82d03364c8 NOJIRA
Add required serialVersionUID.
2010-10-28 17:39:30 +00:00
Marvin S. Addison 5faf72b876 CASC-120
Use Collections.enumeration.
2010-10-28 16:06:32 +00:00
Scott Battaglia aa4afd9c5f NOJIRA
migrated to Java 5
2010-10-25 03:59:14 +00:00
Scott Battaglia 1911c7242c CASC-132
catch remote exception and log it as a warning
2010-10-23 04:09:47 +00:00
Scott Battaglia f68afc177c NOJIRA:
upgrade to Java 1.5, upgrade Clover, Ehcache version, switch to 3.2.0-SNAPSHOT, and Jasig Parent pom.  Switch to Apache license.
2010-10-23 04:03:14 +00:00
Scott Battaglia c459d1adde NOJIRA:
upgrade to Java 1.5, upgrade Clover, Ehcache version, switch to 3.2.0-SNAPSHOT, and Jasig Parent pom.  Switch to Apache license.
2010-10-23 03:57:16 +00:00
Scott Battaglia 0b59f0c7fd NOJIRA:
upgrade to Java 1.5, upgrade Clover, Ehcache version, switch to 3.2.0-SNAPSHOT, and Jasig Parent pom.  Switch to Apache license.
2010-10-23 03:51:04 +00:00
Scott Battaglia b0044cd075 NOJIRA:
upgrade to Java 1.5, upgrade Clover, Ehcache version, switch to 3.2.0-SNAPSHOT, and Jasig Parent pom.  Switch to Apache license.
2010-10-23 03:49:49 +00:00
Scott Battaglia df8211cf68 [maven-release-plugin] prepare for next development iteration 2010-10-13 03:45:34 +00:00
Scott Battaglia 0270596bac [maven-release-plugin] prepare release cas-client-3.1.12 2010-10-13 03:44:57 +00:00
Scott Battaglia 75b51c85bd NOJIRA
upgrade the oss-parent pom
2010-10-13 03:32:35 +00:00
Scott Battaglia 54964cb5a4 CASC-129
updated exception message thrown when there no valid assertions to better indicate that it may be a clock drift issue.
2010-10-13 02:51:53 +00:00
Scott Battaglia ff5a99ea0a CASC-126
improved logging of errors.
2010-10-06 03:30:57 +00:00
Scott Battaglia ac08968c30 NOJIRA
extremely minor formatting fixes
2010-10-06 03:27:37 +00:00
Marvin S. Addison a947490c04 CASC-33
Add SingleSignOutValve, which required some refactoring in core
org.jasig.cas.client.session package to facilitate code reuse.
2010-09-23 15:03:50 +00:00
Marvin S. Addison 5857589a44 CASC-33
Refactor logout valves for reduced code duplication.
Improve logging.
2010-09-22 18:28:43 +00:00
Marvin S. Addison c7c8404259 CASC-33
Logging improvements.
2010-09-22 15:00:48 +00:00
Scott Battaglia 29866f923e CASC-33
minor updates to documentation, final keyword, and formatting.
2010-09-22 03:31:35 +00:00
Marvin S. Addison 4bd7b522cb CASC-33
Logging changes to help confirm functionality of logout valves.
Fix typo in regular expression-based logout valve class name.
2010-09-21 15:52:16 +00:00
Marvin S. Addison b99b45d1ba CASC-33
Fix botched commit of Tomcat 6.x container authentication.
2010-09-21 15:07:13 +00:00
Scott Battaglia a1b9031416 CASC-33
minor updates to documentation, final keyword, and formatting.
2010-09-21 03:15:18 +00:00
Marvin S. Addison ce46854baa CASC-33
Tomcat 6.x support for container-based CAS authentication.
Minor changes to 7.x support for consistency.
2010-09-20 20:19:32 +00:00
Scott Battaglia 704f1b8a67 CASC-33
fixed test that was failing (my guess is its due to the different ways the JVMs return arrays).  Also enhanced code to use "Best practice" of never returning null and instead returning an empty list simplifying upstream code.
2010-09-20 03:42:51 +00:00
Scott Battaglia f64a23b1ae CASC-125
added default auth filter for saml1.1 and made sure that it and the validation filter set the required saml parameters.
2010-09-20 03:33:49 +00:00
Marvin S. Addison f023fa5282 NOJIRA
Ignore maven target directory.
2010-09-17 20:45:38 +00:00
Marvin S. Addison 54afd070ec CASC-33
Updated Tomcat container authnz support with abstracted
version-agnostic core, cas-client-integration-tomcat-common, to facilitate
integration with multiple versions of Tomcat.
2010-09-17 20:37:19 +00:00
Marvin S. Addison 0f3d8a5c60 CASC-33
Service parameter must be lowercase.
2010-09-10 19:39:23 +00:00
Scott Battaglia 9b8ce98ebf CASC-33
support for Tomcat: more authentication mechanisms.  Fixed authenticator class and added license.
2010-09-03 03:36:16 +00:00
Scott Battaglia cd3ecb8e3c CASC-33
support for Tomcat: more authentication mechanisms.  Just need to do the abstract class now.
2010-09-01 03:56:46 +00:00
Scott Battaglia 9ffca231a0 CASC-33
support for Tomcat: logout, proxy callback.
2010-08-29 21:53:32 +00:00
Scott Battaglia 74a8cff651 CASC-115
applied Marvin's patch.  Made changes to check for debug enabled before doing any concatenation and to renable the initCause
2010-08-16 03:15:45 +00:00
Scott Battaglia 2449a7a61b CASC-33
initial Tomcat support started.
2010-07-20 03:55:54 +00:00
Scott Battaglia 649b39b1c8 CASC-116
removed secondary call to response.encodeRedirectUrl because according to the Tomcat source code they essentially do the same thing.
2010-07-20 02:33:36 +00:00
Scott Battaglia b1f6e24f7e CASC-117
added init cause to login exceptions
2010-07-20 02:12:02 +00:00
Scott Battaglia 40c006389e [maven-release-plugin] prepare for next development iteration 2010-06-17 03:08:14 +00:00
Scott Battaglia 07cc6b62f3 [maven-release-plugin] prepare release cas-client-3.1.11 2010-06-17 03:08:03 +00:00
Scott Battaglia c312ca0b4f NOJIRA
preparations for 3.1.11 release
2010-06-17 03:04:31 +00:00
Scott Battaglia 4776006b07 NOJIRA
preparations for 3.1.11 release
2010-06-17 02:59:34 +00:00
Scott Battaglia 6a942e294b NOJIRA
preparations for 3.1.11 release
2010-06-17 02:55:26 +00:00
Scott Battaglia 8bd5e8ba07 [maven-release-plugin] prepare release cas-client-3.1.11 2010-06-17 02:54:34 +00:00
Scott Battaglia 4e5b27bdd1 NOJIRA
preparations for 3.1.11 release
2010-06-17 02:52:17 +00:00
Scott Battaglia 56822871d6 NOJIRA
preparations for 3.1.11 release
2010-06-17 02:51:56 +00:00
Scott Battaglia 206c5180a7 NOJIRA
preparations for 3.1.11 release
2010-06-17 02:37:42 +00:00
Scott Battaglia 07ea7b92da NOJIRA
preparations for 3.1.11 release
2010-06-17 02:35:43 +00:00
Scott Battaglia 0e289c70b5 [maven-release-plugin] prepare release cas-client-3.1.11 2010-06-17 02:28:49 +00:00
Scott Battaglia dcddfe5d65 NOJIRA
preparations for 3.1.11 release
2010-06-17 02:19:15 +00:00
Marvin S. Addison 587c9c41a3 CASC-108
Ignore target directory in new JBoss integration module.
2010-06-07 15:31:04 +00:00
Marvin S. Addison a57e3d401f CASC-108
Minor logging fixes/improvements.
2010-06-07 15:29:23 +00:00
Scott Battaglia 01fd618436 CASC-112
added brackets around the pgtIou to make it more obvious the message isn't cut off.
2010-06-05 17:25:34 +00:00
Scott Battaglia 23711eb6a1 CASC-108
commit before we move to the new repository.  We cannot release this yet because we're missing a contributor license agreement.
2010-06-01 22:56:09 +00:00
Scott Battaglia b9208f9077 CASC-109
changed location of redirect to successful block
2010-05-27 03:32:03 +00:00
Scott Battaglia 975bf7700c CASC-110
added the reserved keyword to the list.
2010-05-27 03:09:39 +00:00
Scott Battaglia b76ce0dcc9 CASC-103
updated javadoc to explain the purpose of the method
2010-05-09 05:07:52 +00:00
Scott Battaglia f5984a088d CASC-107
enabled providing a specific encoding
2010-05-09 04:18:51 +00:00
Scott Battaglia 92c2b081cd CASC-106
made some changes to explicitly use UTC.
2010-05-09 03:51:18 +00:00
Scott Battaglia d6f11f89a2 CASC-105
changed log level to debug instead of warn.
2010-05-09 03:26:32 +00:00
Marvin S. Addison 4ef10cd168 CASC-80
Add support for setting HostnameVerifier for CAS validation filters in
web.xml.
2010-02-24 14:55:51 +00:00
Marvin S. Addison 96a31f5afd NOJIRA
Update svn:ignore to ignore maven target directories.
2010-02-23 18:37:41 +00:00
Scott Battaglia 856d2b07f9 CASC-102
moved the call to initialize the ticket validator to after the setting of the proxy granting ticket storage.
2009-12-18 03:12:15 +00:00
Scott Battaglia ef9caa321e NOJIRA
preparations for 3.1.10
2009-12-16 13:43:04 +00:00
Scott Battaglia 3f2a1c4c69 CASC-96
reworked logic
2009-11-24 15:34:32 +00:00
Scott Battaglia 6459137bb2 CASC-99
moved the line to make sure we're not accidentally prepending "&"
2009-11-24 15:19:15 +00:00
Scott Battaglia ff84c43b45 CASC-100
moved call to create url
2009-11-24 15:08:57 +00:00
Scott Battaglia 7f56406ca6 NOJIRA
work for a 3.1.10-SNAPSHOT
2009-11-24 15:08:41 +00:00
Scott Battaglia f5d698c5de NOJIRA
preparations for 3.1.9 release
2009-10-22 15:37:35 +00:00
Scott Battaglia c652557f8a CASC-96
corrected session call
2009-10-14 16:02:03 +00:00
Scott Battaglia 30c2d9e3c9 NOJIRA
re-added accidental removal of Ehcache-backed impl
2009-10-14 15:59:51 +00:00
Scott Battaglia 111190063d CASC-95
removed unused directory
2009-10-14 03:21:57 +00:00
Scott Battaglia 79e706e59f CASC-95
added memcached support
2009-10-14 03:20:06 +00:00
Scott Battaglia b16412731d CASC-93
added check for role
2009-09-22 15:26:49 +00:00
Scott Battaglia bdb354531e CASC-95
use ehcache for distributed support
2009-09-20 16:09:56 +00:00
Scott Battaglia ccdd0596c7 CASC-94
moved HttpConnection to CommonUtils
2009-09-20 14:50:43 +00:00
Scott Battaglia 92ebc16288 NOJIRA
changed to sftp from scp
2009-09-14 15:18:00 +00:00
Scott Battaglia 1a86ba2633 NOJIRA
preparation for 3.1.8
2009-09-11 12:46:55 +00:00
Scott Battaglia 5435445f11 CASC-89
revert behavior for POST requests for the "logoutRequest" parameter.
2009-09-11 12:39:58 +00:00
Scott Battaglia 95f63d7743 CASC-92
changed config parameter to determine where properties came from in logs.
2009-09-11 11:50:52 +00:00
Scott Battaglia 42cc968a2e CASC-90
added logout support
2009-09-01 12:22:21 +00:00
Scott Battaglia 8a32fd2061 NOJIRA
forgot a check for null.  Whoops.
2009-08-12 13:43:57 +00:00
Scott Battaglia f0a78e0edf CASC-85
added safeGetParameter method
2009-08-11 18:22:09 +00:00
Scott Battaglia f9e3ae8abb CASC-85
moved the reading of parameters
2009-07-30 16:49:55 +00:00
Scott Battaglia 590d87d265 NOJIRA
updates for 3.1.7
2009-07-29 15:42:21 +00:00
Scott Battaglia a14767c232 CASC-86
fixed the random id generation and the issue instant that Joe pointed out.
2009-07-29 14:27:48 +00:00
Scott Battaglia 745c45718c CASC-88
imported Marvin's patch with some modifications to fix support for proxying in a non-Spring environment.
2009-07-29 13:54:29 +00:00
Scott Battaglia 9b1ba497e3 CASC-87
improved utility to allow for arbitrary parameters to be passed at login
2009-07-29 12:26:17 +00:00
Scott Battaglia bddd8f0622 NOJIRA
preparation for 3.1.6
2009-05-26 17:33:50 +00:00
Scott Battaglia cbbab079a7 NOJIRA
transfered over old tests
2009-05-26 15:47:13 +00:00
Scott Battaglia ad62b2fc2a NOJIRA
transfered over old tests
2009-05-26 15:47:00 +00:00
Scott Battaglia e78706747a CASC-84
added property to override configuration init param
2009-05-23 03:33:41 +00:00
Scott Battaglia 1031f01ee0 NOJIRA
updated so that we rely on the filter instead of the listener.
2009-05-22 19:37:53 +00:00
Scott Battaglia de82cb0a85 CASC-82
updated logging
2009-05-22 17:57:06 +00:00
Marvin S. Addison 7dd013cb9f CASC-81
Set validator renew property from servlet configuration.  Testing shows this resolves issue.
2009-05-06 13:17:29 +00:00
Brad Cupit b38a27626a CASC-77
removed the CleanUpRegistry, Cleanable interface, etc. and just use a simple static getter on the Filter that returns the Storage. The TimerTask just calls this static getter directly. This was deemed simpler than the CleanUpRegistry solution.

for Spring config: rather than use Quartz, we just use the java.util.Timer support in Spring
2009-03-21 21:24:31 +00:00
Brad Cupit 866e2b99ba NOJIRA
sleep long enough for the ticket to timeout
2009-02-20 14:10:04 +00:00
Brad Cupit 5761e0cb61 CASC-77
summary: fixed classloader leak by making the thread stop on webapp unload

this fix requires clients (those using proxy authentication) to configure either
a) a listener in web.xml (see CleanUpListener)
b) quartz in a spring xml config file (see CleanUpJob)

each of these starts a thread which runs the clean up operation

the listener will shut itself down on app undeploy
Spring's SchedulerFactoryBean (a quartz helper) must be configured with a destroy-method="destroy" in the spring xml config, otherwise a classloader leak may occur on webapp undeploy/hot deploy
2009-02-13 22:30:38 +00:00
Brad Cupit 7d4c321b3c NOJIRA
adding Eclipse's .classpath .project and .settings/ to svn:ignore
2009-02-12 15:50:36 +00:00
Brad Cupit c71748d104 CASC-79 (not enough synchronization on HashMap)
also, made nested classes static (they didn't have to be non-static, so this version is slightly more flexible and takes up slightly less memory: see Effective Java 2nd Edition Item 22)
2009-02-11 19:44:33 +00:00
Scott Battaglia 7191670c4e CASC-74
updated javadoc about serverName
2009-01-30 00:40:22 +00:00
Scott Battaglia d0be75e7b3 CASC-73
reduced warning message
2009-01-05 04:27:10 +00:00
Scott Battaglia d00986afc7 NOJIRA
preparation for CAS Client for Java 3.1.5 release
2008-12-18 04:21:15 +00:00
Scott Battaglia d419c68670 CASC-72
removed dependency on Confluence authenticator
2008-12-18 04:01:34 +00:00
Scott Battaglia fb1e4e5a84 CASC-71
removed Java 1.5 code
2008-12-05 19:08:18 +00:00
Scott Battaglia d237b339c6 NOJIRA
enforce 1.4
2008-10-31 16:12:45 +00:00
Scott Battaglia a1f983ae6b NOJIRA
prepare for the 3.1.4 release
2008-10-27 12:42:40 +00:00
Scott Battaglia 720c840eec CASC-70
check the request for the assertion if there is no session.
2008-10-24 13:36:09 +00:00
Scott Battaglia af2530d57d CASC-66
added support for configuration via JNDI
2008-08-27 16:37:36 +00:00
Scott Battaglia e0ca0a6e35 CASC-64
added a default error redirect page
2008-08-27 12:35:12 +00:00
Scott Battaglia eee667a611 CASC-68
enabled redirect after ticket validation by default
2008-08-27 12:03:00 +00:00
Scott Battaglia 3d09247029 CASC-58
allow to determine gateway features potentially via alternate methods
2008-08-06 14:45:22 +00:00
Scott Battaglia 415d118b5c CASC-65
added an explicit call to remove an entry from the backing storage before adding it just in case it already exists under another key
2008-08-06 13:07:03 +00:00
Scott Battaglia e8f438db55 CASC-64
capture and send redirect
2008-08-05 19:23:56 +00:00
Scott Battaglia e3d38a70a9 CASC-63
added synchronized methods
2008-07-11 13:51:38 +00:00
Scott Battaglia e1f533c759 NOJIRA
added another test
2008-06-19 18:54:20 +00:00
Scott Battaglia 2e0e6c85c0 NOJIRA
3.1.4 snapshot
2008-06-19 14:48:42 +00:00
Scott Battaglia fb98e1285f NOJIRA added svn:ignore 2008-06-16 13:49:01 +00:00
Scott Battaglia 98d4d53418 NOJIRA
getting ready for 3.1.3 release
2008-06-16 13:47:56 +00:00
Scott Battaglia 2863bd39e5 NOJIRA
removed unnecessary system.outs
2008-06-16 13:35:05 +00:00
Scott Battaglia 9673f33f53 NOJIRA
added one more debug logging statement
2008-06-10 03:32:22 +00:00
Scott Battaglia 4252731534 NOJIRA
factored out common code for proxying
2008-06-09 18:18:32 +00:00
Scott Battaglia ff11894493 NOJIRA
updated for an RC3
2008-06-09 17:59:54 +00:00
Scott Battaglia 44d180c864 NOJIRA
svn ignore
2008-06-09 17:29:46 +00:00
Scott Battaglia 88b87074dc CASC-37
added significantly more logging
2008-06-09 17:24:31 +00:00
Scott Battaglia 88b89a3756 CASC-56
implemented adding Content-Type to fix problem
2008-06-09 12:43:26 +00:00
Scott Battaglia ab21368d94 NOJIRA
added exclusion for log4j
2008-06-03 19:45:43 +00:00
Scott Battaglia 78054e3dbd NOJIRA
added exclusion for log4j
2008-06-03 19:35:21 +00:00
Scott Battaglia 2445b49e0a NOJIRA
added some Saml11 tests and updated to RC3
2008-06-03 19:33:33 +00:00
Scott Battaglia 56d0d2e023 CASC-54
added support for parsing custom attributes.  Added a basic model that is easily overrideable.
2008-05-29 21:10:25 +00:00
Scott Battaglia fe8e8d8bb3 CASC-52
switched to the PropertyEditor method which seems to work better.
2008-05-29 15:49:09 +00:00
Scott Battaglia a7d06fd666 CASC-55
added the check for the "/" to both the proxy retriever and the validators.
2008-05-28 21:15:32 +00:00
Scott Battaglia 74b3d60843 CASC-51
try/catch around the invalidate call incase its already invalidated.
2008-05-28 20:59:09 +00:00
Scott Battaglia c12836c9d6 CASC-52
started reworking beaninfo to proxylist
2008-05-28 19:05:14 +00:00
Scott Battaglia ef520c834f CASC-50
getRemoteUser checks if the principal is null now
2008-05-27 17:01:38 +00:00
Scott Battaglia f92005dd8e CASC-48
added ability to provide a map of custom attributes
2008-05-07 15:55:18 +00:00
Scott Battaglia 1f770cd549 NOJIRA
fixed version number
2008-04-28 19:01:34 +00:00
Scott Battaglia 13810e2b70 NOJIRA
updated for 3.1.3 rc1 release
2008-04-28 18:46:34 +00:00
Scott Battaglia bab75f9092 NOJIRA removed 2008-04-22 17:54:31 +00:00
Scott Battaglia 5bf8ccfa4a CASC-46
added required id for serialization.
2008-04-17 21:01:38 +00:00
Scott Battaglia 44cf029138 CASC-46
added serializable
2008-04-17 20:47:14 +00:00
Scott Battaglia a160d37c05 NOJIRA recommiting the jira and confluence stuff 2008-04-14 18:06:49 +00:00
Scott Battaglia fa78a2f626 NOJIRA
updated pom
2008-04-11 18:45:08 +00:00
Scott Battaglia dbd1017a8a CASC-44
added Adam's trace statements
2008-04-11 18:35:00 +00:00
Scott Battaglia 9f9686ee61 NOJIRA
added src folder
2008-04-08 15:18:37 +00:00
Scott Battaglia 22fc6d344b NOJIRA
added atlassian module
2008-04-08 14:58:53 +00:00
Scott Battaglia ea549d1a9b NOJIRA
prepare for 3.1.2 release
2008-03-10 20:44:25 +00:00
Scott Battaglia 93beba2242 NOJIRA
moved license file
2008-03-10 20:35:06 +00:00
Scott Battaglia a9f0ed72e6 CASC-42
parse out soap headers
2008-03-03 17:06:51 +00:00
Scott Battaglia ccbf08d8aa CASC-41
fixed property name
2008-03-03 15:41:24 +00:00
Scott Battaglia d8f5359a52 NOJIRA
renamed license.txt
2008-02-19 20:06:29 +00:00
Scott Battaglia ee788ac57e NOJIRA
added SCM version
2008-02-19 19:32:23 +00:00
Scott Battaglia 85bbf086ba NOJIRA
removed extra stuff so that we can send to repository
2008-02-19 18:51:51 +00:00
285 changed files with 26806 additions and 1755 deletions

20
.github/FUNDING.yml vendored Normal file
View File

@ -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']

11
.github/renovate.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"extends": [
"config:base",
":preserveSemverRanges",
":rebaseStalePrs",
":disableRateLimiting",
":semanticCommits",
":semanticCommitTypeAll(renovatebot)"
],
"labels": ["dependencies", "bot"]
}

73
.github/stale.yml vendored Normal file
View File

@ -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

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
.classpath
!/.project
.project
.settings
bin
target
*.ipr
*.iml
*.iws
.idea/
.DS_Store
.idea

44
.mergify.yml Normal file
View File

@ -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:

38
.travis.yml Normal file
View File

@ -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

View File

@ -1,31 +1,50 @@
License for Use
Copyright (c) 2007, JA-SIG, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the JA-SIG, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
====
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:
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.
====
License for Use
Copyright (c) 2007, JA-SIG, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the JA-SIG, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

101
NOTICE Normal file
View File

@ -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.
This project includes:
Apache Commons Codec under Apache License, Version 2.0
Apache Log4j 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
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
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: 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
javax.annotation API under CDDL + GPLv2 with classpath exception
JBoss Application Server Tomcat under lgpl
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 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
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
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

1504
README.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +1,84 @@
<!--
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.
-->
<assembly>
<id>release</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<lineEnding>unix</lineEnding>
<useDefaultExcludes>true</useDefaultExcludes>
<useStrictFiltering>false</useStrictFiltering>
<directory>${basedir}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.xml</include>
<include>*.txt</include>
</includes>
</fileSet>
</fileSets>
<moduleSets>
<moduleSet>
<includes></includes>
<sources>
<fileSets>
<fileSet>
<directory>src</directory>
<outputDirectory>src</outputDirectory>
<lineEnding>unix</lineEnding>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
<id>release</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<lineEnding>unix</lineEnding>
<useDefaultExcludes>true</useDefaultExcludes>
<useStrictFiltering>false</useStrictFiltering>
<directory>${basedir}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.xml</include>
<include>*.txt</include>
</includes>
</fileSet>
</fileSets>
<moduleSets>
<moduleSet>
<includes></includes>
<sources>
<fileSets>
<fileSet>
<directory>src</directory>
<outputDirectory>src</outputDirectory>
<lineEnding>unix</lineEnding>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
<fileSet>
<lineEnding>unix</lineEnding>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>*.xml</include>
</includes>
</fileSet>
<fileSet>
<lineEnding>unix</lineEnding>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>*.xml</include>
</includes>
</fileSet>
<fileSet>
<lineEnding>unix</lineEnding>
<directory>target/site/apidocs/</directory>
<useDefaultExcludes>true</useDefaultExcludes>
<outputDirectory>docs</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
<fileSet>
<lineEnding>unix</lineEnding>
<directory>target/site/apidocs/</directory>
<useDefaultExcludes>true</useDefaultExcludes>
<outputDirectory>docs</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
<includeModuleDirectory>true</includeModuleDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
</sources>
<binaries>
<outputDirectory>modules</outputDirectory>
<includeDependencies>true</includeDependencies>
<unpack>false</unpack>
<useDefaultExcludes>true</useDefaultExcludes>
<includes />
</binaries>
</moduleSet>
</moduleSets>
<includeModuleDirectory>true</includeModuleDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
</sources>
<binaries>
<outputDirectory>modules</outputDirectory>
<includeDependencies>true</includeDependencies>
<unpack>false</unpack>
<useDefaultExcludes>true</useDefaultExcludes>
<includes/>
</binaries>
</moduleSet>
</moduleSets>
</assembly>

View File

@ -0,0 +1,50 @@
====
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.
====
License for Use
Copyright (c) 2007, JA-SIG, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the JA-SIG, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

42
cas-client-core/NOTICE Normal file
View File

@ -0,0 +1,42 @@
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.
This project includes:
Apache Commons Codec under Apache License, Version 2.0
Apache Log4j 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
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
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 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

View File

@ -1,53 +1,44 @@
<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">
<!--
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</groupId>
<version>3.1.1</version>
<groupId>org.jasig.cas.client</groupId>
<version>3.6.2-SNAPSHOT</version>
<artifactId>cas-client</artifactId>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-client-core</artifactId>
<packaging>jar</packaging>
<name>JA-SIG CAS Client for Java - Core</name>
<name>Jasig CAS Client for Java - Core</name>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>false</filtering>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.4</source>
<target>1.4</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests*</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clover-plugin</artifactId>
<configuration>
<licenseLocation>${basedir}/src/test/clover/clover.license</licenseLocation>
</configuration>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>instrument</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
@ -56,49 +47,70 @@
</build>
<dependencies>
<dependency>
<groupId>xml-security</groupId>
<artifactId>xmlsec</artifactId>
<version>1.3.0</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>xml-security</groupId>
<artifactId>xmlsec</artifactId>
<version>1.3.0</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml</artifactId>
<version>1.1b</version>
<type>jar</type>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>2.5.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>test</scope>
<version>1.2.17</version>
<exclusions>
<exclusion>
<artifactId>jmxri</artifactId>
<groupId>com.sun.jmx</groupId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -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;
}
}

View File

@ -1,3 +1,21 @@
/**
* 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.io.Serializable;
@ -29,6 +47,6 @@ public interface AttributePrincipal extends Principal, Serializable {
* The Map of key/value pairs associated with this principal.
* @return the map of key/value pairs associated with this principal.
*/
Map getAttributes();
Map<String, Object> getAttributes();
}

View File

@ -1,28 +1,45 @@
/**
* 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 org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.util.CommonUtils;
import java.util.Collections;
import java.util.Map;
import org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Concrete implementation of the AttributePrincipal interface.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
public class AttributePrincipalImpl implements AttributePrincipal {
public class AttributePrincipalImpl extends SimplePrincipal implements AttributePrincipal {
private static final Logger LOGGER = LoggerFactory.getLogger(AttributePrincipalImpl.class);
/** Unique Id for Serialization */
private static final long serialVersionUID = -8810123156070148535L;
/** The unique identifier for this principal. */
private final String name;
private static final long serialVersionUID = -1443182634624927187L;
/** Map of key/value pairs about this principal. */
private final Map attributes;
private final Map<String, Object> attributes;
/** The CAS 2 ticket used to retrieve a proxy ticket. */
private final String proxyGrantingTicket;
@ -36,7 +53,7 @@ public class AttributePrincipalImpl implements AttributePrincipal {
* @param name the unique identifier for the principal.
*/
public AttributePrincipalImpl(final String name) {
this(name, Collections.EMPTY_MAP);
this(name, Collections.<String, Object> emptyMap());
}
/**
@ -45,8 +62,8 @@ public class AttributePrincipalImpl implements AttributePrincipal {
* @param name the unique identifier for the principal.
* @param attributes the key/value pairs for this principal.
*/
public AttributePrincipalImpl(final String name, final Map attributes) {
this(name, attributes, null, null);
public AttributePrincipalImpl(final String name, final Map<String, Object> attributes) {
this(name, attributes, null, null);
}
/**
@ -56,40 +73,41 @@ public class AttributePrincipalImpl implements AttributePrincipal {
* @param proxyGrantingTicket the ticket associated with this principal.
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS server.
*/
public AttributePrincipalImpl(final String name, final String proxyGrantingTicket, final ProxyRetriever proxyRetriever) {
this(name, Collections.EMPTY_MAP, proxyGrantingTicket, proxyRetriever);
public AttributePrincipalImpl(final String name, final String proxyGrantingTicket,
final ProxyRetriever proxyRetriever) {
this(name, Collections.<String, Object> emptyMap(), proxyGrantingTicket, proxyRetriever);
}
/**
* Constructs a new principal witht he supplied name, attributes, and proxying capabilities.
* Constructs a new principal with the supplied name, attributes, and proxying capabilities.
*
* @param name the unique identifier for the principal.
* @param attributes the key/value pairs for this principal.
* @param proxyGrantingTicket the ticket associated with this principal.
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS server.
*/
public AttributePrincipalImpl(final String name, final Map attributes, final String proxyGrantingTicket, final ProxyRetriever proxyRetriever) {
this.name = name;
public AttributePrincipalImpl(final String name, final Map<String, Object> attributes,
final String proxyGrantingTicket, final ProxyRetriever proxyRetriever) {
super(name);
this.attributes = attributes;
this.proxyGrantingTicket = proxyGrantingTicket;
this.proxyRetriever = proxyRetriever;
CommonUtils.assertNotNull(this.name, "name cannot be null.");
CommonUtils.assertNotNull(this.attributes, "attributes cannot be null.");
}
public Map getAttributes() {
@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);
}
LOGGER.debug("No ProxyGrantingTicket was supplied, so no Proxy Ticket can be retrieved.");
return null;
}
public String getName() {
return this.name;
}
}

View File

@ -1,12 +1,28 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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 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;
@ -18,6 +34,8 @@ 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
@ -28,18 +46,16 @@ import java.io.IOException;
* <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>
*
* @author Scott Battaglia
* @version $Revision: 11768 $ $Date: 2007-02-07 15:44:16 -0500 (Wed, 07 Feb 2007) $
* @author Misagh Moayyed
* @since 3.0
*/
public class AuthenticationFilter extends AbstractCasFilter {
public static final String CONST_CAS_GATEWAY = "_const_cas_gateway_";
/**
* The URL to the CAS Server login.
*/
@ -55,52 +71,155 @@ public class AuthenticationFilter extends AbstractCasFilter {
*/
private boolean gateway = false;
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
super.initInternal(filterConfig);
setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));
setRenew(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
setGateway(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "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>>();
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);
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) {
this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlMatcherClass.getName());
} else {
try {
logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);
this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlPatternType);
} catch (final IllegalArgumentException e) {
logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, e);
}
}
if (this.ignoreUrlPatternMatcherStrategyClass != null) {
this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
}
}
final Class<? extends GatewayResolver> gatewayStorageClass = getClass(ConfigurationKeys.GATEWAY_STORAGE_CLASS);
if (gatewayStorageClass != null) {
setGatewayStorage(ReflectUtils.newInstance(gatewayStorageClass));
}
final Class<? extends AuthenticationRedirectStrategy> authenticationRedirectStrategyClass = getClass(ConfigurationKeys.AUTHENTICATION_REDIRECT_STRATEGY_CLASS);
if (authenticationRedirectStrategyClass != null) {
this.authenticationRedirectStrategy = ReflectUtils.newInstance(authenticationRedirectStrategyClass);
}
}
}
@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);
}
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
@Override
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final HttpSession session = request.getSession(false);
final String ticket = request.getParameter(getArtifactParameterName());
final Assertion assertion = session != null ? (Assertion) session
.getAttribute(CONST_CAS_ASSERTION) : null;
final boolean wasGatewayed = session != null
&& session.getAttribute(CONST_CAS_GATEWAY) != null;
if (CommonUtils.isBlank(ticket) && assertion == null && !wasGatewayed) {
log.debug("no ticket and no assertion found");
if (this.gateway) {
log.debug("setting gateway attribute in session");
request.getSession(true).setAttribute(CONST_CAS_GATEWAY, "yes");
}
final String serviceUrl = constructServiceUrl(request, response);
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), serviceUrl, this.renew, this.gateway);
if (log.isDebugEnabled()) {
log.debug("redirecting to \"" + urlToRedirectTo + "\"");
}
response.sendRedirect(urlToRedirectTo);
if (isInternalRequest(request)) {
logger.debug("Request is ignored [internal].");
filterChain.doFilter(request, response);
return;
}
if (session != null) {
log.debug("removing gateway attribute from session");
session.setAttribute(CONST_CAS_GATEWAY, null);
if (isRequestUrlExcluded(request)) {
logger.debug("Request is ignored.");
filterChain.doFilter(request, response);
return;
}
filterChain.doFilter(request, response);
final HttpSession session = request.getSession(false);
final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
if (assertion != null) {
filterChain.doFilter(request, response);
return;
}
final String serviceUrl = constructServiceUrl(request, response);
final String ticket = retrieveTicketFromRequest(request);
final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
filterChain.doFilter(request, response);
return;
}
final String modifiedServiceUrl;
logger.debug("no ticket and no assertion found");
if (this.gateway) {
logger.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
logger.debug("Constructed service url: {}", modifiedServiceUrl);
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway, this.method);
logger.debug("redirecting to \"{}\"", urlToRedirectTo);
this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
}
public final void setRenew(final boolean renew) {
@ -111,7 +230,52 @@ 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());
}
final String requestUri = urlBuffer.toString();
return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
}
public final void setIgnoreUrlPatternMatcherStrategyClass(
final UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass) {
this.ignoreUrlPatternMatcherStrategyClass = ignoreUrlPatternMatcherStrategyClass;
}
}

View File

@ -0,0 +1,46 @@
/**
* 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.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Interface to abstract the authentication strategy for redirecting. The traditional method was to always just redirect,
* but due to AJAX, etc. we may need to support other strategies. This interface is designed to hold that logic such that
* authentication filter class does not get crazily complex.
*
* @author Scott Battaglia
* @since 3.3.0
*/
public interface AuthenticationRedirectStrategy {
/**
* Method name is a bit of a misnomer. This method handles "redirection" for a localized version of redirection (i.e. AJAX might mean an XML fragment that contains the url to go to).
*
* @param request the original HttpServletRequest. MAY NOT BE NULL.
* @param response the original HttpServletResponse. MAY NOT BE NULL.
* @param potentialRedirectUrl the url that might be used (there are no guarantees of course!)
* @throws IOException the exception to throw if there is some type of error. This will bubble up through the filter.
*/
void redirect(HttpServletRequest request, HttpServletResponse response, String potentialRedirectUrl)
throws IOException;
}

View File

@ -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.authentication;
/**
* A pattern matcher that looks inside the url to find the exact pattern specified.
*
* @author Misagh Moayyed
* @since 3.3.1
*/
public final class ContainsPatternUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
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;
}
}

View File

@ -0,0 +1,38 @@
/**
* 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.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Implementation of the {@link AuthenticationRedirectStrategy} class that preserves the original behavior that existed prior to 3.3.0.
*
* @author Scott Battaglia
* @since 3.3.0
*/
public final class DefaultAuthenticationRedirectStrategy implements AuthenticationRedirectStrategy {
@Override
public void redirect(final HttpServletRequest request, final HttpServletResponse response,
final String potentialRedirectUrl) throws IOException {
response.sendRedirect(potentialRedirectUrl);
}
}

View File

@ -0,0 +1,45 @@
/**
* 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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
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);
if (session == null) {
return false;
}
final boolean result = session.getAttribute(CONST_CAS_GATEWAY) != null;
return result;
}
@Override
public String storeGatewayInformation(final HttpServletRequest request, final String serviceUrl) {
request.getSession(true).setAttribute(CONST_CAS_GATEWAY, "yes");
return serviceUrl;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,48 @@
/**
* 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;
/**
* A pattern matcher that produces a successful match if the pattern
* specified matches the given url exactly and equally.
*
* @author Misagh Moayyed
* @since 3.3.1
*/
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;
}
}

View File

@ -0,0 +1,54 @@
/**
* 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.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jasig.cas.client.util.CommonUtils;
/**
* Implementation of the redirect strategy that can handle a Faces Ajax request in addition to the standard redirect style.
*
* @author Scott Battaglia
* @since 3.3.0
*/
public final class FacesCompatibleAuthenticationRedirectStrategy implements AuthenticationRedirectStrategy {
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 {
if (CommonUtils.isNotBlank(request.getParameter(FACES_PARTIAL_AJAX_PARAMETER))) {
// this is an ajax request - redirect ajaxly
response.setContentType("text/xml");
response.setStatus(200);
final PrintWriter writer = response.getWriter();
writer.write("<?xml version='1.0' encoding='UTF-8'?>");
writer.write(String.format("<partial-response><redirect url=\"%s\"></redirect></partial-response>",
potentialRedirectUrl));
} else {
response.sendRedirect(potentialRedirectUrl);
}
}
}

View File

@ -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.authentication;
import javax.servlet.http.HttpServletRequest;
/**
* Implementations of this should only have a default constructor if
* you plan on constructing them via the web.xml.
*
* @author Scott Battaglia
* @version $Revision$
* @since 1.0
*
*/
public interface GatewayResolver {
/**
* Determines if the request has been gatewayed already. Should also do gateway clean up.
*
* @param request the Http Servlet Request
* @param serviceUrl the service url
* @return true if yes, false otherwise.
*/
boolean hasGatewayedAlready(HttpServletRequest request, String serviceUrl);
/**
* Storage the request for gatewaying and return the service url, which can be modified.
*
* @param request the HttpServletRequest.
* @param serviceUrl the service url
* @return the potentially modified service url to redirect to
*/
String storeGatewayInformation(HttpServletRequest request, String serviceUrl);
}

View File

@ -0,0 +1,57 @@
/**
* 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#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);
}
}

View File

@ -0,0 +1,75 @@
/**
* 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.security.Principal;
import java.security.acl.Group;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
/**
* Simple security group implementation
*
* @author Marvin S. Addison
* @version $Revision$
* @since 3.1.11
*
*/
public final class SimpleGroup extends SimplePrincipal implements Group {
/** SimpleGroup.java */
private static final long serialVersionUID = 4382154818494550205L;
/** Group members */
private final Set<Principal> members = new HashSet<Principal>();
/**
* Creates a new group with the given name.
* @param name Group name.
*/
public SimpleGroup(final String name) {
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);
}
public String toString() {
return super.toString() + ": " + members.toString();
}
}

View File

@ -0,0 +1,72 @@
/**
* 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.io.Serializable;
import java.security.Principal;
import org.jasig.cas.client.util.CommonUtils;
/**
* Simple security principal implementation.
*
* @author Marvin S. Addison
* @version $Revision$
* @since 3.1.11
*
*/
public class SimplePrincipal implements Principal, Serializable {
/** SimplePrincipal.java */
private static final long serialVersionUID = -5645357206342793145L;
/** The unique identifier for this principal. */
private final String name;
/**
* Creates a new principal with the given name.
* @param name Principal name.
*/
public SimplePrincipal(final String name) {
this.name = name;
CommonUtils.assertNotNull(this.name, "name cannot be null.");
}
@Override
public final String getName() {
return this.name;
}
public String toString() {
return getName();
}
public boolean equals(final Object o) {
if (o == null) {
return false;
} else if (!(o instanceof SimplePrincipal)) {
return false;
} else {
return getName().equals(((SimplePrincipal) o).getName());
}
}
public int hashCode() {
return 37 * getName().hashCode();
}
}

View File

@ -0,0 +1,42 @@
/**
* 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;
/**
* Defines an abstraction by which request urls can be matches against a given pattern.
* New instances for all extensions for this strategy interface will be created per
* each request. The client will ultimately invoke the {@link #matches(String)} method
* having already applied and set the pattern via the {@link #setPattern(String)} method.
* The pattern itself will be retrieved via the client configuration.
* @author Misagh Moayyed
* @since 3.3.1
*/
public interface UrlPatternMatcherStrategy {
/**
* Execute the match between the given pattern and the url
* @param url the request url typically with query strings included
* @return true if match is successful
*/
boolean matches(String url);
/**
* The pattern against which the url is compared
* @param pattern
*/
void setPattern(String pattern);
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,58 @@
/**
* 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.jaas;
import java.io.Serializable;
import org.jasig.cas.client.authentication.SimplePrincipal;
import org.jasig.cas.client.validation.Assertion;
/**
* Principal implementation that contains the CAS ticket validation assertion.
*
* @author Marvin S. Addison
* @version $Revision$
* @since 3.1.11
*
*/
public class AssertionPrincipal extends SimplePrincipal implements Serializable {
/** AssertionPrincipal.java */
private static final long serialVersionUID = 2288520214366461693L;
/** CAS assertion describing authenticated state */
private final Assertion assertion;
/**
* Creates a new principal containing the CAS assertion.
*
* @param name Principal name.
* @param assertion CAS assertion.
*/
public AssertionPrincipal(final String name, final Assertion assertion) {
super(name);
this.assertion = assertion;
}
/**
* @return CAS ticket validation assertion.
*/
public Assertion getAssertion() {
return this.assertion;
}
}

View File

@ -0,0 +1,588 @@
/**
* 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.jaas;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.security.Principal;
import java.security.acl.Group;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import org.jasig.cas.client.authentication.SimpleGroup;
import org.jasig.cas.client.authentication.SimplePrincipal;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.TicketValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JAAS login module that delegates to a CAS {@link TicketValidator} component
* for authentication, and on success populates a {@link Subject} with principal
* data including NetID and principal attributes. The module expects to be provided
* with the CAS ticket (required) and service (optional) parameters via
* {@link PasswordCallback} and {@link NameCallback}, respectively, by the
* {@link CallbackHandler} that is part of the JAAS framework in which the servlet
* resides.
*
* <p>
* Module configuration options:
* <ul>
* <li>ticketValidatorClass - Fully-qualified class name of CAS ticket validator class.</li>
* <li>casServerUrlPrefix - URL to root of CAS Web application context.</li>
* <li>service (optional) - CAS service parameter that may be overridden by callback handler.
* NOTE: service must be specified by at least one component such that it is available at
* service ticket validation time</li>
* <li>defaultRoles (optional) - Comma-delimited list of static roles applied to all
* authenticated principals.</li>
* <li>roleAttributeNames (optional) - Comma-delimited list of attribute names that describe
* role data delivered to CAS in the service-ticket validation response that should be
* applied to the current authenticated principal.</li>
* <li>principalGroupName (optional) - The name of a group principal containing the
* primary principal name of the current JAAS subject. The default value is "CallerPrincipal",
* which is suitable for JBoss.</li>
* <li>roleGroupName (optional) - The name of a group principal containing all role data.
* The default value is "Roles", which is suitable for JBoss.</li>
* <li>cacheAssertions (optional) - Flag to enable assertion caching. This may be needed
* for JAAS providers that attempt to periodically reauthenticate to renew principal.
* Since CAS tickets are one-time-use, a cached assertion must be provided on reauthentication.</li>
* <li>cacheTimeout (optional) - Assertion cache timeout in minutes.</li>
* <li>cacheTimeoutUnit (optional) - Assertion cache timeout unit. Must be one of {@link TimeUnit} enumeration
* names, e.g. DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS. Default unit is MINUTES.</li>
* </ul>
*
* <p>
* Module options not explicitly listed above are treated as attributes of the
* given ticket validator class, e.g. <code>tolerance</code> in the following example.
*
* <p>
* Sample jaas.config file entry for this module:
* <pre>
* cas {
* org.jasig.cas.client.jaas.CasLoginModule required
* ticketValidatorClass="org.jasig.cas.client.validation.Saml11TicketValidator"
* casServerUrlPrefix="https://cas.example.com/cas"
* tolerance="20000"
* service="https://webapp.example.com/webapp"
* defaultRoles="admin,operator"
* roleAttributeNames="memberOf,eduPersonAffiliation"
* principalGroupName="CallerPrincipal"
* roleGroupName="Roles";
* }
* </pre>
*
* @author Marvin S. Addison
* @version $Revision$ $Date$
* @since 3.1.11
*
*/
public class CasLoginModule implements LoginModule {
/** Constant for login name stored in shared state. */
public static final String LOGIN_NAME = "javax.security.auth.login.name";
/**
* Default group name for storing caller principal.
* The default value supports JBoss, but is configurable to hopefully
* support other JEE containers.
*/
public static final String DEFAULT_PRINCIPAL_GROUP_NAME = "CallerPrincipal";
/**
* Default group name for storing role membership data.
* The default value supports JBoss, but is configurable to hopefully
* support other JEE containers.
*/
public static final String DEFAULT_ROLE_GROUP_NAME = "Roles";
/**
* Default assertion cache timeout in minutes. Default is 8 hours.
*/
public static final int DEFAULT_CACHE_TIMEOUT = 480;
/** Default assertion cache timeout unit is minutes. */
public static final TimeUnit DEFAULT_CACHE_TIMEOUT_UNIT = TimeUnit.MINUTES;
/**
* Stores mapping of ticket to assertion to support JAAS providers that
* attempt to periodically re-authenticate to renew principal. Since
* CAS tickets are one-time-use, a cached assertion must be provided on
* re-authentication.
*/
protected static final Map<TicketCredential, Assertion> ASSERTION_CACHE = new HashMap<TicketCredential, Assertion>();
/** Logger instance */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** JAAS authentication subject */
protected Subject subject;
/** JAAS callback handler */
protected CallbackHandler callbackHandler;
/** CAS ticket validator */
protected TicketValidator ticketValidator;
/** CAS service parameter used if no service is provided via TextCallback on login */
protected String service;
/** CAS assertion */
protected Assertion assertion;
/** CAS ticket credential */
protected TicketCredential ticket;
/** Login module shared state */
protected Map<String, Object> sharedState;
/** Roles to be added to all authenticated principals by default */
protected String[] defaultRoles;
/** Names of attributes in the CAS assertion that should be used for role data */
protected final Set<String> roleAttributeNames = new HashSet<String>();
/** Name of JAAS Group containing caller principal */
protected String principalGroupName = DEFAULT_PRINCIPAL_GROUP_NAME;
/** Name of JAAS Group containing role data */
protected String roleGroupName = DEFAULT_ROLE_GROUP_NAME;
/** Enables or disable assertion caching */
protected boolean cacheAssertions;
/** Assertion cache timeout in minutes */
protected int cacheTimeout = DEFAULT_CACHE_TIMEOUT;
/** Units of cache timeout. */
protected TimeUnit cacheTimeoutUnit = DEFAULT_CACHE_TIMEOUT_UNIT;
/**
* Initializes the CAS login module.
*
* @param subject Authentication subject.
* @param handler Callback handler.
* @param state Shared state map.
* @param options Login module options. The following are supported:
* <ul>
* <li>service - CAS service URL used for service ticket validation.</li>
* <li>ticketValidatorClass - fully-qualified class name of service ticket validator component.</li>
* <li>defaultRoles (optional) - comma-delimited list of roles to be added to all authenticated principals.</li>
* <li>roleAttributeNames (optional) - comma-delimited list of attributes in the CAS assertion that contain role data.</li>
* <li>principalGroupName (optional) - name of JAAS Group containing caller principal.</li>
* <li>roleGroupName (optional) - name of JAAS Group containing role data</li>
* <li>cacheAssertions (optional) - whether or not to cache assertions.
* Some JAAS providers attempt to reauthenticate users after an indeterminate
* period of time. Since the credential used for authentication is a CAS ticket,
* which by default are single use, reauthentication fails. Assertion caching addresses this
* behavior.</li>
* <li>cacheTimeout (optional) - assertion cache timeout in minutes.</li>
* <li>cacheTimeoutUnit (optional) - Assertion cache timeout unit. Must be one of {@link TimeUnit} enumeration
* 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) {
this.assertion = null;
this.callbackHandler = handler;
this.subject = subject;
this.sharedState = (Map<String, Object>) state;
this.sharedState = new HashMap<String, Object>(state);
String ticketValidatorClass = null;
for (final String key : options.keySet()) {
logger.trace("Processing option {}", key);
if ("service".equals(key)) {
this.service = (String) options.get(key);
logger.debug("Set service={}", this.service);
} else if ("ticketValidatorClass".equals(key)) {
ticketValidatorClass = (String) options.get(key);
logger.debug("Set ticketValidatorClass={}", ticketValidatorClass);
} else if ("defaultRoles".equals(key)) {
final String roles = (String) options.get(key);
logger.trace("Got defaultRoles value {}", roles);
this.defaultRoles = roles.split(",\\s*");
logger.debug("Set defaultRoles={}", Arrays.asList(this.defaultRoles));
} else if ("roleAttributeNames".equals(key)) {
final String attrNames = (String) options.get(key);
logger.trace("Got roleAttributeNames value {}", attrNames);
final String[] attributes = attrNames.split(",\\s*");
this.roleAttributeNames.addAll(Arrays.asList(attributes));
logger.debug("Set roleAttributeNames={}", this.roleAttributeNames);
} else if ("principalGroupName".equals(key)) {
this.principalGroupName = (String) options.get(key);
logger.debug("Set principalGroupName={}", this.principalGroupName);
} else if ("roleGroupName".equals(key)) {
this.roleGroupName = (String) options.get(key);
logger.debug("Set roleGroupName={}", this.roleGroupName);
} else if ("cacheAssertions".equals(key)) {
this.cacheAssertions = Boolean.parseBoolean((String) options.get(key));
logger.debug("Set cacheAssertions={}", this.cacheAssertions);
} else if ("cacheTimeout".equals(key)) {
this.cacheTimeout = Integer.parseInt((String) options.get(key));
logger.debug("Set cacheTimeout={}", this.cacheTimeout);
} else if ("cacheTimeoutUnit".equals(key)) {
this.cacheTimeoutUnit = Enum.valueOf(TimeUnit.class, (String) options.get(key));
logger.debug("Set cacheTimeoutUnit={}", this.cacheTimeoutUnit);
}
}
if (this.cacheAssertions) {
cleanCache();
}
CommonUtils.assertNotNull(ticketValidatorClass, "ticketValidatorClass is required.");
this.ticketValidator = createTicketValidator(ticketValidatorClass, options);
}
/**
* Operations to perform before doing login.
*
* @return true if you'd like login to continue, false otherwise.
*/
protected boolean preLogin() {
return true;
}
/**
* This occurs after logout is processed.
*
* @param result the result from the login attempt.
*/
protected void postLogin(final boolean result) {
// template method
}
@Override
public final boolean login() throws LoginException {
logger.debug("Performing login.");
if (!preLogin()) {
logger.debug("preLogin failed.");
return false;
}
final NameCallback serviceCallback = new NameCallback("service");
final PasswordCallback ticketCallback = new PasswordCallback("ticket", false);
boolean result = false;
try {
try {
this.callbackHandler.handle(new Callback[] { ticketCallback, serviceCallback });
} catch (final IOException 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);
throw (LoginException) new LoginException(
"Callback handler does not support PasswordCallback and TextInputCallback.").initCause(e);
}
if (ticketCallback.getPassword() != null) {
this.ticket = new TicketCredential(new String(ticketCallback.getPassword()));
final String service = CommonUtils.isNotBlank(serviceCallback.getName()) ? serviceCallback.getName()
: this.service;
if (this.cacheAssertions) {
this.assertion = ASSERTION_CACHE.get(ticket);
if (this.assertion != null) {
logger.debug("Assertion found in cache.");
}
}
if (this.assertion == null) {
logger.debug("CAS assertion is null; ticket validation required.");
if (CommonUtils.isBlank(service)) {
logger.info("Login failed because required CAS service parameter not provided.");
throw new LoginException(
"Neither login module nor callback handler provided required service parameter.");
}
try {
logger.debug("Attempting ticket validation with service={} and ticket={}", service,
this.ticket);
this.assertion = this.ticketValidator.validate(this.ticket.getName(), service);
} catch (final Exception e) {
logger.info("Login failed due to CAS ticket validation failure", e);
throw (LoginException) new LoginException("CAS ticket validation failed: " + e).initCause(e);
}
}
logger.info("Login succeeded.");
} else {
logger.info("Login failed because callback handler did not provide CAS ticket.");
throw new LoginException("Callback handler did not provide CAS ticket.");
}
result = true;
} finally {
postLogin(result);
}
return result;
}
@Override
public final boolean abort() throws LoginException {
if (this.ticket != null) {
this.ticket = null;
}
if (this.assertion != null) {
this.assertion = null;
}
return true;
}
/**
* Operations to perform before doing commit.
*
* @return true if you'd like commit to continue, false otherwise.
*/
protected boolean preCommit() {
return true;
}
/**
* This occurs after commit is processed.
*
* @param result the result from the login attempt.
*/
protected void postCommit(final boolean result) {
// template method
}
@Override
public final boolean commit() throws LoginException {
if (!preCommit()) {
return false;
}
boolean result = false;
try {
if (this.assertion != null) {
if (this.ticket != null) {
this.subject.getPrivateCredentials().add(this.ticket);
} else {
throw new LoginException("Ticket credential not found.");
}
final AssertionPrincipal casPrincipal = new AssertionPrincipal(this.assertion.getPrincipal().getName(),
this.assertion);
this.subject.getPrincipals().add(casPrincipal);
// Add group containing principal as sole member
// Supports JBoss JAAS use case
final Group principalGroup = new SimpleGroup(this.principalGroupName);
principalGroup.addMember(casPrincipal);
this.subject.getPrincipals().add(principalGroup);
// Add group principal containing role data
final Group roleGroup = new SimpleGroup(this.roleGroupName);
for (final String defaultRole : defaultRoles) {
roleGroup.addMember(new SimplePrincipal(defaultRole));
}
final Map<String, Object> attributes = this.assertion.getPrincipal().getAttributes();
for (final String key : attributes.keySet()) {
if (this.roleAttributeNames.contains(key)) {
// Attribute value is Object if singular or Collection if plural
final Object value = attributes.get(key);
if (value instanceof Collection<?>) {
for (final Object o : (Collection<?>) value) {
roleGroup.addMember(new SimplePrincipal(o.toString()));
}
} else {
roleGroup.addMember(new SimplePrincipal(value.toString()));
}
}
}
this.subject.getPrincipals().add(roleGroup);
// Place principal name in shared state for downstream JAAS modules (module chaining use case)
this.sharedState.put(LOGIN_NAME, assertion.getPrincipal().getName());
logger.debug("Created JAAS subject with principals: {}", subject.getPrincipals());
if (this.cacheAssertions) {
logger.debug("Caching assertion for principal {}", this.assertion.getPrincipal());
ASSERTION_CACHE.put(this.ticket, this.assertion);
}
} else {
// Login must have failed if there is no assertion defined
// Need to clean up state
if (this.ticket != null) {
this.ticket = null;
}
}
result = true;
} finally {
postCommit(result);
}
return result;
}
@Override
public final boolean logout() throws LoginException {
logger.debug("Performing logout.");
if (!preLogout()) {
return false;
}
// Remove cache entry if assertion caching is enabled
if (this.cacheAssertions) {
for (final TicketCredential ticket : this.subject.getPrivateCredentials(TicketCredential.class)) {
logger.debug("Removing cached assertion for {}", ticket);
ASSERTION_CACHE.remove(ticket);
}
}
// Remove all CAS principals
removePrincipalsOfType(AssertionPrincipal.class);
removePrincipalsOfType(SimplePrincipal.class);
removePrincipalsOfType(SimpleGroup.class);
// Remove all CAS credentials
removeCredentialsOfType(TicketCredential.class);
logger.info("Logout succeeded.");
postLogout();
return true;
}
/**
* Happens before logout occurs.
*
* @return true if we should continue, false otherwise.
*/
protected boolean preLogout() {
return true;
}
/**
* Happens after logout.
*/
protected void postLogout() {
// template method
}
/**
* Creates a {@link TicketValidator} instance from a class name and map of property name/value pairs.
* @param className Fully-qualified name of {@link TicketValidator} concrete class.
* @param propertyMap Map of property name/value pairs to set on validator instance.
* @return Ticket validator with properties set.
*/
private TicketValidator createTicketValidator(final String className, final Map<String, ?> propertyMap) {
CommonUtils.assertTrue(propertyMap.containsKey("casServerUrlPrefix"),
"Required property casServerUrlPrefix not found.");
final Class<TicketValidator> validatorClass = ReflectUtils.loadClass(className);
final TicketValidator validator = ReflectUtils.newInstance(validatorClass,
propertyMap.get("casServerUrlPrefix"));
try {
final BeanInfo info = Introspector.getBeanInfo(validatorClass);
for (final String property : propertyMap.keySet()) {
if (!"casServerUrlPrefix".equals(property)) {
logger.debug("Attempting to set TicketValidator property {}", property);
final String value = (String) propertyMap.get(property);
final PropertyDescriptor pd = ReflectUtils.getPropertyDescriptor(info, property);
if (pd != null) {
ReflectUtils.setProperty(property, convertIfNecessary(pd, value), validator, info);
logger.debug("Set {} = {}", property, value);
} else {
logger.warn("Cannot find property {} on {}", property, className);
}
}
}
} catch (final IntrospectionException e) {
throw new RuntimeException("Error getting bean info for " + validatorClass, e);
}
return validator;
}
/**
* Attempts to do simple type conversion from a string value to the type expected
* by the given property.
*
* Currently only conversion to int, long, and boolean are supported.
*
* @param pd Property descriptor of target property to set.
* @param value Property value as a string.
* @return Value converted to type expected by property if a conversion strategy exists.
*/
private static Object convertIfNecessary(final PropertyDescriptor pd, final String value) {
if (String.class.equals(pd.getPropertyType())) {
return value;
} else if (boolean.class.equals(pd.getPropertyType())) {
return Boolean.valueOf(value);
} else if (int.class.equals(pd.getPropertyType())) {
return new Integer(value);
} else if (long.class.equals(pd.getPropertyType())) {
return new Long(value);
} else {
throw new IllegalArgumentException("No conversion strategy exists for property " + pd.getName()
+ " of type " + pd.getPropertyType());
}
}
/**
* Removes all principals of the given type from the JAAS subject.
* @param clazz Type of principal to remove.
*/
private void removePrincipalsOfType(final Class<? extends Principal> clazz) {
this.subject.getPrincipals().removeAll(this.subject.getPrincipals(clazz));
}
/**
* Removes all credentials of the given type from the JAAS subject.
* @param clazz Type of principal to remove.
*/
private void removeCredentialsOfType(final Class<? extends Principal> clazz) {
this.subject.getPrivateCredentials().removeAll(this.subject.getPrivateCredentials(clazz));
}
/**
* Removes expired entries from the assertion cache.
*/
private void cleanCache() {
logger.debug("Cleaning assertion cache of size {}", ASSERTION_CACHE.size());
final Iterator<Map.Entry<TicketCredential, Assertion>> iter = ASSERTION_CACHE.entrySet().iterator();
final Calendar cutoff = Calendar.getInstance();
cutoff.setTimeInMillis(System.currentTimeMillis() - this.cacheTimeoutUnit.toMillis(this.cacheTimeout));
while (iter.hasNext()) {
final Assertion assertion = iter.next().getValue();
final Calendar created = Calendar.getInstance();
created.setTime(assertion.getValidFromDate());
if (created.before(cutoff)) {
logger.debug("Removing expired assertion for principal {}", assertion.getPrincipal());
iter.remove();
}
}
}
}

View File

@ -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.jaas;
import java.io.IOException;
import javax.security.auth.callback.*;
/**
* Callback handler that provides the CAS service and ticket to a
* {@link NameCallback} and {@link PasswordCallback} respectively,
* which meets the requirements of the {@link CasLoginModule} JAAS module.
*
* @author Marvin S. Addison
* @version $Revision$
* @since 3.1.11
*
*/
public class ServiceAndTicketCallbackHandler implements CallbackHandler {
/** CAS service URL */
private final String service;
/** CAS service ticket */
private final String ticket;
/**
* Creates a new instance with the given service and ticket.
*
* @param service CAS service URL.
* @param ticket CAS service ticket.
*/
public ServiceAndTicketCallbackHandler(final String service, final String ticket) {
this.service = service;
this.ticket = ticket;
}
@Override
public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (final Callback callback : callbacks) {
if (callback instanceof NameCallback) {
((NameCallback) callback).setName(this.service);
} else if (callback instanceof PasswordCallback) {
((PasswordCallback) callback).setPassword(this.ticket.toCharArray());
} else {
throw new UnsupportedCallbackException(callback, "Callback not supported.");
}
}
}
}

View File

@ -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.jaas;
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.servlet.FilterChain;
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 org.jasig.cas.client.Protocol;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
/**
* Servlet filter performs a programmatic JAAS login using the Servlet 3.0 HttpServletRequest#login() facility.
* This component should be compatible with any servlet container that supports the Servlet 3.0/JEE6 specification.
* <p>
* The filter executes when it receives a CAS ticket and expects the
* {@link CasLoginModule} JAAS module to perform the CAS
* ticket validation in order to produce an {@link org.jasig.cas.client.jaas.AssertionPrincipal} from which
* the CAS assertion is obtained and inserted into the session to enable SSO.
* <p>
* If a <code>service</code> init-param is specified for this filter, it supersedes
* the service defined for the {@link CasLoginModule}.
*
* @author Daniel Fisher
* @author Marvin S. Addison
* @since 3.3
*/
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 HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final HttpSession session = request.getSession();
final String ticket = CommonUtils.safeGetParameter(request, getProtocol().getArtifactParameterName());
if (session != null && session.getAttribute(CONST_CAS_ASSERTION) == null && ticket != null) {
try {
final String service = constructServiceUrl(request, response);
logger.debug("Attempting CAS ticket validation with service={} and ticket={}", service, ticket);
request.login(service, ticket);
if (request.getUserPrincipal() instanceof AssertionPrincipal) {
final AssertionPrincipal principal = (AssertionPrincipal) request.getUserPrincipal();
logger.debug("Installing CAS assertion into session.");
request.getSession().setAttribute(CONST_CAS_ASSERTION, principal.getAssertion());
} else {
logger.debug("Aborting -- principal is not of type AssertionPrincipal");
throw new GeneralSecurityException("JAAS authentication did not produce CAS AssertionPrincipal.");
}
} catch (final ServletException e) {
logger.debug("JAAS authentication failed.");
response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
} catch (final GeneralSecurityException e) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
}
} else if (session != null && request.getUserPrincipal() == null) {
// There is evidence that in some cases the principal can disappear
// in JBoss despite a valid session.
// This block forces consistency between principal and assertion.
logger.info("User principal not found. Removing CAS assertion from session to force re-authentication.");
session.removeAttribute(CONST_CAS_ASSERTION);
}
chain.doFilter(request, response);
}
}

View File

@ -0,0 +1,75 @@
/**
* 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.jaas;
import java.security.Principal;
/**
* Strongly-typed wrapper for a ticket credential.
*
* @author Marvin S. Addison
* @version $Revision$ $Date$
* @since 3.1.12
*
*/
public final class TicketCredential implements Principal {
/** Hash code seed value */
private static final int HASHCODE_SEED = 17;
/** Ticket ID string */
private final String ticket;
/**
* Creates a new instance that wraps the given ticket.
* @param ticket Ticket identifier string.
*/
public TicketCredential(final String ticket) {
this.ticket = ticket;
}
@Override
public String getName() {
return this.ticket;
}
public String toString() {
return this.ticket;
}
public boolean equals(final Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
final TicketCredential that = (TicketCredential) o;
if (ticket != null ? !ticket.equals(that.ticket) : that.ticket != null)
return false;
return true;
}
public int hashCode() {
int hash = HASHCODE_SEED;
hash = hash * 31 + (ticket == null ? 0 : ticket.hashCode());
return hash;
}
}

View File

@ -0,0 +1,112 @@
/**
* 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.proxy;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
/**
* Provides encryption capabilities. Not entirely safe to configure since we have no way of controlling the
* key and cipher being set.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.2.0
*/
public abstract class AbstractEncryptedProxyGrantingTicketStorageImpl implements ProxyGrantingTicketStorage {
private Key key;
private String cipherAlgorithm = ConfigurationKeys.CIPHER_ALGORITHM.getDefaultValue();
public final void setSecretKey(final String key) throws NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
this.key = SecretKeyFactory.getInstance(this.cipherAlgorithm).generateSecret(new DESedeKeySpec(key.getBytes()));
}
public final void setSecretKey(final Key key) {
this.key = key;
}
/**
* Note: you MUST call this method before calling setSecretKey if you're not using the default algorithm. You've been warned.
*
* @param cipherAlgorithm the cipher algorithm.
*/
public final void setCipherAlgorithm(final String cipherAlgorithm) {
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));
}
protected abstract void saveInternal(String proxyGrantingTicketIou, String proxyGrantingTicket);
protected abstract String retrieveInternal(String proxyGrantingTicketIou);
private String encrypt(final String value) {
if (this.key == null) {
return value;
}
if (value == null) {
return null;
}
try {
final Cipher cipher = Cipher.getInstance(this.cipherAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, this.key);
return new String(cipher.doFinal(value.getBytes()));
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
private String decrypt(final String value) {
if (this.key == null) {
return value;
}
if (value == null) {
return null;
}
try {
final Cipher cipher = Cipher.getInstance(this.cipherAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, this.key);
return new String(cipher.doFinal(value.getBytes()));
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,105 +1,110 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.proxy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of a ProxyRetriever that follows the CAS 2.0 specification.
* For more information on the CAS 2.0 specification, please see the <a
* href="http://www.ja-sig.org/products/cas/overview/protocol/index.html">specification
* href="http://www.jasig.org/cas/protocol">specification
* document</a>.
* <p/>
* In general, this class will make a call to the CAS server with some specified
* parameters and receive an XML response to parse.
*
* @author Scott Battaglia
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
* @since 3.0
*/
public final class Cas20ProxyRetriever implements ProxyRetriever {
/**
* Instance of Commons Logging.
*/
private final Log log = LogFactory.getLog(this.getClass());
/** Unique Id for serialization. */
private static final long serialVersionUID = 560409469568911792L;
private static final Logger logger = LoggerFactory.getLogger(Cas20ProxyRetriever.class);
/**
* Url to CAS server.
*/
private final String casServerUrl;
private final String encoding;
/** Url connection factory to use when communicating with the server **/
private final HttpURLConnectionFactory urlConnectionFactory;
@Deprecated
public Cas20ProxyRetriever(final String casServerUrl, final String encoding) {
this(casServerUrl, encoding, null);
}
/**
* Main Constructor.
*
* @param casServerUrl the URL to the CAS server (i.e. http://localhost/cas/)
* @param encoding the encoding to use.
* @param urlFactory url connection factory use when retrieving proxy responses from the server
*/
public Cas20ProxyRetriever(final String casServerUrl) {
CommonUtils.assertNotNull(casServerUrl,
"casServerUrl cannot be null.");
public Cas20ProxyRetriever(final String casServerUrl, final String encoding,
final HttpURLConnectionFactory urlFactory) {
CommonUtils.assertNotNull(casServerUrl, "casServerUrl cannot be null.");
this.casServerUrl = casServerUrl;
this.encoding = encoding;
this.urlConnectionFactory = urlFactory;
}
public String getProxyTicketIdFor(final String proxyGrantingTicketId,
final String targetService) {
@Override
public String getProxyTicketIdFor(final String proxyGrantingTicketId, final String targetService) {
CommonUtils.assertNotNull(proxyGrantingTicketId, "proxyGrantingTicketId cannot be null.");
CommonUtils.assertNotNull(targetService, "targetService cannot be null.");
final String url = constructUrl(proxyGrantingTicketId, targetService);
HttpURLConnection conn = null;
try {
final URL constructedUrl = new URL(url);
conn = (HttpURLConnection) constructedUrl.openConnection();
final URL url = constructUrl(proxyGrantingTicketId, targetService);
final String response;
final BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
final StringBuffer stringBuffer = new StringBuffer(255);
final String response;
synchronized (stringBuffer) {
while ((line = in.readLine()) != null) {
stringBuffer.append(line);
}
response = stringBuffer.toString();
}
final String error = XmlUtils.getTextForElement(response,
"proxyFailure");
if (CommonUtils.isNotEmpty(error)) {
log.debug(error);
return null;
}
return XmlUtils.getTextForElement(response, "proxyTicket");
} catch (final Exception e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
conn.disconnect();
}
if (this.urlConnectionFactory != null) {
response = CommonUtils.getResponseFromServer(url, this.urlConnectionFactory, this.encoding);
} else {
response = CommonUtils.getResponseFromServer(url, this.encoding);
}
final String error = XmlUtils.getTextForElement(response, "proxyFailure");
if (CommonUtils.isNotEmpty(error)) {
logger.debug(error);
return null;
}
final String ticket = XmlUtils.getTextForElement(response, "proxyTicket");
logger.debug("Got proxy ticket {}", ticket);
return ticket;
}
private String constructUrl(final String proxyGrantingTicketId,
final String targetService) {
private URL constructUrl(final String proxyGrantingTicketId, final String targetService) {
try {
return this.casServerUrl + "proxy" + "?pgt="
+ proxyGrantingTicketId + "&targetService="
+ URLEncoder.encode(targetService, "UTF-8");
} catch (final UnsupportedEncodingException e) {
return new URL(this.casServerUrl + (this.casServerUrl.endsWith("/") ? "" : "/") + "proxy" + "?pgt="
+ proxyGrantingTicketId + "&targetService=" + URLEncoder.encode(targetService, "UTF-8"));
} catch (final Exception e) {
throw new RuntimeException(e);
}
}

View File

@ -0,0 +1,46 @@
/**
* 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.proxy;
import java.util.TimerTask;
/**
* A {@link TimerTask} implementation which performs the
* actual 'cleaning' by calling {@link ProxyGrantingTicketStorage#cleanUp()}.
* <p>
* By default, the {@link org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter} configures
* a task that cleans up the {@link org.jasig.cas.client.proxy.ProxyGrantingTicketStorage} associated with it.
*
* @author Brad Cupit (brad [at] lsu {dot} edu)
* @version $Revision$ $Date$
* @since 3.1.6
*/
public final class CleanUpTimerTask extends TimerTask {
private final ProxyGrantingTicketStorage proxyGrantingTicketStorage;
public CleanUpTimerTask(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
}
@Override
public void run() {
this.proxyGrantingTicketStorage.cleanUp();
}
}

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.proxy;
@ -10,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 {
@ -33,4 +45,10 @@ public interface ProxyGrantingTicketStorage {
* @return the ProxyGrantingTicket Id or null if it can't be found
*/
public String retrieve(String proxyGrantingTicketIou);
/**
* Called on a regular basis by an external timer,
* giving implementations a chance to remove stale data.
*/
public void cleanUp();
}

View File

@ -1,28 +1,44 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of {@link ProxyGrantingTicketStorage} that is backed by a
* HashMap that keeps a ProxyGrantingTicket for a specified amount of time.
* <p/>
* A cleanup thread is run periodically to clean out the HashMap.
* <p>
* {@link ProxyGrantingTicketStorage#cleanUp()} must be called on a regular basis to
* keep the HashMap from growing indefinitely.
*
* @author Scott Battaglia
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
* @author Brad Cupit (brad [at] lsu {dot} edu)
* @since 3.0
*/
public final class ProxyGrantingTicketStorageImpl implements
ProxyGrantingTicketStorage {
public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicketStorage {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Default timeout in milliseconds.
@ -32,7 +48,15 @@ public final class ProxyGrantingTicketStorageImpl implements
/**
* Map that stores the PGTIOU to PGT mappings.
*/
private final Map cache = new HashMap();
private final ConcurrentMap<String, ProxyGrantingTicketHolder> cache = new ConcurrentHashMap<String, ProxyGrantingTicketHolder>();
/**
* time, in milliseconds, before a {@link ProxyGrantingTicketHolder}
* is considered expired and ready for removal.
*
* @see ProxyGrantingTicketStorageImpl#DEFAULT_TIMEOUT
*/
private final long timeout;
/**
* Constructor set the timeout to the default value.
@ -48,38 +72,55 @@ public final class ProxyGrantingTicketStorageImpl implements
* @param timeout the time to hold on to the ProxyGrantingTicket
*/
public ProxyGrantingTicketStorageImpl(final long timeout) {
final Thread thread = new ProxyGrantingTicketCleanupThread(
timeout, this.cache);
thread.setDaemon(true);
thread.start();
this.timeout = timeout;
}
/**
* NOTE: you can only retrieve a ProxyGrantingTicket once with this method.
* Its removed after retrieval.
*/
@Override
public String retrieve(final String proxyGrantingTicketIou) {
final ProxyGrantingTicketHolder holder = (ProxyGrantingTicketHolder) this.cache
.get(proxyGrantingTicketIou);
if (holder == null) {
if (CommonUtils.isBlank(proxyGrantingTicketIou)) {
return null;
}
this.cache.remove(holder);
final ProxyGrantingTicketHolder holder = this.cache.get(proxyGrantingTicketIou);
if (holder == null) {
logger.info("No Proxy Ticket found for [{}].", proxyGrantingTicketIou);
return null;
}
this.cache.remove(proxyGrantingTicketIou);
logger.debug("Returned ProxyGrantingTicket of [{}]", holder.getProxyGrantingTicket());
return holder.getProxyGrantingTicket();
}
public void save(final String proxyGrantingTicketIou,
final String proxyGrantingTicket) {
final ProxyGrantingTicketHolder holder = new ProxyGrantingTicketHolder(
proxyGrantingTicket);
@Override
public void save(final String proxyGrantingTicketIou, final String proxyGrantingTicket) {
final ProxyGrantingTicketHolder holder = new ProxyGrantingTicketHolder(proxyGrantingTicket);
logger.debug("Saving ProxyGrantingTicketIOU and ProxyGrantingTicket combo: [{}, {}]", proxyGrantingTicketIou,
proxyGrantingTicket);
this.cache.put(proxyGrantingTicketIou, holder);
}
private final class ProxyGrantingTicketHolder {
/**
* 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)) {
this.cache.remove(holder.getKey());
}
}
}
private static final class ProxyGrantingTicketHolder {
private final String proxyGrantingTicket;
@ -98,48 +139,4 @@ public final class ProxyGrantingTicketStorageImpl implements
return System.currentTimeMillis() - this.timeInserted > timeout;
}
}
private final class ProxyGrantingTicketCleanupThread extends Thread {
private final long timeout;
private final Map cache;
public ProxyGrantingTicketCleanupThread(final long timeout,
final Map cache) {
this.timeout = timeout;
this.cache = cache;
}
public void run() {
while (true) {
try {
Thread.sleep(this.timeout);
} catch (final InterruptedException e) {
// nothing to do
}
final List itemsToRemove = new ArrayList();
synchronized (this.cache) {
for (final Iterator iter = this.cache.keySet().iterator(); iter
.hasNext();) {
final Object key = iter.next();
final ProxyGrantingTicketHolder holder = (ProxyGrantingTicketHolder) this.cache
.get(key);
if (holder.isExpired(this.timeout)) {
itemsToRemove.add(key);
}
}
for (final Iterator iter = itemsToRemove.iterator(); iter
.hasNext();) {
this.cache.remove(iter.next());
}
}
}
}
}
}

View File

@ -1,19 +1,33 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.proxy;
import java.io.Serializable;
/**
* Interface to abstract the retrieval of a proxy ticket to make the
* 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 {
public interface ProxyRetriever extends Serializable {
/**
* Retrieves a proxy ticket for a specific targetService.
@ -22,6 +36,5 @@ public interface ProxyRetriever {
* @param targetService the service we want to proxy.
* @return the ProxyTicket Id if Granted, null otherwise.
*/
String getProxyTicketIdFor(String proxyGrantingTicketId,
String targetService);
String getProxyTicketIdFor(String proxyGrantingTicketId, String targetService);
}

View File

@ -1,3 +1,23 @@
<!--
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.
-->
<html>
<body>
<p>The proxy package includes a servlet to act as a proxy receptor,

View File

@ -1,14 +1,28 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.session;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* HashMap backed implementation of SessionMappingStorage.
@ -18,38 +32,52 @@ import javax.servlet.http.HttpSession;
* @since 3.1
*
*/
public final class HashMapBackedSessionMappingStorage implements
SessionMappingStorage {
public final class HashMapBackedSessionMappingStorage implements SessionMappingStorage {
/**
* Maps the ID from the CAS server to the Session.
*/
private final Map MANAGED_SESSIONS = new HashMap();
private final Map<String, HttpSession> MANAGED_SESSIONS = new HashMap<String, HttpSession>();
/**
* Maps the Session ID to the key from the CAS Server.
*/
private final Map ID_TO_SESSION_KEY_MAPPING = new HashMap();
private final Map<String, String> ID_TO_SESSION_KEY_MAPPING = new HashMap<String, String>();
public void addSessionById(String mappingId, HttpSession session) {
private final Logger logger = LoggerFactory.getLogger(getClass());
@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);
}
}
public void removeBySessionById(String sessionId) {
final String key = (String) ID_TO_SESSION_KEY_MAPPING.get(sessionId);
@Override
public synchronized void removeBySessionById(final String sessionId) {
logger.debug("Attempting to remove Session=[{}]", sessionId);
final String key = ID_TO_SESSION_KEY_MAPPING.get(sessionId);
if (logger.isDebugEnabled()) {
if (key != null) {
logger.debug("Found mapping for session. Session Removed.");
} else {
logger.debug("No mapping for session found. Ignoring.");
}
}
MANAGED_SESSIONS.remove(key);
ID_TO_SESSION_KEY_MAPPING.remove(sessionId);
}
}
public HttpSession removeSessionByMappingId(String mappingId) {
final HttpSession session = (HttpSession) MANAGED_SESSIONS.get(mappingId);
@Override
public synchronized HttpSession removeSessionByMappingId(final String mappingId) {
final HttpSession session = MANAGED_SESSIONS.get(mappingId);
if (session != null) {
removeBySessionById(session.getId());
removeBySessionById(session.getId());
}
return session;
}
}
}

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.session;
@ -16,26 +29,26 @@ import javax.servlet.http.HttpSession;
*
*/
public interface SessionMappingStorage {
/**
* Remove the HttpSession based on the mappingId.
*
* @param mappingId the id the session is keyed under.
* @return the HttpSession if it exists.
*/
HttpSession removeSessionByMappingId(String mappingId);
/**
* Remove a session by its Id.
* @param sessionId the id of the session.
*/
void removeBySessionById(String sessionId);
/**
* Add a session by its mapping Id.
* @param mappingId the id to map the session to.
* @param session the HttpSession.
*/
void addSessionById(String mappingId, HttpSession session);
/**
* Remove the HttpSession based on the mappingId.
*
* @param mappingId the id the session is keyed under.
* @return the HttpSession if it exists.
*/
HttpSession removeSessionByMappingId(String mappingId);
/**
* Remove a session by its Id.
* @param sessionId the id of the session.
*/
void removeBySessionById(String sessionId);
/**
* Add a session by its mapping Id.
* @param mappingId the id to map the session to.
* @param session the HttpSession.
*/
void addSessionById(String mappingId, HttpSession session);
}

View File

@ -1,22 +1,32 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.session;
import org.jasig.cas.client.util.AbstractConfigurationFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
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.HttpSession;
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;
/**
* Implements the Single Sign Out protocol. It handles registering the session and destroying the session.
@ -27,66 +37,70 @@ import java.io.IOException;
*/
public final class SingleSignOutFilter extends AbstractConfigurationFilter {
/**
* The name of the artifact parameter. This is used to capture the session identifier.
*/
private String artifactParameterName = "ticket";
private static SessionMappingStorage SESSION_MAPPING_STORAGE = new HashMapBackedSessionMappingStorage();
private static final SingleSignOutHandler HANDLER = new SingleSignOutHandler();
private final AtomicBoolean handlerInitialized = new AtomicBoolean(false);
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
init();
super.init(filterConfig);
if (!isIgnoreInitConfiguration()) {
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);
}
public void init() {
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
CommonUtils.assertNotNull(SESSION_MAPPING_STORAGE, "sessionMappingStorage cannote be null.");
public void setArtifactParameterName(final String name) {
HANDLER.setArtifactParameterName(name);
}
public void setArtifactParameterName(final String artifactParameterName) {
this.artifactParameterName = artifactParameterName;
public void setLogoutParameterName(final String name) {
HANDLER.setLogoutParameterName(name);
}
public void setRelayStateParameterName(final String name) {
HANDLER.setRelayStateParameterName(name);
}
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
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 HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
if ("POST".equals(request.getMethod())) {
final String logoutRequest = request.getParameter("logoutRequest");
if (CommonUtils.isNotBlank(logoutRequest)) {
final String sessionIdentifier = XmlUtils.getTextForElement(logoutRequest, "SessionIndex");
if (CommonUtils.isNotBlank(sessionIdentifier)) {
final HttpSession session = SESSION_MAPPING_STORAGE.removeSessionByMappingId(sessionIdentifier);
if (session != null) {
session.invalidate();
}
return;
}
}
} else {
final String artifact = request.getParameter(this.artifactParameterName);
final HttpSession session = request.getSession();
if (CommonUtils.isNotBlank(artifact)) {
SESSION_MAPPING_STORAGE.addSessionById(artifact, session);
}
/**
* <p>Workaround for now for the fact that Spring Security will fail since it doesn't call {@link #init(javax.servlet.FilterConfig)}.</p>
* <p>Ultimately we need to allow deployers to actually inject their fully-initialized {@link org.jasig.cas.client.session.SingleSignOutHandler}.</p>
*/
if (!this.handlerInitialized.getAndSet(true)) {
HANDLER.init();
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void setSessionMappingStorage(final SessionMappingStorage storage) {
SESSION_MAPPING_STORAGE = storage;
}
public static SessionMappingStorage getSessionMappingStorage() {
return SESSION_MAPPING_STORAGE;
if (HANDLER.process(request, response)) {
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
// nothing to do
}
protected static SingleSignOutHandler getSingleSignOutHandler() {
return HANDLER;
}
}

View File

@ -0,0 +1,333 @@
/**
* 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.session;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.zip.Inflater;
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.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;
import org.slf4j.LoggerFactory;
/**
* Performs CAS single sign-out operations in an API-agnostic fashion.
*
* @author Marvin S. Addison
* @version $Revision$ $Date$
* @since 3.1.12
*
*/
public final class SingleSignOutHandler {
private final static int DECOMPRESSION_FACTOR = 10;
/** Logger instance */
private final Logger logger = LoggerFactory.getLogger(getClass());
/** Mapping of token IDs and session IDs to HTTP sessions */
private SessionMappingStorage sessionMappingStorage = new HashMapBackedSessionMappingStorage();
/** The name of the artifact parameter. This is used to capture the session identifier. */
private String artifactParameterName = Protocol.CAS2.getArtifactParameterName();
/** Parameter name that stores logout request for SLO */
private String logoutParameterName = ConfigurationKeys.LOGOUT_PARAMETER_NAME.getDefaultValue();
/** 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;
private boolean eagerlyCreateSessions = true;
private List<String> safeParameters;
private final LogoutStrategy logoutStrategy = isServlet30() ? new Servlet30LogoutStrategy() : new Servlet25LogoutStrategy();
public void setSessionMappingStorage(final SessionMappingStorage storage) {
this.sessionMappingStorage = storage;
}
public void setArtifactParameterOverPost(final boolean artifactParameterOverPost) {
this.artifactParameterOverPost = artifactParameterOverPost;
}
public SessionMappingStorage getSessionMappingStorage() {
return this.sessionMappingStorage;
}
/**
* @param name Name of the authentication token parameter.
*/
public void setArtifactParameterName(final String name) {
this.artifactParameterName = name;
}
/**
* @param name Name of parameter containing CAS logout request message for SLO.
*/
public void setLogoutParameterName(final String name) {
this.logoutParameterName = name;
}
/**
* @param logoutCallbackPath The logout callback path configured at the CAS server.
*/
public void setLogoutCallbackPath(final String logoutCallbackPath) {
this.logoutCallbackPath = logoutCallbackPath;
}
/**
* @param name Name of parameter containing the state of the CAS server webflow.
*/
public void setRelayStateParameterName(final String name) {
this.relayStateParameterName = name;
}
public void setEagerlyCreateSessions(final boolean eagerlyCreateSessions) {
this.eagerlyCreateSessions = eagerlyCreateSessions;
}
/**
* Initializes the component for use.
*/
public synchronized void init() {
if (this.safeParameters == null) {
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
CommonUtils.assertNotNull(this.logoutParameterName, "logoutParameterName cannot be null.");
CommonUtils.assertNotNull(this.sessionMappingStorage, "sessionMappingStorage cannot be null.");
CommonUtils.assertNotNull(this.relayStateParameterName, "relayStateParameterName cannot be null.");
if (this.artifactParameterOverPost) {
this.safeParameters = Arrays.asList(this.logoutParameterName, this.artifactParameterName);
} else {
this.safeParameters = Collections.singletonList(this.logoutParameterName);
}
}
}
/**
* Determines whether the given request contains an authentication token.
*
* @param request HTTP reqest.
*
* @return True if request contains authentication token, false otherwise.
*/
private boolean isTokenRequest(final HttpServletRequest request) {
return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.artifactParameterName,
this.safeParameters));
}
/**
* 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 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;
}
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());
}
/**
* Process a request regarding the SLO process: record the session or destroy it.
*
* @param request the incoming HTTP request.
* @param response the HTTP response.
* @return if the request should continue to be processed.
*/
public boolean process(final HttpServletRequest request, final HttpServletResponse response) {
if (isTokenRequest(request)) {
logger.trace("Received a token request");
recordSession(request);
return true;
}
if (isLogoutRequest(request)) {
logger.trace("Received a logout request");
destroySession(request);
return false;
}
logger.trace("Ignoring URI for logout: {}", request.getRequestURI());
return true;
}
/**
* Associates a token request with the current HTTP session by recording the mapping
* in the the configured {@link SessionMappingStorage} container.
*
* @param request HTTP request containing an authentication token.
*/
private void recordSession(final HttpServletRequest request) {
final HttpSession session = request.getSession(this.eagerlyCreateSessions);
if (session == null) {
logger.debug("No session currently exists (and none created). Cannot record session information for single sign out.");
return;
}
final String token = CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters);
logger.debug("Recording session for token {}", token);
try {
this.sessionMappingStorage.removeBySessionById(session.getId());
} catch (final Exception e) {
// ignore if the session is already marked as invalid. Nothing we can do!
}
sessionMappingStorage.addSessionById(token, session);
}
/**
* Uncompress a logout message (base64 + deflate).
*
* @param originalMessage the original logout message.
* @return the uncompressed logout message.
*/
private String uncompressLogoutMessage(final String originalMessage) {
final byte[] binaryMessage = DatatypeConverter.parseBase64Binary(originalMessage);
Inflater decompresser = null;
try {
// decompress the bytes
decompresser = new Inflater();
decompresser.setInput(binaryMessage);
final byte[] result = new byte[binaryMessage.length * DECOMPRESSION_FACTOR];
final int resultLength = decompresser.inflate(result);
// decode the bytes into a String
return new String(result, 0, resultLength, "UTF-8");
} catch (final Exception e) {
logger.error("Unable to decompress logout message", e);
throw new RuntimeException(e);
} finally {
if (decompresser != null) {
decompresser.end();
}
}
}
/**
* Destroys the current HTTP session for the given CAS logout request.
*
* @param request HTTP request containing a CAS logout message.
*/
private void destroySession(final HttpServletRequest request) {
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) {
final String sessionID = session.getId();
logger.debug("Invalidating session [{}] for token [{}]", sessionID, token);
try {
session.invalidate();
} catch (final IllegalStateException e) {
logger.debug("Error invalidating session.", e);
}
this.logoutStrategy.logout(request);
}
}
}
private boolean isMultipartRequest(final HttpServletRequest request) {
return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart");
}
private static boolean isServlet30() {
try {
return HttpServletRequest.class.getMethod("logout") != null;
} catch (final NoSuchMethodException e) {
return false;
}
}
/**
* Abstracts the ways we can force logout with the Servlet spec.
*/
private interface LogoutStrategy {
void logout(HttpServletRequest request);
}
private class Servlet25LogoutStrategy implements LogoutStrategy {
@Override
public void logout(final HttpServletRequest request) {
// nothing additional to do here
}
}
private class Servlet30LogoutStrategy implements LogoutStrategy {
@Override
public void logout(final HttpServletRequest request) {
try {
request.logout();
} catch (final ServletException e) {
logger.debug("Error performing request.logout.");
}
}
}
}

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.session;
@ -21,18 +34,20 @@ import javax.servlet.http.HttpSessionListener;
*/
public final class SingleSignOutHttpSessionListener implements HttpSessionListener {
private SessionMappingStorage SESSION_MAPPING_STORAGE;
private SessionMappingStorage sessionMappingStorage;
@Override
public void sessionCreated(final HttpSessionEvent event) {
// nothing to do at the moment
}
@Override
public void sessionDestroyed(final HttpSessionEvent event) {
if (SESSION_MAPPING_STORAGE == null) {
SESSION_MAPPING_STORAGE = getSessionMappingStorage();
}
if (sessionMappingStorage == null) {
sessionMappingStorage = getSessionMappingStorage();
}
final HttpSession session = event.getSession();
SESSION_MAPPING_STORAGE.removeBySessionById(session.getId());
sessionMappingStorage.removeBySessionById(session.getId());
}
/**
@ -42,6 +57,6 @@ public final class SingleSignOutHttpSessionListener implements HttpSessionListen
* @return the SessionMappingStorage
*/
protected static SessionMappingStorage getSessionMappingStorage() {
return SingleSignOutFilter.getSessionMappingStorage();
return SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage();
}
}

View File

@ -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.ssl;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
/**
* Hostname verifier that performs no host name verification for an SSL peer
* such that all hosts are allowed.
*
* @author Marvin Addison
* @version $Revision$ $Date$
* @since 3.1.10
*/
public final class AnyHostnameVerifier implements HostnameVerifier {
/** {@inheritDoc} */
@Override
public boolean verify(final String hostname, final SSLSession session) {
return true;
}
}

View File

@ -0,0 +1,46 @@
/**
* 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.ssl;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* A factory to prepare and configure {@link java.net.URLConnection} instances.
*
* @author Misagh Moayyed
* @since 3.3
*/
public interface HttpURLConnectionFactory extends Serializable {
/**
* Receives a {@link URLConnection} instance typically as a result of a {@link URL}
* opening a connection to a remote resource. The received url connection is then
* configured and prepared appropriately depending on its type and is then returned to the caller
* to accommodate method chaining.
*
* @param url The url connection that needs to be configured
* @return The configured {@link HttpURLConnection} instance
*
* @see {@link HttpsURLConnectionFactory}
*/
HttpURLConnection buildHttpURLConnection(final URLConnection url);
}

View File

@ -0,0 +1,192 @@
/**
* 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.ssl;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.security.KeyStore;
import java.util.Properties;
import javax.net.ssl.*;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An implementation of the {@link HttpURLConnectionFactory} whose responsible to configure
* the underlying <i>https</i> connection, if needed, with a given hostname and SSL socket factory based on the
* configuration provided.
*
* @author Misagh Moayyed
* @since 3.3
* @see #setHostnameVerifier(HostnameVerifier)
* @see #setSSLConfiguration(Properties)
*/
public final class HttpsURLConnectionFactory implements HttpURLConnectionFactory {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(HttpsURLConnectionFactory.class);
/**
* Hostname verifier used when making an SSL request to the CAS server.
* Defaults to {@link HttpsURLConnection#getDefaultHostnameVerifier()}
*/
private HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
/**
* Properties file that can contains key/trust info for Client Side Certificates
*/
private Properties sslConfiguration = new Properties();
public HttpsURLConnectionFactory() {
}
public HttpsURLConnectionFactory(final HostnameVerifier verifier, final Properties config) {
setHostnameVerifier(verifier);
setSSLConfiguration(config);
}
public final void setSSLConfiguration(final Properties config) {
this.sslConfiguration = config;
}
/**
* Set the host name verifier for the https connection received.
*
* @see AnyHostnameVerifier
* @see RegexHostnameVerifier
* @see WhitelistHostnameVerifier
*/
public final void setHostnameVerifier(final HostnameVerifier verifier) {
this.hostnameVerifier = verifier;
}
@Override
public HttpURLConnection buildHttpURLConnection(final URLConnection url) {
return this.configureHttpsConnectionIfNeeded(url);
}
/**
* Configures the connection with specific settings for secure http connections
* If the connection instance is not a {@link HttpsURLConnection},
* no additional changes will be made and the connection itself is simply returned.
*
* @param conn the http connection
*/
private HttpURLConnection configureHttpsConnectionIfNeeded(final URLConnection conn) {
if (conn instanceof HttpsURLConnection) {
final HttpsURLConnection httpsConnection = (HttpsURLConnection) conn;
final SSLSocketFactory socketFactory = this.createSSLSocketFactory();
if (socketFactory != null) {
httpsConnection.setSSLSocketFactory(socketFactory);
}
if (this.hostnameVerifier != null) {
httpsConnection.setHostnameVerifier(this.hostnameVerifier);
}
}
return (HttpURLConnection) conn;
}
/**
* Creates a {@link SSLSocketFactory} based on the configuration specified
* <p>
* Sample properties file:
* <pre>
* protocol=TLS
* keyStoreType=JKS
* keyStorePath=/var/secure/location/.keystore
* keyStorePass=changeit
* certificatePassword=aGoodPass
* </pre>
* @return the {@link SSLSocketFactory}
*/
private SSLSocketFactory createSSLSocketFactory() {
InputStream keyStoreIS = null;
try {
final SSLContext sslContext = SSLContext.getInstance(this.sslConfiguration.getProperty("protocol", "SSL"));
if (this.sslConfiguration.getProperty("keyStoreType") != null) {
final KeyStore keyStore = KeyStore.getInstance(this.sslConfiguration.getProperty("keyStoreType"));
if (this.sslConfiguration.getProperty("keyStorePath") != null) {
keyStoreIS = new FileInputStream(this.sslConfiguration.getProperty("keyStorePath"));
if (this.sslConfiguration.getProperty("keyStorePass") != null) {
keyStore.load(keyStoreIS, this.sslConfiguration.getProperty("keyStorePass").toCharArray());
LOGGER.debug("Keystore has {} keys", keyStore.size());
final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(this.sslConfiguration
.getProperty("keyManagerType", "SunX509"));
keyManager.init(keyStore, this.sslConfiguration.getProperty("certificatePassword")
.toCharArray());
sslContext.init(keyManager.getKeyManagers(), null, null);
return sslContext.getSocketFactory();
}
}
}
} catch (final Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
CommonUtils.closeQuietly(keyStoreIS);
}
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();
}
}

View File

@ -0,0 +1,56 @@
/**
* 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.ssl;
import java.io.Serializable;
import java.util.regex.Pattern;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
/**
* Validates an SSL peer's hostname using a regular expression that a candidate
* host must match in order to be verified.
*
* @author Marvin Addison
* @version $Revision$ $Date$
* @since 3.1.10
*
*/
public final class RegexHostnameVerifier implements HostnameVerifier, Serializable {
private static final long serialVersionUID = 1L;
/** Allowed hostname pattern */
private final Pattern pattern;
/**
* Creates a new instance using the given regular expression.
*
* @param regex Regular expression describing allowed hosts.
*/
public RegexHostnameVerifier(final String regex) {
this.pattern = Pattern.compile(regex);
}
/** {@inheritDoc} */
@Override
public boolean verify(final String hostname, final SSLSession session) {
return pattern.matcher(hostname).matches();
}
}

View File

@ -0,0 +1,70 @@
/**
* 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.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.
*
* @author Marvin Addison
* @version $Revision$ $Date$
* @since 3.1.10
*
*/
public final class WhitelistHostnameVerifier implements HostnameVerifier, Serializable {
private static final long serialVersionUID = 1L;
/** Allowed hosts */
private final String[] allowedHosts;
/**
* Creates a new instance using the given array of allowed hosts.
*
* @param allowed Array of allowed hosts.
*/
public WhitelistHostnameVerifier(final String[] allowed) {
this.allowedHosts = allowed;
}
/**
* Creates a new instance using the given list of allowed hosts.
*
* @param allowedList Comma-separated list of allowed hosts.
*/
public WhitelistHostnameVerifier(final String allowedList) {
this.allowedHosts = allowedList.split(",\\s*");
}
/** {@inheritDoc} */
@Override
public boolean verify(final String hostname, final SSLSession session) {
for (final String allowedHost : this.allowedHosts) {
if (hostname.equalsIgnoreCase(allowedHost)) {
return true;
}
}
return false;
}
}

View File

@ -1,41 +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.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.
* <p>
* The following filter options can be configured (either at the context-level or filter-level).
* <ul>
* <li><code>serverName</code> - the name of the CAS server, in the format: localhost:8080 or localhost:8443 or localhost</li>
* <li><code>serverName</code> - the name of the CAS client server, in the format: localhost:8080 or localhost:8443 or localhost or https://localhost:8443</li>
* <li><code>service</code> - the completely qualified service url, i.e. https://localhost/cas-client/app</li>
* </ul>
* <p>Please note that one of the two above parameters must be set.</p>
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @author Misagh Moayyed
* @since 3.1
*/
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_";
/** Instance of commons logging for logging purposes. */
protected final Log log = LogFactory.getLog(getClass());
private final Protocol protocol;
/** Defines the parameter to look for for the artifact. */
private String artifactParameterName = "ticket";
/** 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;
@ -47,64 +59,91 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
/** The exact url of the service. */
private String service;
public final void init(final FilterConfig filterConfig) throws ServletException {
setServerName(getPropertyFromInitParams(filterConfig, "serverName", null));
setService(getPropertyFromInitParams(filterConfig, "service", null));
setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
setServiceParameterName(getPropertyFromInitParams(filterConfig, "serviceParameterName", "service"));
setEncodeServiceUrl(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "encodeServiceUrl", "true")));
protected AbstractCasFilter(final Protocol protocol) {
this.protocol = protocol;
}
initInternal(filterConfig);
@Override
public final void init(final FilterConfig filterConfig) throws ServletException {
super.init(filterConfig);
if (!isIgnoreInitConfiguration()) {
setServerName(getString(ConfigurationKeys.SERVER_NAME));
setService(getString(ConfigurationKeys.SERVICE));
setEncodeServiceUrl(getBoolean(ConfigurationKeys.ENCODE_SERVICE_URL));
initInternal(filterConfig);
}
init();
}
/** Controls the ordering of filter initialization and checking by defining a method that runs before the init. */
/** Controls the ordering of filter initialization and checking by defining a method that runs before the init.
* @param filterConfig the original filter configuration.
* @throws ServletException if there is a problem.
*
*/
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
// template method
}
/**
* Initialization method. Called by Filter's init method or by Spring.
* Initialization method. Called by Filter's init method or by Spring. Similar in concept to the InitializingBean interface's
* 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.isNotEmpty(this.serverName) || CommonUtils.isNotEmpty(this.service),
"serverName or service must be set.");
CommonUtils.assertTrue(CommonUtils.isBlank(this.serverName) || CommonUtils.isBlank(this.service),
"serverName and service cannot both be set. You MUST ONLY set one.");
}
public final void destroy() {
// 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);
return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName,
this.protocol.getServiceParameterName(),
this.protocol.getArtifactParameterName(), this.encodeServiceUrl);
}
/**
* Note that trailing slashes should not be used in the serverName. As a convenience for this common misconfiguration, we strip them from the provided
* value.
*
* @param serverName the serverName. If this method is called, this should not be null. This AND service should not be both configured.
*/
public final void setServerName(final String serverName) {
this.serverName = serverName;
if (serverName != null && serverName.endsWith("/")) {
this.serverName = serverName.substring(0, serverName.length() - 1);
logger.info("Eliminated extra slash from serverName [{}]. It is now [{}]", serverName, this.serverName);
} else {
this.serverName = serverName;
}
}
public final void setService(final String service) {
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;
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.
*
* @param request the HTTP ServletRequest. CANNOT be NULL.
* @return the ticket if its found, null otherwise.
*/
protected String retrieveTicketFromRequest(final HttpServletRequest request) {
return CommonUtils.safeGetParameter(request, this.protocol.getArtifactParameterName(),
Arrays.asList(this.protocol.getArtifactParameterName()));
}
}

View File

@ -1,7 +1,32 @@
/**
* 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.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;
/**
* Abstracts out the ability to configure the filters from the initial properties provided.
@ -12,30 +37,46 @@ import javax.servlet.FilterConfig;
*/
public abstract class AbstractConfigurationFilter implements Filter {
/**
* 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 trieves the ServletContext's initParameters and returns that value if any.
*
* @param filterConfig the Filter Configuration.
* @param propertyName the property to retrieve.
* @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 static final String CONFIGURATION_STRATEGY_KEY = "configurationStrategy";
if (CommonUtils.isNotBlank(value)) {
return value;
}
protected final Logger logger = LoggerFactory.getLogger(getClass());
final String value2 = filterConfig.getServletContext().getInitParameter(propertyName);
private boolean ignoreInitConfiguration = false;
if (CommonUtils.isNotBlank(value2)) {
return value2;
}
private ConfigurationStrategy configurationStrategy;
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 getBoolean(final ConfigurationKey<Boolean> configurationKey) {
return this.configurationStrategy.getBoolean(configurationKey);
}
protected final String getString(final ConfigurationKey<String> configurationKey) {
return this.configurationStrategy.getString(configurationKey);
}
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;
}
protected final boolean isIgnoreInitConfiguration() {
return this.ignoreInitConfiguration;
}
}

View File

@ -1,17 +1,29 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.jasig.cas.client.validation.Assertion;
/**
* Static holder that places Assertion in a threadlocal.
* 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 {
@ -19,18 +31,21 @@ public class AssertionHolder {
/**
* ThreadLocal to hold the Assertion for Threads to access.
*/
private static final ThreadLocal threadLocal = new ThreadLocal();
private static final ThreadLocal<Assertion> threadLocal = new ThreadLocal<Assertion>();
/**
* Retrieve the assertion from the ThreadLocal.
*
* @return the Asssertion associated with this thread.
*/
public static Assertion getAssertion() {
return (Assertion) threadLocal.get();
return threadLocal.get();
}
/**
* Add the Assertion to the ThreadLocal.
*
* @param assertion the assertion to add.
*/
public static void setAssertion(final Assertion assertion) {
threadLocal.set(assertion);

View File

@ -1,39 +1,50 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.jasig.cas.client.validation.Assertion;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
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
}
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
@Override
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpSession session = request.getSession(false);
final Assertion assertion = (Assertion) (session != null ? session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : null);
final Assertion assertion = (Assertion) (session == null ? request
.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session
.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
try {
AssertionHolder.setAssertion(assertion);
@ -43,6 +54,7 @@ public final class AssertionThreadLocalFilter implements Filter {
}
}
@Override
public void destroy() {
// nothing to do
}

View File

@ -1,30 +1,82 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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;
import org.jasig.cas.client.validation.ProxyList;
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 {
/** Instance of Commons Logging. */
private static final Log LOG = LogFactory.getLog(CommonUtils.class);
private static final Logger LOGGER = LoggerFactory.getLogger(CommonUtils.class);
/**
* Constant representing the ProxyGrantingTicket IOU Request Parameter.
*/
private static final String PARAM_PROXY_GRANTING_TICKET_IOU = "pgtIou";
/**
* Constant representing the ProxyGrantingTicket Request Parameter.
*/
private static final String PARAM_PROXY_GRANTING_TICKET = "pgtId";
private static final HttpURLConnectionFactory DEFAULT_URL_CONNECTION_FACTORY = new HttpsURLConnectionFactory();
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", "");
}
private CommonUtils() {
// nothing to do
@ -47,10 +99,10 @@ public final class CommonUtils {
* Check whether the collection is null or empty. If it is, throw an
* exception and display the message.
*
* @param c the collecion to check.
* @param c the collection to check.
* @param message the message to display if the object is null.
*/
public static void assertNotEmpty(final Collection c, final String message) {
public static void assertNotEmpty(final Collection<?> c, final String message) {
assertNotNull(c, message);
if (c.isEmpty()) {
throw new IllegalArgumentException(message);
@ -61,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) {
@ -70,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.
*
@ -77,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();
}
/**
@ -99,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();
}
/**
@ -121,80 +187,561 @@ 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 final String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName, final String serviceUrl, final boolean renew, final boolean gateway) {
public static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName,
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" : "")
+ (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(final String value) {
try {
return casServerLoginUrl + "?" + serviceParameterName + "="
+ URLEncoder.encode(serviceUrl, "UTF-8")
+ (renew ? "&renew=true" : "")
+ (gateway ? "&gateway=true" : "");
return URLEncoder.encode(value, "UTF-8");
} catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
public static void readAndRespondToProxyReceptorRequest(final HttpServletRequest request,
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);
if (CommonUtils.isBlank(proxyGrantingTicket) || CommonUtils.isBlank(proxyGrantingTicketIou)) {
response.getWriter().write("");
return;
}
LOGGER.debug("Received proxyGrantingTicketId [{}] for proxyGrantingTicketIou [{}]", proxyGrantingTicket,
proxyGrantingTicketIou);
proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
LOGGER.debug("Successfully saved proxyGrantingTicketId [{}] for proxyGrantingTicketIou [{}]",
proxyGrantingTicket, proxyGrantingTicketIou);
response.getWriter().write("<?xml version=\"1.0\"?>");
response.getWriter().write("<casClient:proxySuccess xmlns:casClient=\"http://www.yale.edu/tp/casClient\" />");
}
protected static String findMatchingServerName(final HttpServletRequest request, final String serverName) {
final String[] serverNames = serverName.split(" ");
if (serverNames.length == 0 || serverNames.length == 1) {
return serverName;
}
final String host = request.getHeader("Host");
final String xHost = request.getHeader("X-Forwarded-Host");
final String comparisonHost;
comparisonHost = (xHost != null) ? xHost : host;
if (comparisonHost == null) {
return serverName;
}
for (final String server : serverNames) {
final String lowerCaseServer = server.toLowerCase();
if (lowerCaseServer.contains(comparisonHost)) {
return server;
}
}
return serverNames[0];
}
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. 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) {
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 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 final String constructServiceUrl(final HttpServletRequest request,
final HttpServletResponse response, final String service, final String serverName, final String artifactParameterName, final boolean encode) {
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 StringBuffer buffer = new StringBuffer();
final String serverName = findMatchingServerName(request, serverNames);
final URIBuilder originalRequestUrl = new URIBuilder(request.getRequestURL().toString(), encode);
originalRequestUrl.setParameters(request.getQueryString());
synchronized (buffer) {
if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
buffer.append(request.isSecure() ? "https://" : "http://");
}
final URIBuilder builder;
if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
final String scheme = request.isSecure() ? "https://" : "http://";
builder = new URIBuilder(scheme + serverName, encode);
} else {
builder = new URIBuilder(serverName, encode);
}
buffer.append(serverName);
buffer.append(request.getRequestURI());
if (builder.getPort() == -1 && !requestIsOnStandardPort(request)) {
builder.setPort(request.getServerPort());
}
if (CommonUtils.isNotBlank(request.getQueryString())) {
final int location = request.getQueryString().indexOf(
artifactParameterName + "=");
builder.setEncodedPath(builder.getEncodedPath() + request.getRequestURI());
if (location == 0) {
final String returnValue = encode ? response.encodeURL(buffer
.toString()): buffer.toString();
if (LOG.isDebugEnabled()) {
LOG.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();
if (LOG.isDebugEnabled()) {
LOG.debug("serviceUrl generated: " + returnValue);
}
final String result = builder.toString();
final String returnValue = encode ? response.encodeURL(result) : result;
LOGGER.debug("serviceUrl generated: {}", returnValue);
return returnValue;
}
/**
* Safe method for retrieving a parameter from the request without disrupting the reader UNLESS the parameter
* actually exists in the query string.
* <p>
* Note, this does not work for POST Requests for "logoutRequest". It works for all other CAS POST requests because the
* parameter is ALWAYS in the GET request.
* <p>
* If we see the "logoutRequest" parameter we MUST treat it as if calling the standard request.getParameter.
* <p>
* Note, that as of 3.3.0, we've made it more generic.
* </p>
*
* @param request the request to check.
* @param parameter the parameter to look for.
* @return the value of the parameter.
*/
public static String safeGetParameter(final HttpServletRequest request, final String parameter,
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);
}
public static String safeGetParameter(final HttpServletRequest request, final String parameter) {
return safeGetParameter(request, parameter, Arrays.asList("logoutRequest"));
}
/**
* Contacts the remote URL and returns the response.
*
* @param constructedUrl the url to contact.
* @param encoding the encoding to use.
* @return the response.
*/
@Deprecated
public static String getResponseFromServer(final String constructedUrl, final String encoding) {
try {
return getResponseFromServer(new URL(constructedUrl), DEFAULT_URL_CONNECTION_FACTORY, encoding);
} catch (final IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Deprecated
public static String getResponseFromServer(final URL constructedUrl, final String encoding) {
return getResponseFromServer(constructedUrl, DEFAULT_URL_CONNECTION_FACTORY, encoding);
}
/**
* Contacts the remote URL and returns the response.
*
* @param constructedUrl the url to contact.
* @param factory connection factory to prepare the URL connection instance
* @param encoding the encoding to use.
* @return the response.
*/
public static String getResponseFromServer(final URL constructedUrl, final HttpURLConnectionFactory factory,
final String encoding) {
HttpURLConnection conn = null;
InputStreamReader in = null;
try {
conn = factory.buildHttpURLConnection(constructedUrl.openConnection());
if (CommonUtils.isEmpty(encoding)) {
in = new InputStreamReader(conn.getInputStream());
} else {
in = new InputStreamReader(conn.getInputStream(), encoding);
}
final StringBuilder builder = new StringBuilder(255);
int byteRead;
while ((byteRead = in.read()) != -1) {
builder.append((char) byteRead);
}
return builder.toString();
} 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);
if (conn != null) {
conn.disconnect();
}
}
}
public static ProxyList createProxyList(final String proxies) {
if (CommonUtils.isBlank(proxies)) {
return new ProxyList();
}
final ProxyListEditor editor = new ProxyListEditor();
editor.setAsText(proxies);
return (ProxyList) editor.getValue();
}
/**
* Sends the redirect message and captures the exceptions that we can't possibly do anything with.
*
* @param response the HttpServletResponse. CANNOT be NULL.
* @param url the url to redirect to.
*/
public static void sendRedirect(final HttpServletResponse response, final String url) {
try {
response.sendRedirect(url);
} catch (final IOException e) {
LOGGER.warn(e.getMessage(), e);
}
}
/**
* 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 the resource to close
*/
public static void closeQuietly(final Closeable resource) {
try {
if (resource != null) {
resource.close();
}
} catch (final IOException e) {
//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 + "/";
}
}

View File

@ -1,22 +1,29 @@
/*
* Copyright 2006 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A Delegating Filter looks up a parameter in the request object and matches
@ -24,7 +31,6 @@ import java.util.Map;
* 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 {
@ -32,7 +38,7 @@ public final class DelegatingFilter implements Filter {
/**
* Instance of Commons Logging.
*/
private final Log log = LogFactory.getLog(this.getClass());
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* The request parameter to look for in the Request object.
@ -42,7 +48,7 @@ public final class DelegatingFilter implements Filter {
/**
* The map of filters to delegate to and the criteria (as key).
*/
private final Map delegators;
private final Map<String, Filter> delegators;
/**
* The default filter to use if there is no match.
@ -55,25 +61,15 @@ public final class DelegatingFilter implements Filter {
*/
private final boolean exactMatch;
public DelegatingFilter(final String requestParameterName, final Map delegators, final boolean exactMatch) {
public DelegatingFilter(final String requestParameterName, final Map<String, Filter> delegators,
final boolean exactMatch) {
this(requestParameterName, delegators, exactMatch, null);
}
public DelegatingFilter(final String requestParameterName, final Map delegators, final boolean exactMatch, final Filter defaultFilter) {
CommonUtils.assertNotNull(requestParameterName,
"requestParameterName cannot be null.");
CommonUtils.assertTrue(!delegators.isEmpty(),
"delegators cannot be empty.");
for (final Iterator iter = delegators.keySet().iterator(); iter
.hasNext();) {
final Object object = delegators.get(iter.next());
if (!Filter.class.isAssignableFrom(object.getClass())) {
throw new IllegalArgumentException(
"All value objects in the delegators map must be filters.");
}
}
public DelegatingFilter(final String requestParameterName, final Map<String, Filter> delegators,
final boolean exactMatch, final Filter defaultFilter) {
CommonUtils.assertNotNull(requestParameterName, "requestParameterName cannot be null.");
CommonUtils.assertTrue(!delegators.isEmpty(), "delegators cannot be empty.");
this.requestParameterName = requestParameterName;
this.delegators = delegators;
@ -81,39 +77,30 @@ public final class DelegatingFilter implements Filter {
this.exactMatch = exactMatch;
}
@Override
public void destroy() {
// nothing to do here
}
public void doFilter(final ServletRequest request,
final ServletResponse response, final FilterChain filterChain)
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
throws IOException, ServletException {
final String parameter = request
.getParameter(this.requestParameterName);
final String parameter = CommonUtils.safeGetParameter((HttpServletRequest) request, this.requestParameterName);
if (CommonUtils.isNotEmpty(parameter)) {
for (final Iterator iter = this.delegators.keySet().iterator(); iter
.hasNext();) {
final String key = (String) iter.next();
if ((parameter.equals(key) && this.exactMatch)
|| (parameter.matches(key) && !this.exactMatch)) {
final Filter filter = (Filter) this.delegators.get(key);
if (log.isDebugEnabled()) {
log.debug("Match found for parameter ["
+ this.requestParameterName + "] with value ["
+ parameter + "]. Delegating to filter ["
+ filter.getClass().getName() + "]");
}
for (final String key : this.delegators.keySet()) {
if ((parameter.equals(key) && this.exactMatch) || (parameter.matches(key) && !this.exactMatch)) {
final Filter filter = this.delegators.get(key);
logger.debug("Match found for parameter [{}] with value [{}]. Delegating to filter [{}]",
this.requestParameterName, parameter, filter.getClass().getName());
filter.doFilter(request, response, filterChain);
return;
}
}
}
log.debug("No match found for parameter [" + this.requestParameterName
+ "] with value [" + parameter + "]");
logger.debug("No match found for parameter [{}] with value [{}]", this.requestParameterName, parameter);
if (this.defaultFilter != null) {
this.defaultFilter.doFilter(request, response, filterChain);
@ -122,6 +109,7 @@ public final class DelegatingFilter implements Filter {
}
}
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
// nothing to do here.
}

View File

@ -0,0 +1,139 @@
/**
* 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.IOException;
import java.util.ArrayList;
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/>
* 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/>
* 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 {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final List<ErrorHolder> errors = new ArrayList<ErrorHolder>();
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 Exception e) {
final Throwable t = extractErrorToCompare(e);
ErrorHolder currentMatch = null;
for (final ErrorHolder errorHolder : this.errors) {
if (errorHolder.exactMatch(t)) {
currentMatch = errorHolder;
break;
} else if (errorHolder.inheritanceMatch(t)) {
currentMatch = errorHolder;
}
}
if (currentMatch != null) {
httpResponse.sendRedirect(currentMatch.getUrl());
} else {
httpResponse.sendRedirect(defaultErrorRedirectPage);
}
}
}
/**
* 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");
final Enumeration<?> enumeration = filterConfig.getInitParameterNames();
while (enumeration.hasMoreElements()) {
final String className = (String) enumeration.nextElement();
try {
if (!className.equals("defaultErrorRedirectPage")) {
this.errors.add(new ErrorHolder(className, filterConfig.getInitParameter(className)));
}
} catch (final ClassNotFoundException e) {
logger.warn("Class [{}] cannot be found in ClassLoader. Ignoring.", className);
}
}
}
protected final class ErrorHolder {
private Class<?> className;
private String url;
protected ErrorHolder(final String className, final String url) throws ClassNotFoundException {
this.className = Class.forName(className);
this.url = url;
}
public boolean exactMatch(final Throwable e) {
return this.className.equals(e.getClass());
}
public boolean inheritanceMatch(final Throwable e) {
return className.isAssignableFrom(e.getClass());
}
public String getUrl() {
return this.url;
}
}
}

View File

@ -1,38 +1,60 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.jasig.cas.client.validation.Assertion;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Collection;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import org.jasig.cas.client.validation.Assertion;
/**
* Implementation of a filter that wraps the normal HttpServletRequest with a
* wrapper that overrides the getRemoteUser method to retrieve the user from the
* CAS Assertion.
* wrapper that overrides the following methods to provide data from the
* CAS Assertion:
* <ul>
* <li>{@link HttpServletRequest#getUserPrincipal()}</li>
* <li>{@link HttpServletRequest#getRemoteUser()}</li>
* <li>{@link HttpServletRequest#isUserInRole(String)}</li>
* </ul>
* <p/>
* This filter needs to be configured in the chain so that it executes after
* both the authentication and the validation filters.
*
* @author Scott Battaglia
* @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
* @author Marvin S. Addison
* @since 3.0
*/
public final class HttpServletRequestWrapperFilter implements Filter {
public final class HttpServletRequestWrapperFilter extends AbstractConfigurationFilter {
/** Name of the attribute used to answer role membership queries */
private String roleAttribute;
/** Whether or not to ignore case in role membership queries */
private boolean ignoreCase;
@Override
public void destroy() {
// nothing to do
}
@ -42,42 +64,95 @@ public final class HttpServletRequestWrapperFilter implements Filter {
* <code>request.getRemoteUser</code> to the underlying Assertion object
* stored in the user session.
*/
public void doFilter(final ServletRequest servletRequest,
final ServletResponse servletResponse, final FilterChain filterChain)
throws IOException, ServletException {
final Principal principal = retrievePrincipalFromSessionOrRequest(servletRequest);
@Override
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
final AttributePrincipal principal = retrievePrincipalFromSessionOrRequest(servletRequest);
filterChain.doFilter(new CasHttpServletRequestWrapper(
(HttpServletRequest) servletRequest, principal), servletResponse);
filterChain.doFilter(new CasHttpServletRequestWrapper((HttpServletRequest) servletRequest, principal),
servletResponse);
}
protected Principal retrievePrincipalFromSessionOrRequest(final ServletRequest servletRequest) {
protected AttributePrincipal retrievePrincipalFromSessionOrRequest(final ServletRequest servletRequest) {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpSession session = request.getSession(false);
final Assertion assertion = (Assertion) (session == null ? request.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
final Assertion assertion = (Assertion) (session == null ? request
.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session
.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
return assertion == null ? null : assertion.getPrincipal();
}
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
// nothing to do
super.init(filterConfig);
this.roleAttribute = getString(ConfigurationKeys.ROLE_ATTRIBUTE);
this.ignoreCase = getBoolean(ConfigurationKeys.IGNORE_CASE);
}
final class CasHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final Principal principal;
private final AttributePrincipal principal;
CasHttpServletRequestWrapper(final HttpServletRequest request, final Principal principal) {
CasHttpServletRequestWrapper(final HttpServletRequest request, final AttributePrincipal principal) {
super(request);
this.principal = principal;
}
@Override
public Principal getUserPrincipal() {
return this.principal;
}
@Override
public String getRemoteUser() {
return getUserPrincipal().getName();
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.");
return false;
}
if (this.principal == null) {
logger.debug("No Principal in Request. Returning false.");
return false;
}
if (CommonUtils.isBlank(roleAttribute)) {
logger.debug("No Role Attribute Configured. Returning false.");
return false;
}
final Object value = this.principal.getAttributes().get(roleAttribute);
if (value instanceof Collection<?>) {
for (final Object o : (Collection<?>) value) {
if (rolesEqual(role, o)) {
logger.debug("User [{}] is in role [{}]: true", getRemoteUser(), role);
return true;
}
}
}
final boolean isMember = rolesEqual(role, value);
logger.debug("User [{}] is in role [{}]: {}", getRemoteUser(), role, isMember);
return isMember;
}
/**
* Determines whether the given role is equal to the candidate
* role attribute taking into account case sensitivity.
*
* @param given Role under consideration.
* @param candidate Role that the current user possesses.
*
* @return True if roles are equal, false otherwise.
*/
private boolean rolesEqual(final String given, final Object candidate) {
return ignoreCase ? given.equalsIgnoreCase(candidate.toString()) : given.equals(candidate);
}
}
}

View File

@ -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
}
}
}

View File

@ -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();
}
}

View File

@ -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) {}
}
}
}

View File

@ -0,0 +1,183 @@
/**
* 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.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* Helper class with reflection utility methods.
*
* @author Marvin S. Addison
* @version $Revision$
* @since 3.1.11
*
*/
public final class ReflectUtils {
private ReflectUtils() {
// private constructor to prevent instanciation.
}
/**
* Attempts to create a class from a String.
* @param className the name of the class to create.
* @return the class. CANNOT be NULL.
* @throws IllegalArgumentException if the className does not exist.
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> loadClass(final String className) throws IllegalArgumentException {
try {
return (Class<T>) Class.forName(className);
} catch (final ClassNotFoundException e) {
throw new IllegalArgumentException(className + " class not found.");
}
}
/**
* Creates a new instance of the given class by passing the given arguments
* to the constructor.
* @param className Name of class to be created.
* @param args Constructor arguments.
* @return New instance of given class.
*/
public static <T> T newInstance(final String className, final Object... args) {
return newInstance(ReflectUtils.<T> loadClass(className), args);
}
/**
* Creates a new instance of the given class by passing the given arguments
* to the constructor.
* @param clazz Class of instance to be created.
* @param args Constructor arguments.
* @return New instance of given class.
*/
public static <T> T newInstance(final Class<T> clazz, final Object... args) {
final Class<?>[] argClasses = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argClasses[i] = args[i].getClass();
}
try {
return clazz.getConstructor(argClasses).newInstance(args);
} catch (final Exception e) {
throw new IllegalArgumentException("Error creating new instance of " + clazz, e);
}
}
/**
* Gets the property descriptor for the named property on the given class.
* @param clazz Class to which property belongs.
* @param propertyName Name of property.
* @return Property descriptor for given property or null if no property with given
* name exists in given class.
*/
public static PropertyDescriptor getPropertyDescriptor(final Class<?> clazz, final String propertyName) {
try {
return getPropertyDescriptor(Introspector.getBeanInfo(clazz), propertyName);
} catch (final IntrospectionException e) {
throw new RuntimeException("Failed getting bean info for " + clazz, e);
}
}
/**
* Gets the property descriptor for the named property from the bean info describing
* a particular class to which property belongs.
* @param info Bean info describing class to which property belongs.
* @param propertyName Name of property.
* @return Property descriptor for given property or null if no property with given
* name exists.
*/
public static PropertyDescriptor getPropertyDescriptor(final BeanInfo info, final String propertyName) {
for (int i = 0; i < info.getPropertyDescriptors().length; i++) {
final PropertyDescriptor pd = info.getPropertyDescriptors()[i];
if (pd.getName().equals(propertyName)) {
return pd;
}
}
return null;
}
/**
* Sets the given property on the target JavaBean using bean instrospection.
* @param propertyName Property to set.
* @param value Property value to set.
* @param target Target java bean on which to set property.
*/
public static void setProperty(final String propertyName, final Object value, final Object target) {
try {
setProperty(propertyName, value, target, Introspector.getBeanInfo(target.getClass()));
} catch (final IntrospectionException e) {
throw new RuntimeException("Failed getting bean info on target JavaBean " + target, e);
}
}
/**
* Sets the given property on the target JavaBean using bean instrospection.
* @param propertyName Property to set.
* @param value Property value to set.
* @param target Target JavaBean on which to set property.
* @param info BeanInfo describing the target JavaBean.
*/
public static void setProperty(final String propertyName, final Object value, final Object target,
final BeanInfo info) {
try {
final PropertyDescriptor pd = getPropertyDescriptor(info, propertyName);
pd.getWriteMethod().invoke(target, value);
} catch (final InvocationTargetException e) {
throw new RuntimeException("Error setting property " + propertyName, e.getCause());
} catch (final Exception e) {
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);
}
}
}

View File

@ -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");
}
}
}

View File

@ -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();
}
}
}

View File

@ -1,28 +1,44 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.StringReader;
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 org.xml.sax.helpers.XMLReaderFactory;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
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 {
@ -30,7 +46,37 @@ public final class XmlUtils {
/**
* Static instance of Commons Logging.
*/
private final static Log LOG = LogFactory.getLog(XmlUtils.class);
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.
@ -39,12 +85,20 @@ public final class XmlUtils {
*/
public static XMLReader getXmlReader() {
try {
return XMLReaderFactory.createXMLReader();
} catch (final SAXException e) {
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.
@ -54,36 +108,35 @@ public final class XmlUtils {
* @param element the element to look for
* @return the list of text from the elements.
*/
public static List getTextForElements(final String xmlAsString,
final String element) {
final List elements = new ArrayList(2);
public static List<String> getTextForElements(final String xmlAsString, final String element) {
final List<String> elements = new ArrayList<String>(2);
final XMLReader reader = getXmlReader();
final DefaultHandler handler = new DefaultHandler() {
private boolean foundElement = false;
private StringBuffer buffer = new StringBuffer();
private StringBuilder buffer = new StringBuilder();
public void startElement(final String uri, final String localName,
final String qName, final Attributes attributes)
throws SAXException {
@Override
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
public void endElement(final String uri, final String localName,
final String qName) throws SAXException {
@Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
elements.add(this.buffer.toString());
this.buffer = new StringBuffer();
this.buffer = new StringBuilder();
}
}
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);
}
@ -96,7 +149,7 @@ public final class XmlUtils {
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
LOG.error(e, e);
LOGGER.error(e.getMessage(), e);
return null;
}
@ -111,34 +164,33 @@ public final class XmlUtils {
* @param element the element to look for
* @return the text value of the element.
*/
public static String getTextForElement(final String xmlAsString,
final String element) {
public static String getTextForElement(final String xmlAsString, final String element) {
final XMLReader reader = getXmlReader();
final StringBuffer buffer = new StringBuffer();
final StringBuilder builder = new StringBuilder();
final DefaultHandler handler = new DefaultHandler() {
private boolean foundElement = false;
public void startElement(final String uri, final String localName,
final String qName, final Attributes attributes)
throws SAXException {
@Override
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
public void endElement(final String uri, final String localName,
final String qName) throws SAXException {
@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) {
buffer.append(ch, start, length);
builder.append(ch, start, length);
}
}
};
@ -149,10 +201,10 @@ public final class XmlUtils {
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
LOG.error(e, e);
LOGGER.error(e.getMessage(), e);
return null;
}
return buffer.toString();
return builder.toString();
}
}

View File

@ -1,3 +1,23 @@
<!--
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.
-->
<html>
<body>
<p>The validation package includes interfaces for validating Tickets, as well as the common implementations.</p>

View File

@ -1,15 +1,25 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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 java.net.URL;
import java.net.HttpURLConnection;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import org.jasig.cas.client.util.CommonUtils;
/**
* Abstract class that knows the protocol for validating a CAS ticket.
@ -27,31 +37,8 @@ public abstract class AbstractCasProtocolUrlBasedTicketValidator extends Abstrac
/**
* 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) {
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) validationUrl.openConnection();
final BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
final StringBuffer stringBuffer = new StringBuffer(255);
synchronized (stringBuffer) {
while ((line = in.readLine()) != null) {
stringBuffer.append(line);
stringBuffer.append("\n");
}
return stringBuffer.toString();
}
} catch (final IOException e) {
log.error(e,e);
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
return CommonUtils.getResponseFromServer(validationUrl, getURLConnectionFactory(), getEncoding());
}
}

View File

@ -1,31 +1,49 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.net.ssl.HostnameVerifier;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
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;
/**
* The filter that handles all the work of validating ticket requests.
* <p>
* This filter can be configured with the following values:
* <ul>
* <li><code>redirectAfterValidation</code> - redirect the CAS client to the same URL without the ticket.</li>
* <li><code>redirectAfterValidation</code> - redirect the CAS client to the same URL without the ticket.
* (default: true, Will be forced to false when {@link #useSession} is false.)</li>
* <li><code>exceptionOnValidationFailure</code> - throw an exception if the validation fails. Otherwise, continue
* processing.</li>
* <li><code>useSession</code> - store any of the useful information in a session attribute.</li>
* processing. (default: true)</li>
* <li><code>useSession</code> - store any of the useful information in a session attribute. (default: true)</li>
* <li><code>hostnameVerifier</code> - name of class implementing a {@link HostnameVerifier}.</li>
* <li><code>hostnameVerifierConfig</code> - name of configuration class (constructor argument of verifier).</li>
* </ul>
*
* @author Scott Battaglia
@ -42,31 +60,89 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
* successful validation to remove the ticket parameter from the query
* string.
*/
private boolean redirectAfterValidation = false;
private boolean redirectAfterValidation = true;
/** Determines whether an exception is thrown when there is a ticket validation failure. */
private boolean exceptionOnValidationFailure = true;
private boolean exceptionOnValidationFailure = false;
/**
* Specify whether the Assertion should be stored in a session
* attribute {@link AbstractCasFilter#CONST_CAS_ASSERTION}.
*/
private boolean useSession = true;
protected AbstractTicketValidationFilter(final Protocol protocol) {
super(protocol);
}
/**
* Template method to return the appropriate validator.
*
* @param filterConfig the FilterConfiguration that may be needed to construct a validator.
* @return the ticket validator.
*/
protected TicketValidator getTicketValidator(FilterConfig filterConfig) {
protected TicketValidator getTicketValidator(final FilterConfig filterConfig) {
return this.ticketValidator;
}
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
super.initInternal(filterConfig);
setExceptionOnValidationFailure(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "exceptionOnValidationFailure", "true")));
setRedirectAfterValidation(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "redirectAfterValidation", "false")));
setUseSession(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "useSession", "true")));
setTicketValidator(getTicketValidator(filterConfig));
/**
* Gets the ssl config to use for HTTPS connections
* if one is configured for this filter.
* @return Properties that can contains key/trust info for Client Side Certificates
*/
protected Properties getSSLConfig() {
final Properties properties = new Properties();
final String fileName = getString(ConfigurationKeys.SSL_CONFIG_FILE);
if (fileName != null) {
FileInputStream fis = null;
try {
fis = new FileInputStream(fileName);
properties.load(fis);
logger.trace("Loaded {} entries from {}", properties.size(), fileName);
} catch (final IOException ioe) {
logger.error(ioe.getMessage(), ioe);
} finally {
CommonUtils.closeQuietly(fis);
}
}
return properties;
}
/**
* Gets the configured {@link HostnameVerifier} to use for HTTPS connections
* if one is configured for this filter.
* @return Instance of specified host name verifier or null if none specified.
*/
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);
} else {
return ReflectUtils.newInstance(className);
}
}
return null;
}
@Override
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
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.");
setRedirectAfterValidation(false);
}
setTicketValidator(getTicketValidator(filterConfig));
super.initInternal(filterConfig);
}
@Override
public void init() {
super.init();
CommonUtils.assertNotNull(this.ticketValidator, "ticketValidator cannot be null.");
@ -82,7 +158,8 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
* @throws IOException if there is an I/O problem
* @throws ServletException if there is a servlet problem.
*/
protected boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
protected boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
return true;
}
@ -95,8 +172,9 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
* @param response the HttpServletResponse.
* @param assertion the successful Assertion from the server.
*/
protected void onSuccessfulValidation(final HttpServletRequest request, final HttpServletResponse response, final Assertion assertion) {
// nothing to do here.
protected void onSuccessfulValidation(final HttpServletRequest request, final HttpServletResponse response,
final Assertion assertion) {
// nothing to do here.
}
/**
@ -110,7 +188,9 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
// nothing to do here.
}
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
@Override
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
if (!preFilter(servletRequest, servletResponse, filterChain)) {
return;
@ -118,44 +198,40 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final String ticket = request.getParameter(getArtifactParameterName());
final String ticket = retrieveTicketFromRequest(request);
if (CommonUtils.isNotBlank(ticket)) {
if (log.isDebugEnabled()) {
log.debug("Attempting to validate ticket: " + ticket);
}
logger.debug("Attempting to validate ticket: {}", ticket);
try {
final Assertion assertion = this.ticketValidator.validate(
ticket, constructServiceUrl(request,
response));
final Assertion assertion = this.ticketValidator.validate(ticket,
constructServiceUrl(request, response));
if (log.isDebugEnabled()) {
log.debug("Successfully authenticated user: "
+ assertion.getPrincipal().getName());
}
logger.debug("Successfully authenticated user: {}", assertion.getPrincipal().getName());
request.setAttribute(CONST_CAS_ASSERTION, assertion);
if (this.useSession) {
request.getSession().setAttribute(CONST_CAS_ASSERTION,
assertion);
request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);
}
onSuccessfulValidation(request, response, assertion);
if (this.redirectAfterValidation) {
logger.debug("Redirecting after successful ticket validation.");
response.sendRedirect(constructServiceUrl(request, response));
return;
}
} catch (final TicketValidationException e) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
log.warn(e, e);
logger.debug(e.getMessage(), e);
onFailedValidation(request, response);
if (this.exceptionOnValidationFailure) {
throw new ServletException(e);
}
}
if (this.redirectAfterValidation) {
response.sendRedirect(response
.encodeRedirectURL(constructServiceUrl(request, response)));
response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
return;
}
}
@ -165,8 +241,8 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
}
public final void setTicketValidator(final TicketValidator ticketValidator) {
this.ticketValidator = ticketValidator;
}
this.ticketValidator = ticketValidator;
}
public final void setRedirectAfterValidation(final boolean redirectAfterValidation) {
this.redirectAfterValidation = redirectAfterValidation;

View File

@ -1,35 +1,50 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.util.CommonUtils;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Abstract validator implementation for tickets that must be validated against a server.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
public abstract class AbstractUrlBasedTicketValidator implements TicketValidator {
protected final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Commons Logging instance.
* URLConnection factory instance to use when making validation requests to the CAS server.
* Defaults to {@link HttpsURLConnectionFactory}
*/
protected final Log log = LogFactory.getLog(getClass());
private HttpURLConnectionFactory urlConnectionFactory = new HttpsURLConnectionFactory();
/**
* Prefix for the CAS server. Should be everything up to the url endpoint, including the /.
@ -43,14 +58,21 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
*/
private boolean renew;
/**
* A map containing custom parameters to pass to the validation url.
*/
private Map<String, String> customParameters;
private String encoding;
/**
* Constructs a new TicketValidator with the casServerUrlPrefix.
*
* @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);
}
/**
@ -58,7 +80,7 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
*
* @param urlParameters the map containing the parameters.
*/
protected void populateUrlAttributeMap(final Map urlParameters) {
protected void populateUrlAttributeMap(final Map<String, String> urlParameters) {
// nothing to do
}
@ -68,6 +90,7 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
*/
protected abstract String getUrlSuffix();
/**
* Constructs the URL to send the validation request to.
*
@ -76,41 +99,48 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
* @return the fully constructed URL.
*/
protected final String constructValidationUrl(final String ticket, final String serviceUrl) {
final Map urlParameters = new HashMap();
final Map<String, String> urlParameters = new HashMap<String, String>();
logger.debug("Placing URL parameters in map.");
urlParameters.put("ticket", ticket);
urlParameters.put("service", encodeUrl(serviceUrl));
urlParameters.put("service", serviceUrl);
if (this.renew) {
urlParameters.put("renew", "true");
}
logger.debug("Calling template URL attribute map.");
populateUrlAttributeMap(urlParameters);
logger.debug("Loading custom parameters from configuration.");
if (this.customParameters != null) {
urlParameters.putAll(this.customParameters);
}
final String suffix = getUrlSuffix();
final StringBuffer buffer = new StringBuffer(urlParameters.size()*10 + this.casServerUrlPrefix.length() + suffix.length() +1);
final StringBuilder buffer = new StringBuilder(urlParameters.size() * 10 + this.casServerUrlPrefix.length()
+ suffix.length() + 1);
int i = 0;
synchronized (buffer) {
buffer.append(this.casServerUrlPrefix);
buffer.append("/");
buffer.append(suffix);
for (final Iterator iter = urlParameters.entrySet().iterator(); iter.hasNext();) {
buffer.append(this.casServerUrlPrefix);
buffer.append(suffix);
for (final Map.Entry<String, String> entry : urlParameters.entrySet()) {
final String key = entry.getKey();
final String value = entry.getValue();
if (value != null) {
buffer.append(i++ == 0 ? "?" : "&");
final Map.Entry entry = (Map.Entry) iter.next();
final String key = (String) entry.getKey();
final String value = (String) entry.getValue();
if (value != null) {
buffer.append(key);
buffer.append("=");
buffer.append(value);
}
buffer.append(key);
buffer.append("=");
final String encodedValue = encodeUrl(value);
buffer.append(encodedValue);
}
return buffer.toString();
}
return buffer.toString();
}
/**
@ -120,10 +150,10 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
* @return the encoded url, or the original url if "UTF-8" character encoding could not be found.
*/
protected final String encodeUrl(final String url) {
if (url == null) {
return null;
}
if (url == null) {
return null;
}
try {
return URLEncoder.encode(url, "UTF-8");
} catch (final UnsupportedEncodingException e) {
@ -151,24 +181,60 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
protected abstract String retrieveResponseFromServer(URL validationUrl, String ticket);
public Assertion validate(final String ticket, final String service) throws TicketValidationException {
@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);
try {
logger.debug("Retrieving response from server.");
final String serverResponse = retrieveResponseFromServer(new URL(validationUrl), ticket);
if (serverResponse == null) {
throw new TicketValidationException("The CAS server returned no response.");
}
logger.debug("Server response: {}", serverResponse);
return parseResponseFromServer(serverResponse);
} catch (final MalformedURLException e) {
throw new TicketValidationException(e);
}
}
public void setRenew(final boolean renew) {
public final void setRenew(final boolean renew) {
this.renew = renew;
}
}
public final void setCustomParameters(final Map<String, String> customParameters) {
this.customParameters = customParameters;
}
public final void setEncoding(final String encoding) {
this.encoding = encoding;
}
protected final String getEncoding() {
return this.encoding;
}
protected final boolean isRenew() {
return this.renew;
}
protected final String getCasServerUrlPrefix() {
return this.casServerUrlPrefix;
}
protected final Map<String, String> getCustomParameters() {
return this.customParameters;
}
protected HttpURLConnectionFactory getURLConnectionFactory() {
return this.urlConnectionFactory;
}
public void setURLConnectionFactory(final HttpURLConnectionFactory urlConnectionFactory) {
this.urlConnectionFactory = urlConnectionFactory;
}
}

View File

@ -1,15 +1,27 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.authentication.AttributePrincipal;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import org.jasig.cas.client.authentication.AttributePrincipal;
/**
* Represents a response to a validation request.
@ -34,12 +46,20 @@ public interface Assertion extends Serializable {
*/
Date getValidUntilDate();
/**
* The date the authentication actually occurred on. If its unable to be determined, it should be set to the current
* time.
*
* @return the authentication date, or the current time if it can't be determined.
*/
Date getAuthenticationDate();
/**
* The key/value pairs associated with this assertion.
*
* @return the map of attributes.
*/
Map getAttributes();
Map<String, Object> getAttributes();
/**
* The principal for which this assertion is valid.
@ -47,4 +67,12 @@ public interface Assertion extends Serializable {
* @return the principal.
*/
AttributePrincipal getPrincipal();
/**
* Determines whether an Assertion is considered usable or not. A naive implementation may just check the date validity.
*
* @return true if its valid, false otherwise.
* @since 3.3.0 (though in 3.3.0, no one actually calls this)
*/
boolean isValid();
}

View File

@ -1,18 +1,30 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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 java.util.Collections;
import java.util.Date;
import java.util.Map;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.jasig.cas.client.util.CommonUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Concrete Implementation of the {@link Assertion}.
*
@ -24,16 +36,18 @@ import java.util.Map;
public final class AssertionImpl implements Assertion {
/** Unique Id for serialization. */
private static final long serialVersionUID = -7767943925833639221L;
private static final long serialVersionUID = -7767943925833639221L;
/** The date from which the assertion is valid. */
/** The date from which the assertion is valid. */
private final Date validFromDate;
/** The date the assertion is valid until. */
private final Date validUntilDate;
private final Date authenticationDate;
/** Map of key/value pairs associated with this assertion. I.e. authentication type. */
private final Map attributes;
private final Map<String, Object> attributes;
/** The principal for which this assertion is valid for. */
private final AttributePrincipal principal;
@ -44,16 +58,16 @@ public final class AssertionImpl implements Assertion {
* @param name the name of the principal for which this assertion is valid.
*/
public AssertionImpl(final String name) {
this(new AttributePrincipalImpl(name));
this(new AttributePrincipalImpl(name));
}
/**
* Creates a new Assrtion with the supplied Principal.
* Creates a new Assertion with the supplied Principal.
*
* @param principal the Principal to associate with the Assertion.
*/
public AssertionImpl(final AttributePrincipal principal) {
this(principal, new HashMap());
this(principal, Collections.<String, Object> emptyMap());
}
/**
@ -62,41 +76,64 @@ public final class AssertionImpl implements Assertion {
* @param principal the Principal to associate with the Assertion.
* @param attributes the key/value pairs for this attribute.
*/
public AssertionImpl(final AttributePrincipal principal, final Map attributes) {
this(principal, new Date(), null, attributes);
public AssertionImpl(final AttributePrincipal principal, final Map<String, Object> attributes) {
this(principal, new Date(), null, new Date(), attributes);
}
/**
* Creats a new Assertion with the supplied principal, Assertion attributes, and start and valid until dates.
* Creates a new Assertion with the supplied principal, Assertion attributes, and start and valid until dates.
*
* @param principal the Principal to associate with the Assertion.
* @param validFromDate when the assertion is valid from.
* @param validUntilDate when the assertion is valid to.
* @param attributes the key/value pairs for this attribute.
*/
public AssertionImpl(final AttributePrincipal principal, final Date validFromDate, final Date validUntilDate, final Map attributes) {
public AssertionImpl(final AttributePrincipal principal, final Date validFromDate, final Date validUntilDate,
final Date authenticationDate, final Map<String, Object> attributes) {
this.principal = principal;
this.validFromDate = validFromDate;
this.validUntilDate = validUntilDate;
this.attributes = attributes;
this.authenticationDate = authenticationDate;
CommonUtils.assertNotNull(this.principal, "principal cannot be null.");
CommonUtils.assertNotNull(this.validFromDate, "validFromDate cannot be null.");
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;
}
public Map getAttributes() {
@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.validFromDate.equals(now))
&& (this.validUntilDate == null || this.validUntilDate.after(now) || this.validUntilDate.equals(now));
}
}

View File

@ -1,27 +1,55 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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 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 {
public Cas10TicketValidationFilter() {
super(Protocol.CAS1);
}
@Override
protected final TicketValidator getTicketValidator(final FilterConfig filterConfig) {
final String casUrlServerPrefix = getPropertyFromInitParams(filterConfig, "casUrlServerPrefix", null);
final Cas10TicketValidator validator = new Cas10TicketValidator(casUrlServerPrefix);
validator.setRenew(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
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(getString(ConfigurationKeys.ENCODING));
return validator;
}

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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;
@ -22,18 +35,19 @@ 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.");
}
try {
final BufferedReader reader = new BufferedReader(new StringReader(
response));
final BufferedReader reader = new BufferedReader(new StringReader(response));
reader.readLine();
final String name = reader.readLine();

View File

@ -1,66 +1,157 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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.proxy.Cas20ProxyRetriever;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl;
import org.jasig.cas.client.util.CommonUtils;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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/>
* 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 Scott Battaglia
* @author Brad Cupit (brad [at] lsu {dot} edu)
* @version $Revision$ $Date$
* @since 3.1
*
*/
public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketValidationFilter {
/**
* Constant representing the ProxyGrantingTicket IOU Request Parameter.
*/
private static final String PARAM_PROXY_GRANTING_TICKET_IOU = "pgtIou";
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()
};
/**
* Constant representing the ProxyGrantingTicket Request Parameter.
*/
private static final String PARAM_PROXY_GRANTING_TICKET = "pgtId";
/**
* 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;
private Timer timer;
private TimerTask timerTask;
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 {
super.initInternal(filterConfig);
setProxyReceptorUrl(getPropertyFromInitParams(filterConfig, "proxyReceptorUrl", null));
public Cas20ProxyReceivingTicketValidationFilter() {
this(Protocol.CAS2);
this.defaultServiceTicketValidatorClass = Cas20ServiceTicketValidator.class;
this.defaultProxyTicketValidatorClass = Cas20ProxyTicketValidator.class;
}
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 = getString(ConfigurationKeys.CIPHER_ALGORITHM);
final String secretKey = getString(ConfigurationKeys.SECRET_KEY);
p.setCipherAlgorithm(cipherAlgorithm);
try {
if (secretKey != null) {
p.setSecretKey(secretKey);
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}
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.");
if (this.timer == null) {
this.timer = new Timer(true);
}
if (this.timerTask == null) {
this.timerTask = new CleanUpTimerTask(this.proxyGrantingTicketStorage);
}
this.timer.schedule(this.timerTask, this.millisBetweenCleanUps, this.millisBetweenCleanUps);
}
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 (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;
}
/**
@ -69,43 +160,64 @@ 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 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)) {
final Cas20ProxyTicketValidator v = new Cas20ProxyTicketValidator(casServerUrlPrefix);
v.setAcceptAnyProxy(Boolean.parseBoolean(allowAnyProxy));
v.setAllowedProxyChains(constructListOfProxies(allowedProxyChains));
if (allowAnyProxy || CommonUtils.isNotBlank(allowedProxyChains)) {
final Cas20ProxyTicketValidator v = createNewTicketValidator(ticketValidatorClass, casServerUrlPrefix,
this.defaultProxyTicketValidatorClass);
v.setAcceptAnyProxy(allowAnyProxy);
v.setAllowedProxyChains(CommonUtils.createProxyList(allowedProxyChains));
validator = v;
} else {
validator = new Cas20ServiceTicketValidator(casServerUrlPrefix);
validator = createNewTicketValidator(ticketValidatorClass, casServerUrlPrefix,
this.defaultServiceTicketValidatorClass);
}
validator.setProxyCallbackUrl(getPropertyFromInitParams(filterConfig, "proxyCallbackUrl", null));
validator.setProxyCallbackUrl(getString(ConfigurationKeys.PROXY_CALLBACK_URL));
validator.setProxyGrantingTicketStorage(this.proxyGrantingTicketStorage);
validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix));
validator.setRenew(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(),
getSSLConfig());
validator.setURLConnectionFactory(factory);
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(); ) {
final String s = (String) e.nextElement();
if (!params.contains(s)) {
additionalParameters.put(s, filterConfig.getInitParameter(s));
}
}
validator.setPrivateKey(this.privateKey);
validator.setCustomParameters(additionalParameters);
return validator;
}
protected final List constructListOfProxies(final String proxies) {
if (CommonUtils.isBlank(proxies)) {
return new ArrayList();
}
final String[] splitProxies = proxies.split("\n");
final List items = Arrays.asList(splitProxies);
final ProxyListPropertyEditor editor = new ProxyListPropertyEditor();
editor.setValue(items);
return (List) editor.getValue();
@Override
public void destroy() {
super.destroy();
this.timer.cancel();
}
/**
* This processes the ProxyReceptor request before the ticket validation code executes.
*/
protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
@Override
protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final String requestUri = request.getRequestURI();
@ -114,29 +226,13 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
return true;
}
final String proxyGrantingTicketIou = request
.getParameter(PARAM_PROXY_GRANTING_TICKET_IOU);
final String proxyGrantingTicket = request
.getParameter(PARAM_PROXY_GRANTING_TICKET);
if (CommonUtils.isBlank(proxyGrantingTicket)
|| CommonUtils.isBlank(proxyGrantingTicketIou)) {
response.getWriter().write("");
return false;
try {
CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
} catch (final RuntimeException e) {
logger.error(e.getMessage(), e);
throw e;
}
if (log.isDebugEnabled()) {
log.debug("Received proxyGrantingTicketId ["
+ proxyGrantingTicket + "] for proxyGrantingTicketIou ["
+ proxyGrantingTicketIou + "]");
}
this.proxyGrantingTicketStorage.save(proxyGrantingTicketIou,
proxyGrantingTicket);
response.getWriter().write("<?xml version=\"1.0\"?>");
response.getWriter().write("<casClient:proxySuccess xmlns:casClient=\"http://www.yale.edu/tp/casClient\" />");
return false;
}
@ -144,7 +240,19 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
this.proxyReceptorUrl = proxyReceptorUrl;
}
public final void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
public void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage storage) {
this.proxyGrantingTicketStorage = storage;
}
public void setTimer(final Timer timer) {
this.timer = timer;
}
public void setTimerTask(final TimerTask timerTask) {
this.timerTask = timerTask;
}
public void setMillisBetweenCleanUps(final int millisBetweenCleanUps) {
this.millisBetweenCleanUps = millisBetweenCleanUps;
}
}

View File

@ -1,62 +1,118 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.jasig.cas.client.util.XmlUtils;
/**
* Extension to the traditional Service Ticket validation that will validate service tickets and proxy tickets.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
public final class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
private boolean acceptAnyProxy;
/** This should be a list of an array of Strings */
private List allowedProxyChains = new ArrayList();
private ProxyList allowedProxyChains = new ProxyList();
/** Allows for an empty chain of proxy callback urls. **/
private boolean allowEmptyProxyChain = true;
public Cas20ProxyTicketValidator(final String casServerUrlPrefix) {
super(casServerUrlPrefix);
}
protected final ProxyList getAllowedProxyChains() {
return this.allowedProxyChains;
}
@Override
protected String getUrlSuffix() {
return "proxyValidate";
}
protected void customParseResponse(final String response, final Assertion assertion) throws TicketValidationException {
final List proxies = XmlUtils.getTextForElements(response, "proxy");
final String[] proxiedList = (String[]) proxies.toArray(new String[proxies.size()]);
@Override
protected void customParseResponse(final String response, final Assertion assertion)
throws TicketValidationException {
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 (proxies == null || proxies.isEmpty() || this.acceptAnyProxy) {
if (this.allowEmptyProxyChain && proxies.isEmpty()) {
logger.debug("Found an empty proxy chain, permitted by client configuration");
return;
}
for (Iterator iter = this.allowedProxyChains.iterator(); iter.hasNext();) {
if (Arrays.equals(proxiedList, (String[]) iter.next())) {
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;
}
final String[] proxiedList = proxies.toArray(new String[proxies.size()]);
if (this.allowedProxyChains.contains(proxiedList)) {
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());
}
public void setAcceptAnyProxy(final boolean acceptAnyProxy) {
protected List<String> parseProxiesFromResponse(final String response) {
return XmlUtils.getTextForElements(response, "proxy");
}
public final void setAcceptAnyProxy(final boolean acceptAnyProxy) {
this.acceptAnyProxy = acceptAnyProxy;
}
public void setAllowedProxyChains(final List allowedProxyChains) {
public final void setAllowedProxyChains(final ProxyList allowedProxyChains) {
this.allowedProxyChains = allowedProxyChains;
}
protected final boolean isAcceptAnyProxy() {
return this.acceptAnyProxy;
}
protected final boolean isAllowEmptyProxyChain() {
return this.allowEmptyProxyChain;
}
/**
* Set to determine whether empty proxy chains are allowed.
* @see #customParseResponse(String, Assertion)
* @param allowEmptyProxyChain whether to allow empty proxy chains or not. True if so, false otherwise.
*/
public final void setAllowEmptyProxyChain(final boolean allowEmptyProxyChain) {
this.allowEmptyProxyChain = allowEmptyProxyChain;
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.validation;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.SimpleBeanInfo;
import org.springframework.beans.propertyeditors.CustomBooleanEditor;
/**
* BeanInfo support for using this class with Spring. Configures a ProxyListPropertyEditor to be used with the
* Cas20ProxyTicketValidator when Spring is used to configure the CAS client.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
public final class Cas20ProxyTicketValidatorBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
final PropertyDescriptor descriptor = new PropertyDescriptor("allowedProxyChains", Cas20ProxyTicketValidator.class, null, "setAllowedProxyChains") {
public PropertyEditor createPropertyEditor(final Object bean) {
return new ProxyListPropertyEditor();
}
};
final PropertyDescriptor acceptAnyProxy = new PropertyDescriptor("acceptAnyProxy", Cas20ProxyTicketValidator.class, null, "setAcceptAnyProxy") {
public PropertyEditor createPropertyEditor(final Object bean) {
return new CustomBooleanEditor(true);
}
};
return new PropertyDescriptor[] {descriptor, acceptAnyProxy};
} catch (final IntrospectionException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,10 +1,31 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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 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;
@ -12,18 +33,23 @@ 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.util.XmlUtils;
import java.util.Map;
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;
/**
* Implementation of the TicketValidator that will validate Service Tickets in compliance with the CAS 2.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
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;
@ -33,6 +59,9 @@ 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.
@ -41,7 +70,7 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
*/
public Cas20ServiceTicketValidator(final String casServerUrlPrefix) {
super(casServerUrlPrefix);
this.proxyRetriever = new Cas20ProxyRetriever(casServerUrlPrefix);
this.proxyRetriever = new Cas20ProxyRetriever(casServerUrlPrefix, getEncoding(), getURLConnectionFactory());
}
/**
@ -49,37 +78,40 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
*
* @param urlParameters the Map containing the existing parameters to send to the server.
*/
protected final void populateUrlAttributeMap(final Map urlParameters) {
urlParameters.put("pgtUrl", encodeUrl(this.proxyCallbackUrl));
@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 = this.proxyGrantingTicketStorage != null ? this.proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou) : null;
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.");
}
final Assertion assertion;
final Map<String, Object> attributes = extractCustomAttributes(response);
if (CommonUtils.isNotBlank(proxyGrantingTicket)) {
final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, proxyGrantingTicket, this.proxyRetriever);
attributes.remove(PGT_ATTRIBUTE);
final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes,
proxyGrantingTicket, this.proxyRetriever);
assertion = new AssertionImpl(attributePrincipal);
} else {
assertion = new AssertionImpl(principal);
assertion = new AssertionImpl(new AttributePrincipalImpl(principal, attributes));
}
customParseResponse(response, assertion);
@ -87,6 +119,87 @@ 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:
* &lt;cas:attributes&gt;
* &lt;cas:attribute1&gt;value&lt;/cas:attribute1&gt;
* &lt;cas:attribute2&gt;value&lt;/cas:attribute2&gt;
* &lt;/cas:attributes&gt;
* <p>
*
* Attributes look like following also parsed correctly:
* &lt;cas:attributes&gt;&lt;cas:attribute1&gt;value&lt;/cas:attribute1&gt;&lt;cas:attribute2&gt;value&lt;/cas:attribute2&gt;&lt;/cas:attributes&gt;
* <p>
*
* This code is here merely for sample/demonstration purposes for those wishing to modify the CAS2 protocol. You'll
* probably want a more robust implementation or to use SAML 1.1
*
* @param xml the XML to parse.
* @return the map of attributes.
*/
protected Map<String, Object> extractCustomAttributes(final String xml) {
final SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
try {
final SAXParser saxParser = spf.newSAXParser();
final XMLReader xmlReader = saxParser.getXMLReader();
final CustomAttributeHandler handler = new CustomAttributeHandler();
xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource(new StringReader(xml)));
return handler.getAttributes();
} catch (final Exception e) {
logger.error(e.getMessage(), e);
return Collections.emptyMap();
}
}
/**
* Template method if additional custom parsing (such as Proxying) needs to be done.
*
@ -94,7 +207,8 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
* @param assertion the partially constructed assertion.
* @throws TicketValidationException if there is a problem constructing the Assertion.
*/
protected void customParseResponse(final String response, final Assertion assertion) throws TicketValidationException {
protected void customParseResponse(final String response, final Assertion assertion)
throws TicketValidationException {
// nothing to do
}
@ -108,5 +222,88 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
public final void setProxyRetriever(final ProxyRetriever proxyRetriever) {
this.proxyRetriever = proxyRetriever;
}
}
protected final String getProxyCallbackUrl() {
return this.proxyCallbackUrl;
}
protected final ProxyGrantingTicketStorage getProxyGrantingTicketStorage() {
return this.proxyGrantingTicketStorage;
}
protected final ProxyRetriever getProxyRetriever() {
return this.proxyRetriever;
}
private class CustomAttributeHandler extends DefaultHandler {
private Map<String, Object> attributes;
private boolean foundAttributes;
private String currentAttribute;
private StringBuilder value;
@Override
public void startDocument() throws SAXException {
this.attributes = new HashMap<String, Object>();
}
@Override
public void startElement(final String namespaceURI, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if ("attributes".equals(localName)) {
this.foundAttributes = true;
} else if (this.foundAttributes) {
this.value = new StringBuilder();
this.currentAttribute = localName;
}
}
@Override
public void characters(final char[] chars, final int start, final int length) throws SAXException {
if (this.currentAttribute != null) {
value.append(chars, start, length);
}
}
@Override
public void endElement(final String namespaceURI, final String localName, final String qName)
throws SAXException {
if ("attributes".equals(localName)) {
this.foundAttributes = false;
this.currentAttribute = null;
} else if (this.foundAttributes) {
final Object o = this.attributes.get(this.currentAttribute);
if (o == null) {
this.attributes.put(this.currentAttribute, this.value.toString());
} else {
final List<Object> items;
if (o instanceof List) {
items = (List<Object>) o;
} else {
items = new LinkedList<Object>();
items.add(o);
this.attributes.put(this.currentAttribute, items);
}
items.add(this.value.toString());
}
}
}
public Map<String, Object> getAttributes() {
return this.attributes;
}
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public void setPrivateKey(final PrivateKey privateKey) {
this.privateKey = privateKey;
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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;
@ -15,11 +28,11 @@ package org.jasig.cas.client.validation;
public final class InvalidProxyChainTicketValidationException extends TicketValidationException {
/**
* Unique Id for Serialization
*/
private static final long serialVersionUID = -7736653266370691534L;
* Unique Id for Serialization
*/
private static final long serialVersionUID = -7736653266370691534L;
/**
/**
* Constructs an exception with the supplied message.
* @param string the supplied message.
*/

View File

@ -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.validation;
import java.util.ArrayList;
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.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.3
*/
public final class ProxyList {
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 = 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(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;
}
public String toString() {
return this.proxyChains.toString();
}
}

View File

@ -0,0 +1,63 @@
/**
* 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 java.beans.PropertyEditorSupport;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.jasig.cas.client.util.CommonUtils;
/**
* Convert a String-formatted list of acceptable proxies to an array.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*
*/
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[]>();
try {
String line;
while ((line = reader.readLine()) != null) {
if (CommonUtils.isNotBlank(line)) {
proxyChains.add(line.trim().split(" "));
}
}
} catch (final IOException e) {
// ignore this
} finally {
try {
reader.close();
} catch (final IOException e) {
// nothing to do
}
}
setValue(new ProxyList(proxyChains));
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.validation;
import java.beans.PropertyEditorSupport;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.jasig.cas.client.util.CommonUtils;
/**
* Convert a String-formatted list of acceptable proxies to an array.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*
*/
public final class ProxyListPropertyEditor extends PropertyEditorSupport {
public void setAsText(final String text) throws IllegalArgumentException {
final BufferedReader reader = new BufferedReader(new StringReader(text));
final List proxyChains = new ArrayList();
try {
String line;
while ((line = reader.readLine()) != null) {
if (CommonUtils.isNotBlank(line)) {
proxyChains.add(line.trim().split(" "));
}
}
} catch (final IOException e) {
// ignore this
} finally {
try {
reader.close();
} catch (final IOException e) {
// nothing to do
}
}
setValue(proxyChains);
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.validation;
import javax.servlet.FilterConfig;
/**
* Implementation of TicketValidationFilter that can instanciate a SAML 1.1 Ticket Validator.
* <p>
* Deployers can provide the "casServerUrlPrefix" and "tolerance" properties of the Saml11TicketValidator via the
* context or filter init parameters.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
public class Saml11TicketValidationFilter extends AbstractTicketValidationFilter {
public Saml11TicketValidationFilter() {
setArtifactParameterName("SAMLart");
setServiceParameterName("TARGET");
}
protected final TicketValidator getTicketValidator(final FilterConfig filterConfig) {
final Saml11TicketValidator validator = new Saml11TicketValidator(getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null));
final String tolerance = getPropertyFromInitParams(filterConfig, "tolerance", "1000");
validator.setTolerance(Long.parseLong(tolerance));
return validator;
}
}

View File

@ -1,204 +0,0 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.validation;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.opensaml.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
/**
* TicketValidator that can understand validating a SAML artifact. This includes the SOAP request/response.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*/
public final class Saml11TicketValidator extends AbstractUrlBasedTicketValidator {
/** Time tolerance to allow for time drifting. */
private long tolerance = 1000L;
public Saml11TicketValidator(final String casServerUrlPrefix) {
super(casServerUrlPrefix);
}
protected String getUrlSuffix() {
return "samlValidate";
}
protected void populateUrlAttributeMap(final Map urlParameters) {
final String service = (String) urlParameters.get("service");
urlParameters.remove("service");
urlParameters.remove("ticket");
urlParameters.put("TARGET", service);
}
protected Assertion parseResponseFromServer(final String response) throws TicketValidationException {
try {
final SAMLResponse samlResponse = new SAMLResponse(new ByteArrayInputStream(response.getBytes()));
if (!samlResponse.getAssertions().hasNext()) {
throw new TicketValidationException("No assertions found.");
}
for (final Iterator iter = samlResponse.getAssertions(); iter.hasNext();) {
final SAMLAssertion assertion = (SAMLAssertion) iter.next();
if (!isValidAssertion(assertion)) {
continue;
}
final SAMLAuthenticationStatement authenticationStatement = getSAMLAuthenticationStatement(assertion);
if (authenticationStatement == null) {
throw new TicketValidationException("No AuthentiationStatement found in SAML Assertion.");
}
final SAMLSubject subject = authenticationStatement.getSubject();
if (subject == null) {
throw new TicketValidationException("No Subject found in SAML Assertion.");
}
final SAMLAttribute[] attributes = getAttributesFor(assertion, subject);
final Map personAttributes = new HashMap();
for (int i = 0; i < attributes.length; i++) {
final SAMLAttribute samlAttribute = attributes[i];
final List values = getValuesFrom(samlAttribute);
personAttributes.put(samlAttribute.getName(), values.size() == 1 ? values.get(0) : values);
}
final AttributePrincipal principal = new AttributePrincipalImpl(subject.getNameIdentifier().getName(), personAttributes);
final Map authenticationAttributes = new HashMap();
authenticationAttributes.put("samlAuthenticationStatement::authMethod", authenticationStatement.getAuthMethod());
final Assertion casAssertion = new AssertionImpl(principal, authenticationAttributes);
return casAssertion;
}
} catch (final SAMLException e) {
throw new TicketValidationException(e);
}
throw new TicketValidationException("No valid assertions from the SAML response found.");
}
private boolean isValidAssertion(final SAMLAssertion assertion) {
final Date notBefore = assertion.getNotBefore();
final Date notOnOrAfter = assertion.getNotOnOrAfter();
if (assertion.getNotBefore() == null || assertion.getNotOnOrAfter() == null) {
log.debug("Assertion has no bounding dates. Will not process.");
return false;
}
final long currentTime = new Date().getTime();
if (currentTime + tolerance < notBefore.getTime()) {
log.debug("skipping assertion that's not yet valid...");
return false;
}
if (notOnOrAfter.getTime() <= currentTime - tolerance) {
log.debug("skipping expired assertion...");
return false;
}
return true;
}
private SAMLAuthenticationStatement getSAMLAuthenticationStatement(final SAMLAssertion assertion) {
for (final Iterator iter = assertion.getStatements(); iter.hasNext();) {
final SAMLStatement statement = (SAMLStatement) iter.next();
if (statement instanceof SAMLAuthenticationStatement) {
return (SAMLAuthenticationStatement) statement;
}
}
return null;
}
private SAMLAttribute[] getAttributesFor(final SAMLAssertion assertion, final SAMLSubject subject) {
final List attributes = new ArrayList();
for (final Iterator iter = assertion.getStatements(); iter.hasNext();) {
final SAMLStatement statement = (SAMLStatement) iter.next();
if (statement instanceof SAMLAttributeStatement) {
final SAMLAttributeStatement attributeStatement = (SAMLAttributeStatement) statement;
// used because SAMLSubject does not implement equals
if (subject.getNameIdentifier().getName().equals(attributeStatement.getSubject().getNameIdentifier().getName())) {
for (final Iterator iter2 = attributeStatement.getAttributes(); iter2.hasNext();)
attributes.add(iter2.next());
}
}
}
return (SAMLAttribute[]) attributes.toArray(new SAMLAttribute[attributes.size()]);
}
private List getValuesFrom(final SAMLAttribute attribute) {
final List list = new ArrayList();
for (final Iterator iter = attribute.getValues(); iter.hasNext();) {
list.add(iter.next());
}
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=\"_192.168.16.51.1024506224022\" IssueInstant=\"2002-06-19T17:03:44.022Z\">"
+ "<samlp:AssertionArtifact>" + ticket
+ "</samlp:AssertionArtifact></samlp:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>";
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) validationUrl.openConnection();
conn.setRequestMethod("POST");
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);
final DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes(MESSAGE_TO_SEND);
out.flush();
out.close();
final BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
final StringBuffer buffer = new StringBuffer(256);
synchronized (buffer) {
String line;
while ((line = in.readLine()) != null) {
buffer.append(line);
}
return buffer.toString();
}
} catch (final IOException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
public void setTolerance(final long tolerance) {
this.tolerance = tolerance;
}
}

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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;
@ -15,11 +28,11 @@ package org.jasig.cas.client.validation;
public class TicketValidationException extends Exception {
/**
* Unique Id for Serialization
*/
private static final long serialVersionUID = -7036248720402711806L;
* Unique Id for Serialization
*/
private static final long serialVersionUID = -7036248720402711806L;
/**
/**
* Constructs an exception with the supplied message.
*
* @param string the message

View File

@ -1,7 +1,20 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
/**
* 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;

View File

@ -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;
}
}

Some files were not shown because too many files have changed in this diff Show More