mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 11:28:25 +00:00
da79dff7d7
- Dispatcher sets a Controller::here variable with the real URL used to access the page, so that tag generators can that use an url (linkTo and formTag for example) use the real url, not guess it from the controller and action names which often fails - Log class works more reliably and a LogError() shortcut function was added - Nstring class added, to store string-related functions (there are just four yet, including a random password generator and an string-to-array splitter - SimpleTest library (with Rephlux) included in /vendors; I've tweaked SimpleScorer::inCli() function, because it didn't work on my setup, it should work everywhere now (it checks for empty REQUEST_METHOD, which should only be empty in CLI) git-svn-id: https://svn.cakephp.org/repo/trunk/cake@248 3807eeeb-6ff5-0310-8944-8be069107fe0
320 lines
11 KiB
HTML
320 lines
11 KiB
HTML
<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">
|
|
<h2>
|
|
<a href="index.html">SimpleTest</a>
|
|
</h2>
|
|
<ul>
|
|
<li>
|
|
<a href="overview.html">Overview</a>
|
|
</li>
|
|
<li>
|
|
<a href="unit_test_documentation.html">Unit tester</a>
|
|
</li>
|
|
<li>
|
|
<a href="group_test_documentation.html">Group tests</a>
|
|
</li>
|
|
<li>
|
|
<a href="server_stubs_documentation.html">Server stubs</a>
|
|
</li>
|
|
<li>
|
|
<a href="mock_objects_documentation.html">Mock objects</a>
|
|
</li>
|
|
<li>
|
|
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
|
</li>
|
|
<li>
|
|
<a href="reporter_documentation.html">Reporting</a>
|
|
</li>
|
|
<li>
|
|
<a href="expectation_documentation.html">Expectations</a>
|
|
</li>
|
|
<li>
|
|
<a href="web_tester_documentation.html">Web tester</a>
|
|
</li>
|
|
<li>
|
|
<a href="form_testing_documentation.html">Testing forms</a>
|
|
</li>
|
|
<li>
|
|
<span class="chosen">Authentication</span>
|
|
</li>
|
|
<li>
|
|
<a href="browser_documentation.html">Scriptable browser</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<h1>Authentication documentation</h1>
|
|
<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>
|
|
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 testAuthentication() {
|
|
$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.
|
|
</p>
|
|
<p>
|
|
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->clickSubmit('Log in');
|
|
$this->assertWantedPattern('/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->assertWantedPattern('/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->clickSubmit('Log in');
|
|
$this->assertWantedPattern('/Welcome Me/');<strong>
|
|
|
|
$this->restart();
|
|
$this->get('http://www.my-site.com/restricted.php');
|
|
$this->assertWantedPattern('/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->clickSubmit('Log in');
|
|
$this->assertWantedPattern('/Welcome Me/');
|
|
<strong>
|
|
$this->ageCookies(3600);</strong>
|
|
$this->restart();
|
|
$this->get('http://www.my-site.com/restricted.php');
|
|
$this->assertWantedPattern('/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>
|
|
<div class="copyright">
|
|
Copyright<br>Marcus Baker, Jason Sweat, Perrick Penet 2004
|
|
</div>
|
|
</body>
|
|
</html>
|