From 7c4d56319f8c89220119885722fdc52278cba45e Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Fri, 7 Feb 2020 16:43:33 -0700 Subject: [PATCH] cassample groovy->java Issue gh-4939 --- ...ring-security-samples-xml-cassample.gradle | 11 -- .../samples/cas/AbstractCasTests.groovy | 36 ---- .../samples/cas/CasSampleProxyTests.groovy | 122 -------------- .../samples/cas/CasSampleTests.groovy | 135 --------------- .../samples/cas/modules/NavModule.groovy | 31 ---- .../cas/pages/ExtremelySecurePage.groovy | 32 ---- .../samples/cas/pages/HomePage.groovy | 32 ---- .../samples/cas/pages/LoginPage.groovy | 46 ----- .../cas/pages/ProxyTicketSamplePage.groovy | 33 ---- .../samples/cas/pages/SecurePage.groovy | 33 ---- .../samples/cas/CasSampleProxyTests.java | 147 ++++++++++++++++ .../security/samples/cas/CasSampleTests.java | 157 ++++++++++++++++++ .../samples/cas/JettyCasService.java} | 114 +++++++------ .../samples/cas/pages/AccessDeniedPage.java} | 31 +++- .../cas/pages/ExtremelySecurePage.java | 53 ++++++ .../security/samples/cas/pages/HomePage.java | 53 ++++++ .../samples/cas/pages/LocalLogoutPage.java} | 12 +- .../security/samples/cas/pages/LoginPage.java | 65 ++++++++ .../security/samples/cas/pages/Page.java | 51 ++++++ .../cas/pages/ProxyTicketSamplePage.java | 53 ++++++ .../samples/cas/pages/SecurePage.java | 66 ++++++++ .../samples/cas/pages/UnauthorizedPage.java | 51 ++++++ .../xml/cas/cassample/src/main/webapp/401.jsp | 8 + .../cassample/src/main/webapp/WEB-INF/web.xml | 4 + .../cassample/src/main/webapp/cas-logout.jsp | 4 +- .../cas/cassample/src/main/webapp/index.jsp | 8 +- .../src/main/webapp/secure/extreme/index.jsp | 12 +- .../src/main/webapp/secure/index.jsp | 8 +- 28 files changed, 822 insertions(+), 586 deletions(-) delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/AbstractCasTests.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleProxyTests.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleTests.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/modules/NavModule.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ExtremelySecurePage.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/HomePage.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LoginPage.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.groovy delete mode 100644 samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/SecurePage.groovy create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleProxyTests.java create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleTests.java rename samples/xml/cas/cassample/src/integration-test/{groovy/org/springframework/security/samples/cas/JettyCasService.groovy => java/org/springframework/security/samples/cas/JettyCasService.java} (53%) rename samples/xml/cas/cassample/src/integration-test/{groovy/org/springframework/security/samples/cas/pages/AccessDeniedPage.groovy => java/org/springframework/security/samples/cas/pages/AccessDeniedPage.java} (51%) create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ExtremelySecurePage.java create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/HomePage.java rename samples/xml/cas/cassample/src/integration-test/{groovy/org/springframework/security/samples/cas/pages/LocalLogoutPage.groovy => java/org/springframework/security/samples/cas/pages/LocalLogoutPage.java} (83%) create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LoginPage.java create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/Page.java create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.java create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/SecurePage.java create mode 100644 samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/UnauthorizedPage.java create mode 100644 samples/xml/cas/cassample/src/main/webapp/401.jsp diff --git a/samples/xml/cas/cassample/spring-security-samples-xml-cassample.gradle b/samples/xml/cas/cassample/spring-security-samples-xml-cassample.gradle index ba67be2f28..9fedcea3bd 100644 --- a/samples/xml/cas/cassample/spring-security-samples-xml-cassample.gradle +++ b/samples/xml/cas/cassample/spring-security-samples-xml-cassample.gradle @@ -3,12 +3,6 @@ apply plugin: 'io.spring.convention.spring-sample-war' def keystore = "$rootDir/samples/certificates/server.jks" def password = 'password' - -sourceSets { - test.resources.exclude 'GebConfig.groovy' - integrationTest.groovy.srcDir file('src/integration-test/groovy') -} - dependencies { compile project(':spring-security-cas') compile project(':spring-security-core') @@ -24,10 +18,7 @@ dependencies { runtime 'org.springframework:spring-context-support' integrationTestCompile project(':spring-security-cas') - integrationTestCompile gebDependencies integrationTestCompile seleniumDependencies - integrationTestCompile spockDependencies - integrationTestCompile 'org.codehaus.groovy:groovy' integrationTestCompile 'org.eclipse.jetty:jetty-server' integrationTestCompile 'org.eclipse.jetty:jetty-servlet' integrationTestCompile 'org.slf4j:jcl-over-slf4j' @@ -40,8 +31,6 @@ integrationTest { def casServerHost = 'localhost:' + casServer().gretty.httpsPort systemProperties['cas.server.host'] = casServerHost systemProperties['cas.service.host'] = casServiceHost - systemProperties['geb.build.baseUrl'] = 'https://'+casServiceHost+'/cas-sample/' - systemProperties['geb.build.reportsDir'] = 'build/geb-reports' systemProperties['jar.path'] = jar.archivePath systemProperties['javax.net.ssl.trustStore'] = keystore systemProperties['javax.net.ssl.trustStorePassword'] = password diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/AbstractCasTests.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/AbstractCasTests.groovy deleted file mode 100644 index 87b2e9f88d..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/AbstractCasTests.groovy +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas - -import org.springframework.security.samples.cas.pages.LoginPage; - -import java.io.File; - -import geb.spock.* - - -/** - * Base test for Geb testing. - * - * @author Rob Winch - */ -class AbstractCasTests extends GebReportingSpec { - - def cleanupSpec() { - to LoginPage - resetBrowser() - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleProxyTests.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleProxyTests.groovy deleted file mode 100644 index 269cf5d79a..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleProxyTests.groovy +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas - -import org.apache.commons.httpclient.HttpClient -import org.apache.commons.httpclient.methods.GetMethod -import org.jasig.cas.client.jaas.CasLoginModule; -import org.jasig.cas.client.proxy.Cas20ProxyRetriever -import org.springframework.security.samples.cas.pages.* - -import spock.lang.* - - -/** - * Tests authenticating to the CAS Sample application using Proxy Tickets. Geb is used to authenticate the {@link JettyCasService} - * to the CAS Server in order to obtain the Ticket Granting Ticket. Afterwards HttpClient is used for accessing the CAS Sample application - * using Proxy Tickets obtained using the Proxy Granting Ticket. - * - * @author Rob Winch - */ -@Stepwise -class CasSampleProxyTests extends AbstractCasTests { - HttpClient client = new HttpClient() - @Shared String casServerUrl = LoginPage.url.replaceFirst('/login','') - @Shared JettyCasService service = new JettyCasService().init(casServerUrl) - @Shared Cas20ProxyRetriever retriever = new Cas20ProxyRetriever(casServerUrl,'UTF-8') - @Shared String pt - - def cleanupSpec() { - service.stop() - } - - def 'access secure page succeeds with ROLE_USER'() { - setup: 'Obtain a pgt for a user with ROLE_USER' - driver.get LoginPage.url+"?service="+service.serviceUrl() - at LoginPage - login 'scott' - when: 'User with ROLE_USER accesses the secure page' - def content = getSecured(getBaseUrl()+SecurePage.url).responseBodyAsString - then: 'The secure page is returned' - content.contains('

Secure Page

') - } - - def 'access proxy ticket sample succeeds with ROLE_USER'() { - when: 'a proxy ticket is used to create another proxy ticket' - def content = getSecured(getBaseUrl()+ProxyTicketSamplePage.url).responseBodyAsString - then: 'The proxy ticket sample page is returned' - content.contains('

Secure Page using a Proxy Ticket

') - } - - def 'access extremely secure page with ROLE_USER is denied'() { - when: 'User with ROLE_USER accesses the extremely secure page' - GetMethod method = getSecured(getBaseUrl()+ExtremelySecurePage.url) - then: 'access is denied' - assert method.responseBodyAsString =~ /(?i)403.*?Denied/ - assert 403 == method.statusCode - } - - def 'access secure page with ROLE_SUPERVISOR succeeds'() { - setup: 'Obtain pgt for user with ROLE_SUPERVISOR' - to LocalLogoutPage - casServerLogout.click() - driver.get(LoginPage.url+"?service="+service.serviceUrl()) - at LoginPage - login 'rod' - when: 'User with ROLE_SUPERVISOR accesses the secure page' - def content = getSecured(getBaseUrl()+ExtremelySecurePage.url).responseBodyAsString - then: 'The secure page is returned' - content.contains('

VERY Secure Page

') - } - - def 'access extremely secure page with ROLE_SUPERVISOR reusing pt succeeds (stateless mode works)'() { - when: 'User with ROLE_SUPERVISOR accesses extremely secure page with used pt' - def content = getSecured(getBaseUrl()+ExtremelySecurePage.url,pt).responseBodyAsString - then: 'The extremely secure page is returned' - content.contains('

VERY Secure Page

') - } - - def 'access secure page with invalid proxy ticket fails'() { - when: 'Invalid ticket is used to access secure page' - GetMethod method = getSecured(getBaseUrl()+SecurePage.url,'invalidticket') - then: 'Authentication fails' - method.statusCode == 401 - } - - /** - * Gets the result of calling a url with a proxy ticket - * @param targetUrl the absolute url to attempt to access - * @param pt the proxy ticket to use. Defaults to {@link #getPt(String)} with targetUrl specified for the targetUrl. - * @return the GetMethod after calling a url with a specified proxy ticket - */ - GetMethod getSecured(String targetUrl,String pt=getPt(targetUrl)) { - assert pt != null - GetMethod method = new GetMethod(targetUrl+"?ticket="+pt) - int status = client.executeMethod(method) - method - } - - /** - * Obtains a proxy ticket using the pgt from the {@link #service}. - * @param targetService the targetService that the proxy ticket will be valid for - * @return a proxy ticket for targetService - */ - String getPt(String targetService) { - assert service.pgt != null - pt = retriever.getProxyTicketIdFor(service.pgt, targetService) - pt - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleTests.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleTests.groovy deleted file mode 100644 index 341d0ae9a5..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleTests.groovy +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas - -import geb.spock.* - -import org.apache.http.impl.conn.DefaultClientConnectionOperator; -import org.junit.runner.RunWith; -import org.spockframework.runtime.Sputnik; -import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; -import org.springframework.security.core.context.ThreadLocalSecurityContextHolderStrategy; -import org.springframework.security.samples.cas.pages.* - -import spock.lang.Shared; -import spock.lang.Stepwise; - -/** - * Tests the CAS sample application using service tickets. - * - * @author Rob Winch - */ -@Stepwise -class CasSampleTests extends AbstractCasTests { - @Shared String casServerLogoutUrl = LoginPage.url.replaceFirst('/login','/logout') - - def 'access home page with unauthenticated user succeeds'() { - when: 'Unauthenticated user accesses the Home Page' - to HomePage - then: 'The home page succeeds' - at HomePage - } - - def 'access extremely secure page with unauthenitcated user requires login'() { - when: 'Unauthenticated user accesses the extremely secure page' - via ExtremelySecurePage - then: 'The login page is displayed' - at LoginPage - } - - def 'authenticate attempt with invaid ticket fails'() { - when: 'present invalid ticket' - go "login/cas?ticket=invalid" - then: 'the login failed page is displayed' - $("h2").text() == 'Login to CAS failed!' - } - - def 'access secure page with unauthenticated user requires login'() { - when: 'Unauthenticated user accesses the secure page' - via SecurePage - then: 'The login page is displayed' - at LoginPage - } - - def 'saved request is used for secure page'() { - when: 'login with ROLE_USER after requesting the secure page' - login 'scott' - then: 'the secure page is displayed' - at SecurePage - } - - def 'access proxy ticket sample with ROLE_USER is allowed'() { - when: 'user with ROLE_USER requests the proxy ticket sample page' - to ProxyTicketSamplePage - then: 'the proxy ticket sample page is displayed' - at ProxyTicketSamplePage - } - - def 'access extremely secure page with ROLE_USER is denied'() { - when: 'User with ROLE_USER accesses extremely secure page' - via ExtremelySecurePage - then: 'the access denied page is displayed' - at AccessDeniedPage - } - - def 'clicking local logout link displays local logout page'() { - setup: 'Navigate to page with logout link' - to SecurePage - when: 'Local logout link is clicked' - navModule.logout.click() - then: 'the local logout page is displayed' - at LocalLogoutPage - } - - def 'clicking cas server logout link successfully performs logout'() { - when: 'the cas server logout link is clicked and the secure page is requested' - casServerLogout.click() - via SecurePage - then: 'the login page is displayed' - at LoginPage - } - - def 'access extremely secure page with ROLE_SUPERVISOR succeeds'() { - setup: 'login with ROLE_SUPERVISOR' - login 'rod' - when: 'access extremely secure page' - to ExtremelySecurePage - then: 'extremely secure page is displayed' - at ExtremelySecurePage - } - - def 'after logout extremely secure page requires login'() { - when: 'logout and request extremely secure page' - navModule.logout.click() - casServerLogout.click() - via ExtremelySecurePage - then: 'login page is displayed' - at LoginPage - } - - def 'logging out of the cas server successfully logs out of the cas sample application'() { - setup: 'login with ROLE_USER' - via SecurePage - at LoginPage - login 'rod' - at SecurePage - when: 'logout of the CAS Server' - go casServerLogoutUrl - via SecurePage - then: 'user is logged out of the CAS Service' - at LoginPage - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/modules/NavModule.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/modules/NavModule.groovy deleted file mode 100644 index be59e8c31f..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/modules/NavModule.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas.modules; - -import geb.* -import org.springframework.security.samples.cas.pages.* - -/** - * Represents the navigation for the CAS Sample application - * - * @author Rob Winch - */ -class NavModule extends Module { - static content = { - home(to: HomePage) { $("a", text: "Home") } - logout(to: LocalLogoutPage) { $("a", text: "Logout") } - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ExtremelySecurePage.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ExtremelySecurePage.groovy deleted file mode 100644 index 580656764a..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ExtremelySecurePage.groovy +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas.pages; - -import geb.* -import org.springframework.security.samples.cas.modules.* - -/** - * Represents the extremely secure page of the CAS Sample application. - * - * @author Rob Winch - */ -class ExtremelySecurePage extends Page { - static url = "secure/extreme/" - static at = { assert $('h1').text() == 'VERY Secure Page'; true; } - static content = { - navModule { module NavModule } - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/HomePage.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/HomePage.groovy deleted file mode 100644 index fa14033ec8..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/HomePage.groovy +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas.pages - -import geb.* - -/** - * Represents the Home page of the CAS sample application - * - * @author Rob Winch - */ -class HomePage extends Page { - static at = { assert $('h1').text() == 'Home Page'; true} - static url = '' - static content = { - securePage { $('a',text: 'Secure page') } - extremelySecurePage { $('a',text: 'Extremely secure page') } - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LoginPage.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LoginPage.groovy deleted file mode 100644 index 2d06717b85..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LoginPage.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas.pages; - -import geb.* - -/** - * The CAS login page. - * - * @author Rob Winch - */ -class LoginPage extends Page { - static url = loginUrl() - static at = { assert driver.currentUrl.startsWith(loginUrl()); true} - static content = { - login(required:false) { user, password=user -> - loginForm.username = user - loginForm.password = password - submit.click() - } - loginForm { $('#login') } - submit { $('input', type: 'submit') } - } - - /** - * Gets the login page url which might change based upon the system properties. This is to support using a randomly available port for CI. - * @return - */ - private static String loginUrl() { - def host = System.getProperty('cas.server.host', 'localhost:9443') - "https://${host}/cas/login" - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.groovy deleted file mode 100644 index 4a4fb22619..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas.pages; - -import geb.* -import org.springframework.security.samples.cas.modules.* - - -/** - * Represents the proxy ticket sample page within the CAS Sample application. - * - * @author Rob Winch - */ -class ProxyTicketSamplePage extends Page { - static url = "secure/ptSample" - static at = { assert $('h1').text() == 'Secure Page using a Proxy Ticket'; true} - static content = { - navModule { module NavModule } - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/SecurePage.groovy b/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/SecurePage.groovy deleted file mode 100644 index 0d069c3df3..0000000000 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/SecurePage.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples.cas.pages; - -import geb.* -import org.springframework.security.samples.cas.modules.* - - -/** - * Represents the secure page within the CAS Sample application. - * - * @author Rob Winch - */ -class SecurePage extends Page { - static url = "secure/" - static at = { assert $('h1').text() == 'Secure Page'; true} - static content = { - navModule { module NavModule } - } -} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleProxyTests.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleProxyTests.java new file mode 100644 index 0000000000..de65160781 --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleProxyTests.java @@ -0,0 +1,147 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas; + +import java.util.HashMap; +import java.util.Map; + +import org.jasig.cas.client.proxy.Cas20ProxyRetriever; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.htmlunit.HtmlUnitDriver; + +import org.springframework.security.samples.cas.pages.AccessDeniedPage; +import org.springframework.security.samples.cas.pages.ExtremelySecurePage; +import org.springframework.security.samples.cas.pages.LoginPage; +import org.springframework.security.samples.cas.pages.ProxyTicketSamplePage; +import org.springframework.security.samples.cas.pages.SecurePage; +import org.springframework.security.samples.cas.pages.UnauthorizedPage; + +/** + * Tests authenticating to the CAS Sample application using Proxy Tickets. Geb is used to authenticate the {@link JettyCasService} + * to the CAS Server in order to obtain the Ticket Granting Ticket. Afterwards HttpClient is used for accessing the CAS Sample application + * using Proxy Tickets obtained using the Proxy Granting Ticket. + * + * @author Rob Winch + * @author Josh Cummings + */ +public class CasSampleProxyTests { + private static String serverUrl; + private static String serviceUrl; + private static JettyCasService service; + private static Cas20ProxyRetriever retriever; + + private WebDriver driver = new HtmlUnitDriver(); + + private LoginPage login; + private SecurePage secure; + private ExtremelySecurePage extremelySecure; + private ProxyTicketSamplePage proxyTicketSample; + private AccessDeniedPage accessDenied; + private UnauthorizedPage unauthorized; + + @BeforeClass + public static void setupClass() { + String serverHost = System.getProperty("cas.server.host", "localhost:8443"); + serverUrl = "https://" + serverHost + "/cas"; + String serviceHost = System.getProperty("cas.service.host", "localhost:8443"); + serviceUrl = "https://" + serviceHost + "/cas-sample"; + service = new JettyCasService().init(serverUrl); + retriever = new Cas20ProxyRetriever(serverUrl, "UTF-8"); + } + + @AfterClass + public static void teardownClass() throws Exception { + service.stop(); + } + + @Before + public void setup() { + this.login = new LoginPage(this.driver, serverUrl); + this.secure = new SecurePage(this.driver, serviceUrl); + this.extremelySecure = new ExtremelySecurePage(this.driver, serviceUrl); + this.proxyTicketSample = new ProxyTicketSamplePage(this.driver, serviceUrl); + this.accessDenied = new AccessDeniedPage(this.driver); + this.unauthorized = new UnauthorizedPage(this.driver); + } + + @After + public void teardown() { + this.driver.close(); + } + + @Test + public void securePageWhenRoleUserThenDisplays() { + this.login.to(this::serviceParam).assertAt().login("scott"); + this.secure.to(this::ticketParam).assertAt(); + } + + @Test + public void proxyTicketSamplePageWhenRoleUserThenDisplays() { + this.login.to(this::serviceParam).assertAt().login("scott"); + this.proxyTicketSample.to(this::ticketParam).assertAt(); + } + + @Test + public void extremelySecurePageWhenRoleUserThenDenies() { + this.login.to(this::serviceParam).assertAt().login("scott"); + this.extremelySecure.to(this::ticketParam); + this.accessDenied.assertAt(); + } + + @Test + public void extremelySecurePageWhenRoleSupervisorThenDisplays() { + this.login.to(this::serviceParam).assertAt().login("rod"); + this.extremelySecure.to(this::ticketParam).assertAt(); + } + + @Test + public void extremelySecurePageWhenReusingTicketThenDisplays() { + this.login.to(this::serviceParam).assertAt().login("rod"); + Map ptCache = new HashMap<>(); + this.extremelySecure.to(url -> url + "?ticket=" + ptCache.computeIfAbsent(url, this::getPt)).assertAt(); + this.extremelySecure.to(url -> url + "?ticket=" + ptCache.get(url)).assertAt(); + } + + @Test + public void securePageWhenInvalidTicketThenFails() { + this.login.to(this::serviceParam).assertAt().login("scott"); + this.secure.to(url -> url + "?ticket=invalid"); + this.unauthorized.assertAt(); + } + + private String serviceParam(String url) { + return url + "?service=" + service.serviceUrl(); + } + + private String ticketParam(String url) { + return url + "?ticket=" + getPt(url); + } + + /** + * Obtains a proxy ticket using the pgt from the {@link #service}. + * @param targetService the targetService that the proxy ticket will be valid for + * @return a proxy ticket for targetService + */ + String getPt(String targetService) { + assert service.pgt != null; + return retriever.getProxyTicketIdFor(service.pgt, targetService); + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleTests.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleTests.java new file mode 100644 index 0000000000..c03ef891fc --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/CasSampleTests.java @@ -0,0 +1,157 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.htmlunit.HtmlUnitDriver; + +import org.springframework.security.samples.cas.pages.AccessDeniedPage; +import org.springframework.security.samples.cas.pages.ExtremelySecurePage; +import org.springframework.security.samples.cas.pages.HomePage; +import org.springframework.security.samples.cas.pages.LocalLogoutPage; +import org.springframework.security.samples.cas.pages.LoginPage; +import org.springframework.security.samples.cas.pages.ProxyTicketSamplePage; +import org.springframework.security.samples.cas.pages.SecurePage; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests the CAS sample application using service tickets. + * + * @author Rob Winch + * @author Josh Cummings + */ +public class CasSampleTests { + private WebDriver driver = new HtmlUnitDriver(); + + private String serviceUrl; + private String serverUrl; + + private LoginPage login; + + private HomePage home; + private SecurePage secure; + private ExtremelySecurePage extremelySecure; + private ProxyTicketSamplePage proxyTicketSample; + private LocalLogoutPage localLogout; + private AccessDeniedPage accessDenied; + + @Before + public void setup() { + String serverHost = System.getProperty("cas.server.host", "localhost:8443"); + this.serverUrl = "https://" + serverHost + "/cas"; + String serviceHost = System.getProperty("cas.service.host", "localhost:8443"); + this.serviceUrl = "https://" + serviceHost + "/cas-sample"; + this.login = new LoginPage(this.driver, this.serverUrl); + this.home = new HomePage(this.driver, this.serviceUrl); + this.secure = new SecurePage(this.driver, this.serviceUrl); + this.extremelySecure = new ExtremelySecurePage(this.driver, this.serviceUrl); + this.proxyTicketSample = new ProxyTicketSamplePage(this.driver, this.serviceUrl); + this.localLogout = new LocalLogoutPage(this.driver, this.serviceUrl); + this.accessDenied = new AccessDeniedPage(this.driver); + } + + @After + public void tearDown() { + this.driver.close(); + } + + @Test + public void homePageWhenUnauthenticatedUserThenSucceeds() { + this.home.to().assertAt(); + } + + @Test + public void extremelySecurePageWhenUnauthenticatedThenRequiresLogin() { + this.extremelySecure.to(); + this.login.assertAt(); + } + + @Test + public void authenticateWhenInvalidTicketThenFails() { + this.driver.get(this.serviceUrl + "/login/cas?ticket=invalid"); + assertThat(this.driver.findElement(By.tagName("h2")).getText()) + .isEqualTo("Login to CAS failed!"); + } + + @Test + public void securePageWhenUnauthenticatedThenRequiresLogin() { + this.secure.to(); + this.login.assertAt(); + } + + @Test + public void securePageWhenRoleUserThenDisplays() { + this.login.to().login("scott"); + this.secure.to().assertAt(); + } + + @Test + public void proxyTicketSamplePageWhenRoleUserThenDisplays() { + this.login.to().login("scott"); + this.proxyTicketSample.to().assertAt(); + } + + @Test + public void extremelySecurePageWhenRoleUserThenDenies() { + this.login.to().login("scott"); + this.extremelySecure.to(); + this.accessDenied.assertAt(); + } + + @Test + public void localLogoutLinkWhenClickedThenRedirectsToLocalLogoutPage() { + this.login.to().login("scott"); + this.secure.to().logout(); + this.localLogout.assertAt(); + } + + @Test + public void casLogoutWhenClickedThenPerformsCompleteLogout() { + this.login.to().login("scott"); + this.driver.get(this.serverUrl + "/logout"); + this.secure.to(); + this.login.assertAt(); + } + + @Test + public void extremelySecureWhenRoleSupervisorThenDisplays() { + this.login.to().login("rod"); + this.extremelySecure.to().assertAt(); + } + + @Test + public void casLogoutWhenClickedThenExtremelySecurePageRequiresLogin() { + this.login.to().login("scott"); + this.driver.get(this.serverUrl + "/logout"); + this.extremelySecure.to(); + this.login.assertAt(); + } + + @Test + public void casLogoutWhenVisitedThenLogsOutSample() { + this.secure.to(); + this.login.assertAt().login("rod"); + this.secure.assertAt(); + this.driver.get(this.serverUrl + "/logout"); + this.secure.to(); + this.login.assertAt(); + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/JettyCasService.groovy b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/JettyCasService.java similarity index 53% rename from samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/JettyCasService.groovy rename to samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/JettyCasService.java index 8be5860fb2..1491beb6f2 100644 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/JettyCasService.groovy +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/JettyCasService.java @@ -13,41 +13,46 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.security.samples.cas +package org.springframework.security.samples.cas; -import org.eclipse.jetty.http.HttpVersion -import org.eclipse.jetty.server.HttpConfiguration -import org.eclipse.jetty.server.HttpConnectionFactory -import org.eclipse.jetty.server.SecureRequestCustomizer -import org.eclipse.jetty.server.ServerConnector -import org.eclipse.jetty.server.SslConnectionFactory +import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.ssl.SslContextFactory; - -import javax.servlet.ServletException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import org.eclipse.jetty.server.Request -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.server.handler.AbstractHandler import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl; import org.jasig.cas.client.validation.Cas20ProxyTicketValidator; +import org.jasig.cas.client.validation.TicketValidationException; + +import org.springframework.util.StringUtils; /** * A CAS Service that allows a PGT to be obtained. This is useful for testing use of proxy tickets. * * @author Rob Winch */ -class JettyCasService extends Server { - private Cas20ProxyTicketValidator validator - private int port = availablePort() +public class JettyCasService extends Server { + private Cas20ProxyTicketValidator validator; + private int port = availablePort(); /** * The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter * equal to {@link #serviceUrl()}. */ - String pgt + String pgt; /** * Start the CAS Service which will be available at {@link #serviceUrl()}. @@ -55,16 +60,15 @@ class JettyCasService extends Server { * @param casServerUrl * @return */ - def init(String casServerUrl) { - println "Initializing to " + casServerUrl - ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl() - validator = new Cas20ProxyTicketValidator(casServerUrl) - validator.setAcceptAnyProxy(true) - validator.setProxyGrantingTicketStorage(storage) - validator.setProxyCallbackUrl(absoluteUrl('callback')) - - String password = System.getProperty('javax.net.ssl.trustStorePassword','password') + JettyCasService init(String casServerUrl) { + System.out.println("Initializing to " + casServerUrl); + ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl(); + this.validator = new Cas20ProxyTicketValidator(casServerUrl); + this.validator.setAcceptAnyProxy(true); + this.validator.setProxyGrantingTicketStorage(storage); + this.validator.setProxyCallbackUrl(absoluteUrl("callback")); + String password = System.getProperty("javax.net.ssl.trustStorePassword", "password"); SslContextFactory sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath(getTrustStore()); @@ -83,30 +87,39 @@ class JettyCasService extends Server { https_config.addCustomizer(src); ServerConnector https = new ServerConnector(this, - new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()), + new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(https_config)); https.setPort(port); https.setIdleTimeout(500000); - addConnector(https) + addConnector(https); setHandler(new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - def st = request.getParameter('ticket') - if(st) { - JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl()) + String st = request.getParameter("ticket"); + if (StringUtils.hasText(st)) { + try { + JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl()); + } catch (TicketValidationException e) { + throw new IllegalArgumentException(e); + } } - def pgt = request.getParameter('pgtId') - if(pgt) { - JettyCasService.this.pgt = pgt + String pgt = request.getParameter("pgtId"); + if (StringUtils.hasText(pgt)) { + JettyCasService.this.pgt = pgt; } response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); } - }) - start() - this + }); + + try { + start(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + return this; } /** @@ -114,7 +127,7 @@ class JettyCasService extends Server { * @return */ String serviceUrl() { - absoluteUrl('service') + return absoluteUrl("service"); } /** @@ -123,24 +136,27 @@ class JettyCasService extends Server { * @return */ private String absoluteUrl(String relativeUrl) { - "https://localhost:${port}/${relativeUrl}" + return "https://localhost:" + port + "/" + relativeUrl; } private static String getTrustStore() { - String trustStoreLocation = System.getProperty('javax.net.ssl.trustStore') - if(trustStoreLocation == null || !new File(trustStoreLocation).isFile()) { - throw new IllegalStateException('Could not find the trust store at path "'+trustStoreLocation+'". Specify the location using the javax.net.ssl.trustStore system property.') + String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); + if (trustStoreLocation == null || !new File(trustStoreLocation).isFile()) { + throw new IllegalStateException("Could not find the trust store at path \"" + trustStoreLocation + + "\". Specify the location using the javax.net.ssl.trustStore system property."); } - trustStoreLocation + return trustStoreLocation; } + /** * Obtains a random available port (i.e. one that is not in use) * @return */ private static int availablePort() { - ServerSocket server = new ServerSocket(0) - int port = server.localPort - server.close() - port + try (ServerSocket server = new ServerSocket(0)) { + return server.getLocalPort(); + } catch (IOException e) { + throw new IllegalStateException(e); + } } } diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/AccessDeniedPage.groovy b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/AccessDeniedPage.java similarity index 51% rename from samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/AccessDeniedPage.groovy rename to samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/AccessDeniedPage.java index 686762673d..e1426a360f 100644 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/AccessDeniedPage.groovy +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/AccessDeniedPage.java @@ -15,13 +15,38 @@ */ package org.springframework.security.samples.cas.pages; -import geb.* +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import static org.assertj.core.api.Assertions.assertThat; /** * Represents the access denied page * * @author Rob Winch + * @author Josh Cummings */ -class AccessDeniedPage extends Page { - static at = { $("*",text: iContains(~/.*?403.*/)) } +public class AccessDeniedPage { + + private final Content content; + + public AccessDeniedPage(WebDriver driver) { + this.content = PageFactory.initElements(driver, Content.class); + } + + public AccessDeniedPage assertAt() { + assertThat(this.content.header()).contains("403 - Access Denied"); + return this; + } + + public static class Content { + @FindBy(tagName="h1") + WebElement header; + + public String header() { + return this.header.getText(); + } + } } diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ExtremelySecurePage.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ExtremelySecurePage.java new file mode 100644 index 0000000000..7ad5e5d0ee --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ExtremelySecurePage.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Represents the extremely secure page of the CAS Sample application. + * + * @author Rob Winch + * @author Josh Cummings + */ +public class ExtremelySecurePage extends Page { + private final Content content; + + public ExtremelySecurePage(WebDriver driver, String baseUrl) { + super(driver, baseUrl + "/secure/extreme"); + this.content = PageFactory.initElements(driver, Content.class); + } + + @Override + public ExtremelySecurePage assertAt() { + assertThat(this.content.getText()).isEqualTo("VERY Secure Page"); + return this; + } + + public static class Content { + @FindBy(tagName="h1") + WebElement header; + + public String getText() { + return this.header.getText(); + } + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/HomePage.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/HomePage.java new file mode 100644 index 0000000000..25cf8dbded --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/HomePage.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Represents the Home page of the CAS sample application + * + * @author Rob Winch + * @author Josh Cummings + */ +public class HomePage extends Page { + private final Content content; + + public HomePage(WebDriver driver, String baseUrl) { + super(driver, baseUrl); + this.content = PageFactory.initElements(driver, Content.class); + } + + @Override + public HomePage assertAt() { + assertThat(this.content.header()).isEqualTo("Home Page"); + return this; + } + + public static class Content { + @FindBy(tagName="h1") + WebElement header; + + public String header() { + return this.header.getText(); + } + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LocalLogoutPage.groovy b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LocalLogoutPage.java similarity index 83% rename from samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LocalLogoutPage.groovy rename to samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LocalLogoutPage.java index 1376d6aeed..075a792080 100644 --- a/samples/xml/cas/cassample/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LocalLogoutPage.groovy +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LocalLogoutPage.java @@ -15,8 +15,7 @@ */ package org.springframework.security.samples.cas.pages; -import geb.* - +import org.openqa.selenium.WebDriver; /** * This represents the local logout page. This page is where the user is logged out of the CAS Sample application, but @@ -25,11 +24,10 @@ import geb.* * single logout on the other services. * * @author Rob Winch + * @author Josh Cummings */ -class LocalLogoutPage extends Page { - static url = 'cas-logout.jsp' - static at = { assert driver.currentUrl.endsWith(url); true } - static content = { - casServerLogout { $('a',text: 'Logout of CAS') } +public class LocalLogoutPage extends Page { + public LocalLogoutPage(WebDriver driver, String baseUrl) { + super(driver, baseUrl + "/cas-logout.jsp"); } } diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LoginPage.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LoginPage.java new file mode 100644 index 0000000000..44c509905c --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/LoginPage.java @@ -0,0 +1,65 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +/** + * The CAS login page. + * + * @author Rob Winch + * @author Josh Cummings + */ +public class LoginPage extends Page { + private final Content content; + + public LoginPage(WebDriver driver, String baseUrl) { + super(driver, baseUrl + "/login"); + this.content = PageFactory.initElements(driver, Content.class); + } + + public void login(String user) { + login(user, user); + } + + public void login(String user, String password) { + this.content.username(user).password(password).submit(); + } + + public static class Content { + private WebElement username; + private WebElement password; + @FindBy(css = "input[type=submit]") + private WebElement submit; + + public Content username(String username) { + this.username.sendKeys(username); + return this; + } + + public Content password(String password) { + this.password.sendKeys(password); + return this; + } + + public void submit() { + this.submit.click(); + } + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/Page.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/Page.java new file mode 100644 index 0000000000..1e7d4e40c3 --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/Page.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.samples.cas.pages; + +import java.util.function.Function; + +import org.openqa.selenium.WebDriver; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Josh Cummings + */ +public abstract class Page> { + private final WebDriver driver; + private final String url; + + protected Page(WebDriver driver, String url) { + this.driver = driver; + this.url = url; + } + + public T assertAt() { + assertThat(this.driver.getCurrentUrl()).startsWith(this.url); + return (T) this; + } + + public T to() { + this.driver.get(this.url); + return (T) this; + } + + public T to(Function urlPostProcessor) { + this.driver.get(urlPostProcessor.apply(this.url)); + return (T) this; + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.java new file mode 100644 index 0000000000..4f4bd78fa3 --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Represents the proxy ticket sample page within the CAS Sample application. + * + * @author Rob Winch + * @author Josh Cummings + */ +public class ProxyTicketSamplePage extends Page { + private final Content content; + + public ProxyTicketSamplePage(WebDriver driver, String baseUrl) { + super(driver, baseUrl + "/secure/ptSample"); + this.content = PageFactory.initElements(driver, Content.class); + } + + @Override + public ProxyTicketSamplePage assertAt() { + assertThat(this.content.getText()).isEqualTo("Secure Page using a Proxy Ticket"); + return this; + } + + public static class Content { + @FindBy(tagName="h1") + WebElement header; + + public String getText() { + return this.header.getText(); + } + } +} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/SecurePage.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/SecurePage.java new file mode 100644 index 0000000000..7b5afe0093 --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/SecurePage.java @@ -0,0 +1,66 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Represents the secure page within the CAS Sample application. + * + * @author Rob Winch + * @author Josh Cummings + */ +public class SecurePage extends Page { + private final Content content; + + public SecurePage(WebDriver driver, String baseUrl) { + super(driver, baseUrl + "/secure"); + this.content = PageFactory.initElements(driver, Content.class); + } + + @Override + public SecurePage assertAt() { + assertThat(this.content.header()).isEqualTo("Secure Page"); + return this; + } + + public SecurePage logout() { + this.content.logout(); + return this; + } + + public static class Content { + @FindBy(tagName="h1") + WebElement header; + + WebElement logout; + + public String header() { + return this.header.getText(); + } + + public void logout() { + this.logout.click(); + } + } + + // had nav +} diff --git a/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/UnauthorizedPage.java b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/UnauthorizedPage.java new file mode 100644 index 0000000000..4b8e099ab1 --- /dev/null +++ b/samples/xml/cas/cassample/src/integration-test/java/org/springframework/security/samples/cas/pages/UnauthorizedPage.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.samples.cas.pages; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Represents the unauthorized page + * + * @author Josh Cummings + */ +public class UnauthorizedPage { + + private final Content content; + + public UnauthorizedPage(WebDriver driver) { + this.content = PageFactory.initElements(driver, Content.class); + } + + public UnauthorizedPage assertAt() { + assertThat(this.content.header()).contains("401 - Unauthorized"); + return this; + } + + public static class Content { + @FindBy(tagName="h1") + WebElement header; + + public String header() { + return this.header.getText(); + } + } +} diff --git a/samples/xml/cas/cassample/src/main/webapp/401.jsp b/samples/xml/cas/cassample/src/main/webapp/401.jsp new file mode 100644 index 0000000000..db1a4a1f3e --- /dev/null +++ b/samples/xml/cas/cassample/src/main/webapp/401.jsp @@ -0,0 +1,8 @@ + + +401 - Unauthorized + + +

401 - Unauthorized

+ + diff --git a/samples/xml/cas/cassample/src/main/webapp/WEB-INF/web.xml b/samples/xml/cas/cassample/src/main/webapp/WEB-INF/web.xml index fa78554d48..0cf03709fc 100644 --- a/samples/xml/cas/cassample/src/main/webapp/WEB-INF/web.xml +++ b/samples/xml/cas/cassample/src/main/webapp/WEB-INF/web.xml @@ -78,6 +78,10 @@ ptSampleServlet /secure/ptSample + + 401 + /401.jsp + 403 /403.jsp diff --git a/samples/xml/cas/cassample/src/main/webapp/cas-logout.jsp b/samples/xml/cas/cassample/src/main/webapp/cas-logout.jsp index 730e3b366c..5658e5d38b 100644 --- a/samples/xml/cas/cassample/src/main/webapp/cas-logout.jsp +++ b/samples/xml/cas/cassample/src/main/webapp/cas-logout.jsp @@ -9,7 +9,7 @@

You have logged out of this application, but may still have an active single-sign on session with CAS.

-

Logout of CAS

+

Logout of CAS

- \ No newline at end of file + diff --git a/samples/xml/cas/cassample/src/main/webapp/index.jsp b/samples/xml/cas/cassample/src/main/webapp/index.jsp index 546d5996d7..e7d6dc7802 100644 --- a/samples/xml/cas/cassample/src/main/webapp/index.jsp +++ b/samples/xml/cas/cassample/src/main/webapp/index.jsp @@ -5,8 +5,8 @@

Your principal object is....: <%= request.getUserPrincipal() %>

-

Secure page

-

Proxy Ticket Sample page

-

Extremely secure page

+

Secure page

+

Proxy Ticket Sample page

+

Extremely secure page

- \ No newline at end of file + diff --git a/samples/xml/cas/cassample/src/main/webapp/secure/extreme/index.jsp b/samples/xml/cas/cassample/src/main/webapp/secure/extreme/index.jsp index 83cf74ac95..376cbe5fd9 100644 --- a/samples/xml/cas/cassample/src/main/webapp/secure/extreme/index.jsp +++ b/samples/xml/cas/cassample/src/main/webapp/secure/extreme/index.jsp @@ -3,10 +3,10 @@

VERY Secure Page

This is a protected page. You can only see me if you are a supervisor. -

Home -

Secure page

-

Proxy Ticket Sample page

-

Logout -< +

Home +

Secure page

+

Proxy Ticket Sample page

+

Logout + - \ No newline at end of file + diff --git a/samples/xml/cas/cassample/src/main/webapp/secure/index.jsp b/samples/xml/cas/cassample/src/main/webapp/secure/index.jsp index 4504f2c14d..ea4c7240d1 100644 --- a/samples/xml/cas/cassample/src/main/webapp/secure/index.jsp +++ b/samples/xml/cas/cassample/src/main/webapp/secure/index.jsp @@ -8,8 +8,8 @@ or if you've authenticated this session.

You are a supervisor! You can therefore see the extremely secure page.

<% } %> -

Home -

Proxy Ticket Sample page

-

Logout +

Home +

Proxy Ticket Sample page

+

Logout - \ No newline at end of file +