diff options
Diffstat (limited to 'vendors/simpletest/docs/en/authentication_documentation.html')
-rwxr-xr-x | vendors/simpletest/docs/en/authentication_documentation.html | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/vendors/simpletest/docs/en/authentication_documentation.html b/vendors/simpletest/docs/en/authentication_documentation.html new file mode 100755 index 000000000..8da2a7f9e --- /dev/null +++ b/vendors/simpletest/docs/en/authentication_documentation.html @@ -0,0 +1,355 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>SimpleTest documentation for testing log-in and authentication</title> +<link rel="stylesheet" type="text/css" href="docs.css" title="Styles"> +</head> +<body> +<div class="menu_back"><div class="menu"> +<a href="index.html">SimpleTest</a> + | + <a href="overview.html">Overview</a> + | + <a href="unit_test_documentation.html">Unit tester</a> + | + <a href="group_test_documentation.html">Group tests</a> + | + <a href="mock_objects_documentation.html">Mock objects</a> + | + <a href="partial_mocks_documentation.html">Partial mocks</a> + | + <a href="reporter_documentation.html">Reporting</a> + | + <a href="expectation_documentation.html">Expectations</a> + | + <a href="web_tester_documentation.html">Web tester</a> + | + <a href="form_testing_documentation.html">Testing forms</a> + | + <span class="chosen">Authentication</span> + | + <a href="browser_documentation.html">Scriptable browser</a> +</div></div> +<h1>Authentication documentation</h1> + This page... + <ul> +<li> + Getting through <a href="#basic">Basic HTTP authentication</a> + </li> +<li> + Testing <a href="#cookies">cookie based authentication</a> + </li> +<li> + Managing <a href="#session">browser sessions</a> and timeouts + </li> +</ul> +<div class="content"> + + <p> + One of the trickiest, and yet most important, areas + of testing web sites is the security. + Testing these schemes is one of the core goals of + the SimpleTest web tester. + </p> + + <p><a class="target" name="basic"><h2>Basic HTTP authentication</h2></a></p> + <p> + If you fetch a page protected by basic authentication then + rather than receiving content, you will instead get a 401 + header. + We can illustrate this with this test... +<pre> +class AuthenticationTest extends WebTestCase {<strong> + function test401Header() { + $this->get('http://www.lastcraft.com/protected/'); + $this->showHeaders(); + }</strong> +} +</pre> + This allows us to see the challenge header... + <div class="demo"> + <h1>File test</h1> +<pre style="background-color: lightgray; color: black"> +HTTP/1.1 401 Authorization Required +Date: Sat, 18 Sep 2004 19:25:18 GMT +Server: Apache/1.3.29 (Unix) PHP/4.3.4 +WWW-Authenticate: Basic realm="SimpleTest basic authentication" +Connection: close +Content-Type: text/html; charset=iso-8859-1 +</pre> + <div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete. + <strong>0</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div> + </div> + We are trying to get away from visual inspection though, and so SimpleTest + allows to make automated assertions against the challenge. + Here is a thorough test of our header... +<pre> +class AuthenticationTest extends WebTestCase { + function test401Header() { + $this->get('http://www.lastcraft.com/protected/');<strong> + $this->assertAuthentication('Basic'); + $this->assertResponse(401); + $this->assertRealm('SimpleTest basic authentication');</strong> + } +} +</pre> + Any one of these tests would normally do on it's own depending + on the amount of detail you want to see. + </p> + <p> + One theme that runs through SimpleTest is the ability to use + <span class="new_code">SimpleExpectation</span> objects wherever a simple + match is not enough. + If you want only an approximate match to the realm for + example, you can do this... +<pre> +class AuthenticationTest extends WebTestCase { + function test401Header() { + $this->get('http://www.lastcraft.com/protected/'); + $this->assertRealm(<strong>new PatternExpectation('/simpletest/i')</strong>); + } +} +</pre> + Most of the time we are not interested in testing the + authentication itself, but want to get past it to test + the pages underneath. + As soon as the challenge has been issued we can reply with + an authentication response... +<pre> +class AuthenticationTest extends WebTestCase { + function testCanAuthenticate() { + $this->get('http://www.lastcraft.com/protected/');<strong> + $this->authenticate('Me', 'Secret');</strong> + $this->assertTitle(...); + } +} +</pre> + The username and password will now be sent with every + subsequent request to that directory and subdirectories. + You will have to authenticate again if you step outside + the authenticated directory, but SimpleTest is smart enough + to merge subdirectories into a common realm. + </p> + <p> + You can shortcut this step further by encoding the log in + details straight into the URL... +<pre> +class AuthenticationTest extends WebTestCase { + function testCanReadAuthenticatedPages() { + $this->get('http://<strong>Me:Secret@</strong>www.lastcraft.com/protected/'); + $this->assertTitle(...); + } +} +</pre> + If your username or password has special characters, then you + will have to URL encode them or the request will not be parsed + correctly. + Also this header will not be sent on subsequent requests if + you request a page with a fully qualified URL. + If you navigate with relative URLs though, the authentication + information will be preserved. + </p> + <p> + Only basic authentication is currently supported and this is + only really secure in tandem with HTTPS connections. + This is usually enough to protect test server from prying eyes, + however. + Digest authentication and NTLM authentication may be added + in the future. + </p> + + <p><a class="target" name="cookies"><h2>Cookies</h2></a></p> + <p> + Basic authentication doesn't give enough control over the + user interface for web developers. + More likely this functionality will be coded directly into + the web architecture using cookies and complicated timeouts. + </p> + <p> + Starting with a simple log-in form... +<pre> +<form> + Username: + <input type="text" name="u" value="" /><br /> + Password: + <input type="password" name="p" value="" /><br /> + <input type="submit" value="Log in" /> +</form> +</pre> + Which looks like... + </p> + <p> + <form class="demo"> + Username: + <input type="text" name="u" value=""><br> + Password: + <input type="password" name="p" value=""><br> + <input type="submit" value="Log in"> + </form> + </p> + <p> + Let's suppose that in fetching this page a cookie has been + set with a session ID. + We are not going to fill the form in yet, just test that + we are tracking the user. + Here is the test... +<pre> +class LogInTest extends WebTestCase { + function testSessionCookieSetBeforeForm() { + $this->get('http://www.my-site.com/login.php');<strong> + $this->assertCookie('SID');</strong> + } +} +</pre> + All we are doing is confirming that the cookie is set. + As the value is likely to be rather cryptic it's not + really worth testing this with... +<pre> +class LogInTest extends WebTestCase { + function testSessionCookieIsCorrectPattern() { + $this->get('http://www.my-site.com/login.php'); + $this->assertCookie('SID', <strong>new PatternExpectation('/[a-f0-9]{32}/i')</strong>); + } +} +</pre> + The rest of the test would be the same as any other form, + but we might want to confirm that we still have the same + cookie after log-in as before we entered. + We wouldn't want to lose track of this after all. + Here is a possible test for this... +<pre> +class LogInTest extends WebTestCase { + ... + function testSessionCookieSameAfterLogIn() { + $this->get('http://www.my-site.com/login.php');<strong> + $session = $this->getCookie('SID'); + $this->setField('u', 'Me'); + $this->setField('p', 'Secret'); + $this->click('Log in'); + $this->assertText('Welcome Me'); + $this->assertCookie('SID', $session);</strong> + } +} +</pre> + This confirms that the session identifier is maintained + afer log-in. + </p> + <p> + We could even attempt to spoof our own system by setting + arbitrary cookies to gain access... +<pre> +class LogInTest extends WebTestCase { + ... + function testSessionCookieSameAfterLogIn() { + $this->get('http://www.my-site.com/login.php');<strong> + $this->setCookie('SID', 'Some other session'); + $this->get('http://www.my-site.com/restricted.php');</strong> + $this->assertText('Access denied'); + } +} +</pre> + Is your site protected from this attack? + </p> + + <p><a class="target" name="session"><h2>Browser sessions</h2></a></p> + <p> + If you are testing an authentication system a critical piece + of behaviour is what happens when a user logs back in. + We would like to simulate closing and reopening a browser... +<pre> +class LogInTest extends WebTestCase { + ... + function testLoseAuthenticationAfterBrowserClose() { + $this->get('http://www.my-site.com/login.php'); + $this->setField('u', 'Me'); + $this->setField('p', 'Secret'); + $this->click('Log in'); + $this->assertText('Welcome Me');<strong> + + $this->restart(); + $this->get('http://www.my-site.com/restricted.php'); + $this->assertText('Access denied');</strong> + } +} +</pre> + The <span class="new_code">WebTestCase::restart()</span> method will + preserve cookies that have unexpired timeouts, but throw away + those that are temporary or expired. + You can optionally specify the time and date that the restart + happened. + </p> + <p> + Expiring cookies can be a problem. + After all, if you have a cookie that expires after an hour, + you don't want to stall the test for an hour while the + cookie passes it's timeout. + </p> + <p> + To push the cookies over the hour limit you can age them + before you restart the session... +<pre> +class LogInTest extends WebTestCase { + ... + function testLoseAuthenticationAfterOneHour() { + $this->get('http://www.my-site.com/login.php'); + $this->setField('u', 'Me'); + $this->setField('p', 'Secret'); + $this->click('Log in'); + $this->assertText('Welcome Me'); + <strong> + $this->ageCookies(3600);</strong> + $this->restart(); + $this->get('http://www.my-site.com/restricted.php'); + $this->assertText('Access denied'); + } +} +</pre> + After the restart it will appear that cookies are an + hour older and any that pass their expiry will have + disappeared. + </p> + + </div> + References and related information... + <ul> +<li> + SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>. + </li> +<li> + SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>. + </li> +<li> + The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a> + gives full detail on the classes and assertions available. + </li> +</ul> +<div class="menu_back"><div class="menu"> +<a href="index.html">SimpleTest</a> + | + <a href="overview.html">Overview</a> + | + <a href="unit_test_documentation.html">Unit tester</a> + | + <a href="group_test_documentation.html">Group tests</a> + | + <a href="mock_objects_documentation.html">Mock objects</a> + | + <a href="partial_mocks_documentation.html">Partial mocks</a> + | + <a href="reporter_documentation.html">Reporting</a> + | + <a href="expectation_documentation.html">Expectations</a> + | + <a href="web_tester_documentation.html">Web tester</a> + | + <a href="form_testing_documentation.html">Testing forms</a> + | + <span class="chosen">Authentication</span> + | + <a href="browser_documentation.html">Scriptable browser</a> +</div></div> +<div class="copyright"> + Copyright<br>Marcus Baker 2006 + </div> +</body> +</html> |