mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-03-24 17:08:50 +00:00
cassample groovy->java
Issue gh-4939
This commit is contained in:
parent
cb695ae60f
commit
7c4d56319f
@ -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
|
||||
|
@ -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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
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<LocalLogoutPage> {
|
||||
public LocalLogoutPage(WebDriver driver, String baseUrl) {
|
||||
super(driver, baseUrl + "/cas-logout.jsp");
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
8
samples/xml/cas/cassample/src/main/webapp/401.jsp
Normal file
8
samples/xml/cas/cassample/src/main/webapp/401.jsp
Normal file
@ -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>
|
||||
<url-pattern>/secure/ptSample</url-pattern>
|
||||
</servlet-mapping>
|
||||
<error-page>
|
||||
<error-code>401</error-code>
|
||||
<location>/401.jsp</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>403</error-code>
|
||||
<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><a href="logout/cas">Logout of CAS</a></p>
|
||||
<p><a id="casLogout" href="logout/cas">Logout of CAS</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
<p>Your principal object is....: <%= request.getUserPrincipal() %></p>
|
||||
|
||||
<p><a href="secure/index.jsp">Secure page</a></p>
|
||||
<p><a href="secure/ptSample">Proxy Ticket Sample page</a></p>
|
||||
<p><a href="secure/extreme/index.jsp">Extremely secure page</a></p>
|
||||
<p><a id="secure" href="secure/index.jsp">Secure page</a></p>
|
||||
<p><a id="proxy" href="secure/ptSample">Proxy Ticket Sample page</a></p>
|
||||
<p><a id="extremelySecure" href="secure/extreme/index.jsp">Extremely secure page</a></p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -3,10 +3,10 @@
|
||||
<h1>VERY Secure Page</h1>
|
||||
This is a protected page. You can only see me if you are a supervisor.
|
||||
|
||||
<p><a href="../../">Home</a>
|
||||
<p><a href="../../secure/index.jsp">Secure page</a></p>
|
||||
<p><a href="../../secure/ptSample">Proxy Ticket Sample page</a></p>
|
||||
<p><a href="../../logout">Logout</a>
|
||||
<
|
||||
<p><a id="home" href="../../">Home</a>
|
||||
<p><a id="secure" href="../../secure/index.jsp">Secure page</a></p>
|
||||
<p><a id="ptSample" href="../../secure/ptSample">Proxy Ticket Sample page</a></p>
|
||||
<p><a id="logout" href="../../logout">Logout</a>
|
||||
|
||||
</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><a href="../">Home</a>
|
||||
<p><a href="ptSample">Proxy Ticket Sample page</a></p>
|
||||
<p><a href="../logout">Logout</a>
|
||||
<p><a id="home" href="../">Home</a>
|
||||
<p><a id="proxy" href="ptSample">Proxy Ticket Sample page</a></p>
|
||||
<p><a id="logout" href="../logout">Logout</a>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user