parent
							
								
									cb695ae60f
								
							
						
					
					
						commit
						7c4d56319f
					
				|  | @ -3,12 +3,6 @@ apply plugin: 'io.spring.convention.spring-sample-war' | ||||||
| def keystore = "$rootDir/samples/certificates/server.jks" | def keystore = "$rootDir/samples/certificates/server.jks" | ||||||
| def password = 'password' | def password = 'password' | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| sourceSets { |  | ||||||
| 	test.resources.exclude 'GebConfig.groovy' |  | ||||||
| 	integrationTest.groovy.srcDir file('src/integration-test/groovy') |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| dependencies { | dependencies { | ||||||
| 	compile project(':spring-security-cas') | 	compile project(':spring-security-cas') | ||||||
| 	compile project(':spring-security-core') | 	compile project(':spring-security-core') | ||||||
|  | @ -24,10 +18,7 @@ dependencies { | ||||||
| 	runtime 'org.springframework:spring-context-support' | 	runtime 'org.springframework:spring-context-support' | ||||||
| 
 | 
 | ||||||
| 	integrationTestCompile project(':spring-security-cas') | 	integrationTestCompile project(':spring-security-cas') | ||||||
| 	integrationTestCompile gebDependencies |  | ||||||
| 	integrationTestCompile seleniumDependencies | 	integrationTestCompile seleniumDependencies | ||||||
| 	integrationTestCompile spockDependencies |  | ||||||
| 	integrationTestCompile 'org.codehaus.groovy:groovy' |  | ||||||
| 	integrationTestCompile 'org.eclipse.jetty:jetty-server' | 	integrationTestCompile 'org.eclipse.jetty:jetty-server' | ||||||
| 	integrationTestCompile 'org.eclipse.jetty:jetty-servlet' | 	integrationTestCompile 'org.eclipse.jetty:jetty-servlet' | ||||||
| 	integrationTestCompile 'org.slf4j:jcl-over-slf4j' | 	integrationTestCompile 'org.slf4j:jcl-over-slf4j' | ||||||
|  | @ -40,8 +31,6 @@ integrationTest { | ||||||
| 		def casServerHost = 'localhost:' + casServer().gretty.httpsPort | 		def casServerHost = 'localhost:' + casServer().gretty.httpsPort | ||||||
| 		systemProperties['cas.server.host'] = casServerHost | 		systemProperties['cas.server.host'] = casServerHost | ||||||
| 		systemProperties['cas.service.host'] = casServiceHost | 		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['jar.path'] = jar.archivePath | ||||||
| 		systemProperties['javax.net.ssl.trustStore'] = keystore | 		systemProperties['javax.net.ssl.trustStore'] = keystore | ||||||
| 		systemProperties['javax.net.ssl.trustStorePassword'] = password | 		systemProperties['javax.net.ssl.trustStorePassword'] = password | ||||||
|  |  | ||||||
|  | @ -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() |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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('<h1>Secure Page</h1>') |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	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('<h1>Secure Page using a Proxy Ticket</h1>') |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	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('<h1>VERY Secure Page</h1>') |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	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('<h1>VERY Secure Page</h1>') |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	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 |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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 |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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") } |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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 } |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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') } |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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" |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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 } |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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 } |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -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<String, String> 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); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -13,41 +13,46 @@ | ||||||
|  * See the License for the specific language governing permissions and |  * See the License for the specific language governing permissions and | ||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| package org.springframework.security.samples.cas | package org.springframework.security.samples.cas; | ||||||
| 
 | 
 | ||||||
| import org.eclipse.jetty.http.HttpVersion | import java.io.File; | ||||||
| import org.eclipse.jetty.server.HttpConfiguration | import java.io.IOException; | ||||||
| import org.eclipse.jetty.server.HttpConnectionFactory | import java.net.ServerSocket; | ||||||
| import org.eclipse.jetty.server.SecureRequestCustomizer | import javax.servlet.ServletException; | ||||||
| import org.eclipse.jetty.server.ServerConnector | import javax.servlet.http.HttpServletRequest; | ||||||
| import org.eclipse.jetty.server.SslConnectionFactory | 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 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.ProxyGrantingTicketStorage; | ||||||
| import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl; | import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl; | ||||||
| import org.jasig.cas.client.validation.Cas20ProxyTicketValidator; | 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. |  * A CAS Service that allows a PGT to be obtained. This is useful for testing use of proxy tickets. | ||||||
|  * |  * | ||||||
|  * @author Rob Winch |  * @author Rob Winch | ||||||
|  */ |  */ | ||||||
| class JettyCasService extends Server { | public class JettyCasService extends Server { | ||||||
| 	private Cas20ProxyTicketValidator validator | 	private Cas20ProxyTicketValidator validator; | ||||||
| 	private int port = availablePort() | 	private int port = availablePort(); | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter | 	 * The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter | ||||||
| 	 * equal to {@link #serviceUrl()}. | 	 * equal to {@link #serviceUrl()}. | ||||||
| 	 */ | 	 */ | ||||||
| 	String pgt | 	String pgt; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Start the CAS Service which will be available at {@link #serviceUrl()}. | 	 * Start the CAS Service which will be available at {@link #serviceUrl()}. | ||||||
|  | @ -55,16 +60,15 @@ class JettyCasService extends Server { | ||||||
| 	 * @param casServerUrl | 	 * @param casServerUrl | ||||||
| 	 * @return | 	 * @return | ||||||
| 	 */ | 	 */ | ||||||
| 	def init(String casServerUrl) { | 	JettyCasService init(String casServerUrl) { | ||||||
| 		println "Initializing to " + casServerUrl | 		System.out.println("Initializing to " + casServerUrl); | ||||||
| 		ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl() | 		ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl(); | ||||||
| 		validator = new Cas20ProxyTicketValidator(casServerUrl) | 		this.validator = new Cas20ProxyTicketValidator(casServerUrl); | ||||||
| 		validator.setAcceptAnyProxy(true) | 		this.validator.setAcceptAnyProxy(true); | ||||||
| 		validator.setProxyGrantingTicketStorage(storage) | 		this.validator.setProxyGrantingTicketStorage(storage); | ||||||
| 		validator.setProxyCallbackUrl(absoluteUrl('callback')) | 		this.validator.setProxyCallbackUrl(absoluteUrl("callback")); | ||||||
| 
 |  | ||||||
| 		String password = System.getProperty('javax.net.ssl.trustStorePassword','password') |  | ||||||
| 
 | 
 | ||||||
|  | 		String password = System.getProperty("javax.net.ssl.trustStorePassword", "password"); | ||||||
| 
 | 
 | ||||||
| 		SslContextFactory sslContextFactory = new SslContextFactory.Server(); | 		SslContextFactory sslContextFactory = new SslContextFactory.Server(); | ||||||
| 		sslContextFactory.setKeyStorePath(getTrustStore()); | 		sslContextFactory.setKeyStorePath(getTrustStore()); | ||||||
|  | @ -83,30 +87,39 @@ class JettyCasService extends Server { | ||||||
| 		https_config.addCustomizer(src); | 		https_config.addCustomizer(src); | ||||||
| 
 | 
 | ||||||
| 		ServerConnector https = new ServerConnector(this, | 		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)); | 			new HttpConnectionFactory(https_config)); | ||||||
| 		https.setPort(port); | 		https.setPort(port); | ||||||
| 		https.setIdleTimeout(500000); | 		https.setIdleTimeout(500000); | ||||||
| 
 | 
 | ||||||
| 		addConnector(https) | 		addConnector(https); | ||||||
| 		setHandler(new AbstractHandler() { | 		setHandler(new AbstractHandler() { | ||||||
| 			public void handle(String target, Request baseRequest, | 			public void handle(String target, Request baseRequest, | ||||||
| 					HttpServletRequest request, HttpServletResponse response) | 					HttpServletRequest request, HttpServletResponse response) | ||||||
| 			throws IOException, ServletException { | 			throws IOException, ServletException { | ||||||
| 				def st = request.getParameter('ticket') | 				String st = request.getParameter("ticket"); | ||||||
| 				if(st) { | 				if (StringUtils.hasText(st)) { | ||||||
| 					JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl()) | 					try { | ||||||
|  | 						JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl()); | ||||||
|  | 					} catch (TicketValidationException e) { | ||||||
|  | 						throw new IllegalArgumentException(e); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 				def pgt = request.getParameter('pgtId') | 				String pgt = request.getParameter("pgtId"); | ||||||
| 				if(pgt) { | 				if (StringUtils.hasText(pgt)) { | ||||||
| 				  JettyCasService.this.pgt = pgt | 					JettyCasService.this.pgt = pgt; | ||||||
| 				} | 				} | ||||||
| 				response.setStatus(HttpServletResponse.SC_OK); | 				response.setStatus(HttpServletResponse.SC_OK); | ||||||
| 				baseRequest.setHandled(true); | 				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 | 	 * @return | ||||||
| 	 */ | 	 */ | ||||||
| 	String serviceUrl() { | 	String serviceUrl() { | ||||||
| 		absoluteUrl('service') | 		return absoluteUrl("service"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -123,24 +136,27 @@ class JettyCasService extends Server { | ||||||
| 	 * @return | 	 * @return | ||||||
| 	 */ | 	 */ | ||||||
| 	private String absoluteUrl(String relativeUrl) { | 	private String absoluteUrl(String relativeUrl) { | ||||||
| 		"https://localhost:${port}/${relativeUrl}" | 		return "https://localhost:" + port + "/" + relativeUrl; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static String getTrustStore() { | 	private static String getTrustStore() { | ||||||
| 		String trustStoreLocation = System.getProperty('javax.net.ssl.trustStore') | 		String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); | ||||||
| 		if(trustStoreLocation == null || !new File(trustStoreLocation).isFile()) { | 		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.') | 			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) | 	 * Obtains a random available port (i.e. one that is not in use) | ||||||
| 	 * @return | 	 * @return | ||||||
| 	 */ | 	 */ | ||||||
| 	private static int availablePort() { | 	private static int availablePort() { | ||||||
| 		ServerSocket server = new ServerSocket(0) | 		try (ServerSocket server = new ServerSocket(0)) { | ||||||
| 		int port = server.localPort | 			return server.getLocalPort(); | ||||||
| 		server.close() | 		} catch (IOException e) { | ||||||
| 		port | 			throw new IllegalStateException(e); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -15,13 +15,38 @@ | ||||||
|  */ |  */ | ||||||
| package org.springframework.security.samples.cas.pages; | 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 |  * Represents the access denied page | ||||||
|  * |  * | ||||||
|  * @author Rob Winch |  * @author Rob Winch | ||||||
|  |  * @author Josh Cummings | ||||||
|  */ |  */ | ||||||
| class AccessDeniedPage extends Page { | public class AccessDeniedPage { | ||||||
| 	static at = { $("*",text: iContains(~/.*?403.*/)) } | 
 | ||||||
|  | 	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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | @ -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<ExtremelySecurePage> { | ||||||
|  | 	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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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<HomePage> { | ||||||
|  | 	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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -15,8 +15,7 @@ | ||||||
|  */ |  */ | ||||||
| package org.springframework.security.samples.cas.pages; | 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 |  * 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. |  * single logout on the other services. | ||||||
|  * |  * | ||||||
|  * @author Rob Winch |  * @author Rob Winch | ||||||
|  |  * @author Josh Cummings | ||||||
|  */ |  */ | ||||||
| class LocalLogoutPage extends Page { | public class LocalLogoutPage extends Page<LocalLogoutPage> { | ||||||
| 	static url = 'cas-logout.jsp' | 	public LocalLogoutPage(WebDriver driver, String baseUrl) { | ||||||
| 	static at = { assert driver.currentUrl.endsWith(url); true } | 		super(driver, baseUrl + "/cas-logout.jsp"); | ||||||
| 	static content = { |  | ||||||
| 		casServerLogout { $('a',text: 'Logout of CAS') } |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -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<LoginPage> { | ||||||
|  | 	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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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<T extends Page<T>> { | ||||||
|  | 	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<String, String> urlPostProcessor) { | ||||||
|  | 		this.driver.get(urlPostProcessor.apply(this.url)); | ||||||
|  | 		return (T) this; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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<ProxyTicketSamplePage> { | ||||||
|  | 	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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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<SecurePage> { | ||||||
|  | 	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 | ||||||
|  | } | ||||||
|  | @ -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(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  | <title>401 - Unauthorized</title> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | <h1>401 - Unauthorized</h1> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -78,6 +78,10 @@ | ||||||
| 		<servlet-name>ptSampleServlet</servlet-name> | 		<servlet-name>ptSampleServlet</servlet-name> | ||||||
| 		<url-pattern>/secure/ptSample</url-pattern> | 		<url-pattern>/secure/ptSample</url-pattern> | ||||||
| 	</servlet-mapping> | 	</servlet-mapping> | ||||||
|  | 	<error-page> | ||||||
|  | 		<error-code>401</error-code> | ||||||
|  | 		<location>/401.jsp</location> | ||||||
|  | 	</error-page> | ||||||
| 	<error-page> | 	<error-page> | ||||||
| 		<error-code>403</error-code> | 		<error-code>403</error-code> | ||||||
| 		<location>/403.jsp</location> | 		<location>/403.jsp</location> | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
| 
 | 
 | ||||||
| <p>You have logged out of this application, but may still have an active single-sign on session with CAS.</p> | <p>You have logged out of this application, but may still have an active single-sign on session with CAS.</p> | ||||||
| 
 | 
 | ||||||
| <p><a href="logout/cas">Logout of CAS</a></p> | <p><a id="casLogout" href="logout/cas">Logout of CAS</a></p> | ||||||
| 
 | 
 | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -5,8 +5,8 @@ | ||||||
| 
 | 
 | ||||||
| <p>Your principal object is....: <%= request.getUserPrincipal() %></p> | <p>Your principal object is....: <%= request.getUserPrincipal() %></p> | ||||||
| 
 | 
 | ||||||
| <p><a href="secure/index.jsp">Secure page</a></p> | <p><a id="secure" href="secure/index.jsp">Secure page</a></p> | ||||||
| <p><a href="secure/ptSample">Proxy Ticket Sample page</a></p> | <p><a id="proxy" href="secure/ptSample">Proxy Ticket Sample page</a></p> | ||||||
| <p><a href="secure/extreme/index.jsp">Extremely secure page</a></p> | <p><a id="extremelySecure" href="secure/extreme/index.jsp">Extremely secure page</a></p> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -3,10 +3,10 @@ | ||||||
| <h1>VERY Secure Page</h1> | <h1>VERY Secure Page</h1> | ||||||
| This is a protected page. You can only see me if you are a supervisor. | This is a protected page. You can only see me if you are a supervisor. | ||||||
| 
 | 
 | ||||||
| <p><a href="../../">Home</a> | <p><a id="home" href="../../">Home</a> | ||||||
| <p><a href="../../secure/index.jsp">Secure page</a></p> | <p><a id="secure" href="../../secure/index.jsp">Secure page</a></p> | ||||||
| <p><a href="../../secure/ptSample">Proxy Ticket Sample page</a></p> | <p><a id="ptSample" href="../../secure/ptSample">Proxy Ticket Sample page</a></p> | ||||||
| <p><a href="../../logout">Logout</a> | <p><a id="logout" href="../../logout">Logout</a> | ||||||
| < | 
 | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ or if you've authenticated this session.</p> | ||||||
|     <p>You are a supervisor! You can therefore see the <a href="extreme/index.jsp">extremely secure page</a>.</p> |     <p>You are a supervisor! You can therefore see the <a href="extreme/index.jsp">extremely secure page</a>.</p> | ||||||
| <% } %> | <% } %> | ||||||
| 
 | 
 | ||||||
| <p><a href="../">Home</a> | <p><a id="home" href="../">Home</a> | ||||||
| <p><a href="ptSample">Proxy Ticket Sample page</a></p> | <p><a id="proxy" href="ptSample">Proxy Ticket Sample page</a></p> | ||||||
| <p><a href="../logout">Logout</a> | <p><a id="logout" href="../logout">Logout</a> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue