SEC-965: Added integration tests for CAS Sample Application
This commit is contained in:
parent
f1c064b3b9
commit
761d5af6ec
|
@ -2,22 +2,35 @@
|
|||
|
||||
apply plugin: 'war'
|
||||
apply plugin: 'jetty'
|
||||
apply plugin: 'groovy'
|
||||
|
||||
def excludeModules = ['spring-security-acl', 'jsr250-api', 'ehcache', 'spring-jdbc', 'spring-tx']
|
||||
def excludeModules = ['spring-security-acl', 'jsr250-api', 'spring-jdbc', 'spring-tx']
|
||||
def jettyVersion = '7.1.6.v20100715'
|
||||
def keystore = "$rootDir/samples/certificates/server.jks"
|
||||
def password = 'password'
|
||||
|
||||
configurations {
|
||||
casServer
|
||||
}
|
||||
|
||||
configurations {
|
||||
excludeModules.each {name ->
|
||||
runtime.exclude module: name
|
||||
}
|
||||
|
||||
runtime.exclude group: 'org.aspectj'
|
||||
|
||||
integrationTestCompile.extendsFrom groovy
|
||||
}
|
||||
|
||||
sourceSets.integrationTest {
|
||||
groovy.srcDir file('src/integration-test/groovy')
|
||||
}
|
||||
|
||||
eclipseClasspath {
|
||||
plusConfigurations += configurations.integrationTestRuntime
|
||||
}
|
||||
|
||||
dependencies {
|
||||
groovy 'org.codehaus.groovy:groovy:1.7.7'
|
||||
|
||||
casServer "org.jasig.cas:cas-server-webapp:3.4.3.1@war"
|
||||
|
||||
runtime project(':spring-security-web'),
|
||||
|
@ -25,11 +38,16 @@ dependencies {
|
|||
project(':spring-security-config'),
|
||||
"org.slf4j:jcl-over-slf4j:$slf4jVersion",
|
||||
"ch.qos.logback:logback-classic:$logbackVersion"
|
||||
|
||||
integrationTestCompile project(':spring-security-cas'),
|
||||
'org.seleniumhq.selenium:selenium-htmlunit-driver:2.0a7',
|
||||
'org.spockframework:spock-core:0.4-groovy-1.7',
|
||||
'org.codehaus.geb:geb-spock:0.5.1',
|
||||
'commons-httpclient:commons-httpclient:3.1',
|
||||
"org.eclipse.jetty:jetty-server:$jettyVersion",
|
||||
"org.eclipse.jetty:jetty-servlet:$jettyVersion"
|
||||
}
|
||||
|
||||
|
||||
def keystore = "$rootDir/samples/certificates/server.jks"
|
||||
|
||||
[jettyRun, jettyRunWar]*.configure {
|
||||
contextPath = "/cas-sample"
|
||||
def httpConnector = new org.mortbay.jetty.nio.SelectChannelConnector();
|
||||
|
@ -38,33 +56,66 @@ def keystore = "$rootDir/samples/certificates/server.jks"
|
|||
def httpsConnector = new org.mortbay.jetty.security.SslSocketConnector();
|
||||
httpsConnector.port = 8443
|
||||
httpsConnector.keystore = httpsConnector.truststore = keystore
|
||||
httpsConnector.keyPassword = httpsConnector.trustPassword = 'password'
|
||||
httpsConnector.keyPassword = httpsConnector.trustPassword = password
|
||||
|
||||
connectors = [httpConnector, httpsConnector]
|
||||
doFirst() {
|
||||
System.setProperty('cas.server.host', casServer.httpsHost)
|
||||
System.setProperty('cas.service.host', jettyRunWar.httpsHost)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task casServer (type: org.gradle.api.plugins.jetty.JettyRunWar) {
|
||||
contextPath = "/cas"
|
||||
connectors = [new org.mortbay.jetty.security.SslSocketConnector()]
|
||||
connectors[0].port = 9443
|
||||
connectors[0].keystore = connectors[0].truststore = keystore
|
||||
connectors[0].keyPassword = connectors[0].trustPassword = 'password'
|
||||
connectors[0].keyPassword = connectors[0].trustPassword = password
|
||||
connectors[0].wantClientAuth = true
|
||||
connectors[0].needClientAuth = false
|
||||
webApp = configurations.casServer.resolve().toArray()[0]
|
||||
doFirst() {
|
||||
System.setProperty('javax.net.ssl.trustStore', keystore)
|
||||
System.setProperty('javax.net.ssl.trustStorePassword', 'password')
|
||||
System.setProperty('javax.net.ssl.trustStorePassword', password)
|
||||
}
|
||||
}
|
||||
|
||||
task cas (dependsOn: [jettyRunWar, casServer]) {
|
||||
}
|
||||
|
||||
integrationTest.dependsOn cas
|
||||
integrationTest.doFirst {
|
||||
systemProperties['cas.server.host'] = casServer.httpsHost
|
||||
systemProperties['cas.service.host'] = jettyRunWar.httpsHost
|
||||
systemProperties['jar.path'] = jar.archivePath
|
||||
systemProperties['javax.net.ssl.trustStore'] = keystore
|
||||
systemProperties['javax.net.ssl.trustStorePassword'] = password
|
||||
}
|
||||
|
||||
gradle.taskGraph.whenReady {graph ->
|
||||
if (graph.hasTask(cas)) {
|
||||
jettyRunWar.dependsOn(casServer)
|
||||
casServer.daemon = true
|
||||
}
|
||||
if(graph.hasTask(integrationTest)) {
|
||||
jettyRunWar.daemon = true
|
||||
jettyRunWar.httpConnector.port = availablePort()
|
||||
jettyRunWar.httpsConnector.port = jettyRunWar.httpConnector.confidentialPort = availablePort()
|
||||
casServer.httpsConnector.port = availablePort()
|
||||
}
|
||||
}
|
||||
[casServer,jettyRunWar]*.metaClass*.getHttpsConnector {->
|
||||
delegate.connectors.find { it instanceof org.mortbay.jetty.security.SslSocketConnector }
|
||||
}
|
||||
[casServer,jettyRunWar]*.metaClass*.getHttpsHost {->
|
||||
"localhost:"+delegate.httpsConnector.port
|
||||
}
|
||||
jettyRunWar.metaClass.getHttpConnector {->
|
||||
delegate.connectors.find { it instanceof org.mortbay.jetty.nio.SelectChannelConnector }
|
||||
}
|
||||
def availablePort() {
|
||||
ServerSocket server = new ServerSocket(0)
|
||||
int port = server.localPort
|
||||
server.close()
|
||||
port
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.cas;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import geb.spock.*
|
||||
|
||||
|
||||
/**
|
||||
* Base test for Geb testing.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class BaseSpec extends GebReportingSpec {
|
||||
|
||||
/**
|
||||
* All relative urls will be interpreted against this. The host can change based upon a system property. This
|
||||
* allows for the port to be randomly selected from available ports for CI.
|
||||
*/
|
||||
String getBaseUrl() {
|
||||
def host = System.getProperty('cas.service.host', 'localhost:8443')
|
||||
"https://${host}/cas-sample/"
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out responses and screenshots here.
|
||||
*/
|
||||
File getReportDir() {
|
||||
new File('build/geb-reports')
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.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 CasSampleProxySpec extends BaseSpec {
|
||||
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 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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.cas
|
||||
|
||||
import geb.spock.*
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.spockframework.runtime.Sputnik;
|
||||
import org.springframework.security.samples.cas.pages.*
|
||||
|
||||
import spock.lang.Stepwise;
|
||||
|
||||
/**
|
||||
* Tests the CAS sample application using service tickets.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Stepwise
|
||||
class CasSampleSpec extends BaseSpec {
|
||||
|
||||
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'
|
||||
to ExtremelySecurePage
|
||||
then: 'The login page is displayed'
|
||||
at LoginPage
|
||||
}
|
||||
|
||||
def 'authenticate attempt with invaid ticket fails'() {
|
||||
when: 'present invalid ticket'
|
||||
go "j_spring_cas_security_check?ticket=invalid"
|
||||
then: 'the login failed page is displayed'
|
||||
println driver.pageSource
|
||||
$("h2").text() == 'Login to CAS failed!'
|
||||
}
|
||||
|
||||
def 'access secure page with unauthenticated user requires login'() {
|
||||
when: 'Unauthenticated user accesses the secure page'
|
||||
to 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 extremely secure page with ROLE_USER is denied'() {
|
||||
when: 'User with ROLE_USER accesses extremely secure page'
|
||||
to 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()
|
||||
to 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()
|
||||
to ExtremelySecurePage
|
||||
then: 'login page is displayed'
|
||||
at LoginPage
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.cas;
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
import javax.servlet.ServletException
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
|
||||
import org.apache.commons.httpclient.HttpClient
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.eclipse.jetty.server.Request
|
||||
import org.eclipse.jetty.server.Server
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler
|
||||
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl;
|
||||
import org.jasig.cas.client.validation.Assertion
|
||||
import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
/**
|
||||
* The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter
|
||||
* equal to {@link #serviceUrl()}.
|
||||
*/
|
||||
String pgt
|
||||
|
||||
/**
|
||||
* Start the CAS Service which will be available at {@link #serviceUrl()}.
|
||||
*
|
||||
* @param casServerUrl
|
||||
* @return
|
||||
*/
|
||||
def init(String 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')
|
||||
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector()
|
||||
ssl_connector.setPort(port)
|
||||
ssl_connector.setKeystore(getTrustStore())
|
||||
ssl_connector.setPassword(password)
|
||||
ssl_connector.setKeyPassword(password)
|
||||
addConnector(ssl_connector)
|
||||
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())
|
||||
}
|
||||
def pgt = request.getParameter('pgtId')
|
||||
if(pgt) {
|
||||
JettyCasService.this.pgt = pgt
|
||||
}
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
})
|
||||
start()
|
||||
this
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute URL that this CAS service is available at.
|
||||
* @return
|
||||
*/
|
||||
String serviceUrl() {
|
||||
absoluteUrl('service')
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a relative url, will provide an absolute url for this CAS Service.
|
||||
* @param relativeUrl the relative url (i.e. service, callback, etc)
|
||||
* @return
|
||||
*/
|
||||
private String absoluteUrl(String relativeUrl) {
|
||||
"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.')
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.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") }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.cas.pages;
|
||||
|
||||
import geb.*
|
||||
|
||||
/**
|
||||
* Represents the access denied page
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class AccessDeniedPage extends Page {
|
||||
static at = { $("*",text: iContains(~/.*?403.*/)) }
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.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 }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.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') }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.cas.pages;
|
||||
|
||||
import geb.*
|
||||
|
||||
|
||||
/**
|
||||
* This represents the local logout page. This page is where the user is logged out of the CAS Sample application, but
|
||||
* since the user is still logged into the CAS Server accessing a protected page within the CAS Sample application would result
|
||||
* in SSO occurring again. To fully logout, the user should click the cas server logout url which logs out of the cas server and performs
|
||||
* single logout on the other services.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
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') }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.samples.cas.pages;
|
||||
|
||||
import geb.*
|
||||
|
||||
/**
|
||||
* The CAS login page.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class LoginPage extends Page {
|
||||
static url = loginUrl()
|
||||
static at = { driver.currentUrl == 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 an randomly available port for CI.
|
||||
* @return
|
||||
*/
|
||||
private static String loginUrl() {
|
||||
def host = System.getProperty('cas.server.host', 'localhost:9443')
|
||||
"https://${host}/cas/login"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.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 }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue