Merge branch '2.0' into 2.1

* 2.0:
  [DependencyInjection] fixed composer.json
  [Form] Updated checks for the ICU version from 4.5+ to 4.7+ due to test failures with ICU 4.6
  fixed CS
  small fix of #5984 when the container param is not set
  fixed CS
  Use better default ports in urlRedirectAction
  Add tests for urlRedirectAction
  Update src/Symfony/Component/DomCrawler/Tests/FormTest.php
  Update src/Symfony/Component/DomCrawler/Form.php
  [Security] remove escape charters from username provided by Digest DigestAuthenticationListener
  [Security] added test extra for digest authentication
  fixed CS
  [Security] Fixed digest authentication
  [Security] Fixed digest authentication
  [SecurityBundle] Convert Http method to uppercase in the config
  Use Norm Data instead of Data

Conflicts:
	src/Symfony/Bridge/Doctrine/Form/EventListener/MergeCollectionListener.php
	src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php
	src/Symfony/Component/DependencyInjection/composer.json
This commit is contained in:
Fabien Potencier 2012-11-29 11:32:18 +01:00
commit 922c2015f6
12 changed files with 393 additions and 40 deletions

View File

@ -57,15 +57,15 @@ class RedirectController extends ContainerAware
* In case the path is empty, the status code will be 404 when permanent is false
* and 410 otherwise.
*
* @param string $path The absolute path or URL to redirect to
* @param Boolean $permanent Whether the redirection is permanent
* @param Boolean $scheme The URL scheme (null to keep the current one)
* @param integer $httpPort The HTTP port
* @param integer $httpsPort The HTTPS port
* @param string $path The absolute path or URL to redirect to
* @param Boolean $permanent Whether the redirect is permanent or not
* @param string|null $scheme The URL scheme (null to keep the current one)
* @param integer|null $httpPort The HTTP port (null to keep the current one for the same scheme or the configured port in the container)
* @param integer|null $httpsPort The HTTPS port (null to keep the current one for the same scheme or the configured port in the container)
*
* @return Response A Response instance
*/
public function urlRedirectAction($path, $permanent = false, $scheme = null, $httpPort = 80, $httpsPort = 443)
public function urlRedirectAction($path, $permanent = false, $scheme = null, $httpPort = null, $httpsPort = null)
{
if ('' == $path) {
return new Response(null, $permanent ? 410 : 404);
@ -89,10 +89,30 @@ class RedirectController extends ContainerAware
}
$port = '';
if ('http' === $scheme && 80 != $httpPort) {
$port = ':'.$httpPort;
} elseif ('https' === $scheme && 443 != $httpsPort) {
$port = ':'.$httpsPort;
if ('http' === $scheme) {
if (null === $httpPort) {
if ('http' === $request->getScheme()) {
$httpPort = $request->getPort();
} elseif ($this->container->hasParameter('request_listener.http_port')) {
$httpPort = $this->container->getParameter('request_listener.http_port');
}
}
if (null !== $httpPort && 80 != $httpPort) {
$port = ":$httpPort";
}
} elseif ('https' === $scheme) {
if (null === $httpsPort) {
if ('https' === $request->getScheme()) {
$httpsPort = $request->getPort();
} elseif ($this->container->hasParameter('request_listener.https_port')) {
$httpsPort = $this->container->getParameter('request_listener.https_port');
}
}
if (null !== $httpsPort && 443 != $httpsPort) {
$port = ":$httpsPort";
}
}
$url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs;

View File

@ -87,9 +87,7 @@ class RedirectControllerTest extends TestCase
$returnResponse = $controller->redirectAction($route, $permanent);
$this->assertInstanceOf('\Symfony\Component\HttpFoundation\Response', $returnResponse);
$this->assertTrue($returnResponse->isRedirect($url));
$this->assertRedirectUrl($returnResponse, $url);
$this->assertEquals($expectedCode, $returnResponse->getStatusCode());
}
@ -119,9 +117,143 @@ class RedirectControllerTest extends TestCase
$controller = new RedirectController();
$returnResponse = $controller->urlRedirectAction('http://foo.bar/');
$this->assertInstanceOf('\Symfony\Component\HttpFoundation\Response', $returnResponse);
$this->assertEquals('http://foo.bar/', $returnResponse->headers->get('Location'));
$this->assertRedirectUrl($returnResponse, 'http://foo.bar/');
$this->assertEquals(302, $returnResponse->getStatusCode());
}
public function testUrlRedirectDefaultPortParameters()
{
$host = 'www.example.com';
$baseUrl = '/base';
$path = '/redirect-path';
$httpPort = 1080;
$httpsPort = 1443;
$expectedUrl = "https://$host:$httpsPort$baseUrl$path";
$request = $this->createRequestObject('http', $host, $httpPort, $baseUrl);
$controller = $this->createRedirectController($request, null, $httpsPort);
$returnValue = $controller->urlRedirectAction($path, false, 'https');
$this->assertRedirectUrl($returnValue, $expectedUrl);
$expectedUrl = "http://$host:$httpPort$baseUrl$path";
$request = $this->createRequestObject('https', $host, $httpPort, $baseUrl);
$controller = $this->createRedirectController($request, $httpPort);
$returnValue = $controller->urlRedirectAction($path, false, 'http');
$this->assertRedirectUrl($returnValue, $expectedUrl);
}
public function urlRedirectProvider()
{
return array(
// Standard ports
array('http', null, null, 'http', 80, ""),
array('http', 80, null, 'http', 80, ""),
array('https', null, null, 'http', 80, ""),
array('https', 80, null, 'http', 80, ""),
array('http', null, null, 'https', 443, ""),
array('http', null, 443, 'https', 443, ""),
array('https', null, null, 'https', 443, ""),
array('https', null, 443, 'https', 443, ""),
// Non-standard ports
array('http', null, null, 'http', 8080, ":8080"),
array('http', 4080, null, 'http', 8080, ":4080"),
array('http', 80, null, 'http', 8080, ""),
array('https', null, null, 'http', 8080, ""),
array('https', null, 8443, 'http', 8080, ":8443"),
array('https', null, 443, 'http', 8080, ""),
array('https', null, null, 'https', 8443, ":8443"),
array('https', null, 4443, 'https', 8443, ":4443"),
array('https', null, 443, 'https', 8443, ""),
array('http', null, null, 'https', 8443, ""),
array('http', 8080, 4443, 'https', 8443, ":8080"),
array('http', 80, 4443, 'https', 8443, ""),
);
}
/**
* @dataProvider urlRedirectProvider
*/
public function testUrlRedirect($scheme, $httpPort, $httpsPort, $requestScheme, $requestPort, $expectedPort)
{
$host = 'www.example.com';
$baseUrl = '/base';
$path = '/redirect-path';
$expectedUrl = "$scheme://$host$expectedPort$baseUrl$path";
$request = $this->createRequestObject($requestScheme, $host, $requestPort, $baseUrl);
$controller = $this->createRedirectController($request);
$returnValue = $controller->urlRedirectAction($path, false, $scheme, $httpPort, $httpsPort);
$this->assertRedirectUrl($returnValue, $expectedUrl);
}
private function createRequestObject($scheme, $host, $port, $baseUrl)
{
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$request
->expects($this->any())
->method('getScheme')
->will($this->returnValue($scheme));
$request
->expects($this->any())
->method('getHost')
->will($this->returnValue($host));
$request
->expects($this->any())
->method('getPort')
->will($this->returnValue($port));
$request
->expects($this->any())
->method('getBaseUrl')
->will($this->returnValue($baseUrl));
return $request;
}
private function createRedirectController(Request $request, $httpPort = null, $httpsPort = null)
{
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container
->expects($this->at(0))
->method('get')
->with($this->equalTo('request'))
->will($this->returnValue($request));
if (null !== $httpPort) {
$container
->expects($this->once())
->method('hasParameter')
->with($this->equalTo('request_listener.http_port'))
->will($this->returnValue(true));
$container
->expects($this->once())
->method('getParameter')
->with($this->equalTo('request_listener.http_port'))
->will($this->returnValue($httpPort));
}
if (null !== $httpsPort) {
$container
->expects($this->once())
->method('hasParameter')
->with($this->equalTo('request_listener.https_port'))
->will($this->returnValue(true));
$container
->expects($this->once())
->method('getParameter')
->with($this->equalTo('request_listener.https_port'))
->will($this->returnValue($httpsPort));
}
$controller = new RedirectController();
$controller->setContainer($container);
return $controller;
}
public function assertRedirectUrl(Response $returnResponse, $expectedUrl)
{
$this->assertTrue($returnResponse->isRedirect($expectedUrl), "Expected: $expectedUrl\nGot: ".$returnResponse->headers->get('Location'));
}
}

View File

@ -182,7 +182,7 @@ class SecurityExtension extends Extension
$container,
$access['path'],
$access['host'],
count($access['methods']) === 0 ? null : $access['methods'],
$access['methods'],
$access['ip']
);
@ -574,7 +574,7 @@ class SecurityExtension extends Extension
return $switchUserListenerId;
}
private function createRequestMatcher($container, $path = null, $host = null, $methods = null, $ip = null, array $attributes = array())
private function createRequestMatcher($container, $path = null, $host = null, $methods = array(), $ip = null, array $attributes = array())
{
$serialized = serialize(array($path, $host, $methods, $ip, $attributes));
$id = 'security.request_matcher.'.md5($serialized).sha1($serialized);
@ -583,6 +583,10 @@ class SecurityExtension extends Extension
return $this->requestMatchers[$id];
}
if ($methods) {
$methods = array_map('strtoupper', (array) $methods);
}
// only add arguments that are necessary
$arguments = array($path, $host, $methods, $ip, $attributes);
while (count($arguments) > 0 && !end($arguments)) {

View File

@ -63,7 +63,7 @@ $container->loadFromExtension('security', array(
),
'access_control' => array(
array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https'),
array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => array('get', 'POST')),
array('path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'),
),

View File

@ -57,7 +57,7 @@
<role id="ROLE_SUPER_ADMIN">ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH</role>
<role id="ROLE_REMOTE">ROLE_USER,ROLE_ADMIN</role>
<rule path="/blog/524" role="ROLE_USER" requires-channel="https" />
<rule path="/blog/524" role="ROLE_USER" requires-channel="https" methods="get,POST" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' path="/blog/.*" />
</config>
</srv:container>

View File

@ -51,7 +51,7 @@ security:
ROLE_REMOTE: ROLE_USER,ROLE_ADMIN
access_control:
- { path: /blog/524, role: ROLE_USER, requires_channel: https }
- { path: /blog/524, role: ROLE_USER, requires_channel: https, methods: [get, POST]}
-
path: /blog/.*
role: IS_AUTHENTICATED_ANONYMOUSLY

View File

@ -102,6 +102,7 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
$matcherIds = array();
foreach ($rules as $rule) {
list($matcherId, $roles, $channel) = $rule;
$requestMatcher = $container->getDefinition($matcherId);
$this->assertFalse(isset($matcherIds[$matcherId]));
$matcherIds[$matcherId] = true;
@ -110,9 +111,17 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
if (1 === $i) {
$this->assertEquals(array('ROLE_USER'), $roles);
$this->assertEquals('https', $channel);
$this->assertEquals(
array('/blog/524', null, array('GET', 'POST')),
$requestMatcher->getArguments()
);
} elseif (2 === $i) {
$this->assertEquals(array('IS_AUTHENTICATED_ANONYMOUSLY'), $roles);
$this->assertNull($channel);
$this->assertEquals(
array('/blog/.*'),
$requestMatcher->getArguments()
);
}
}
}

View File

@ -359,7 +359,7 @@ class Form extends Link implements \ArrayAccess
$xpath = new \DOMXPath($document);
foreach ($xpath->query('descendant::input | descendant::button | descendant::textarea | descendant::select', $root) as $node) {
if (!$node->hasAttribute('name')) {
if (!$node->hasAttribute('name') || !$node->getAttribute('name')) {
continue;
}

View File

@ -126,6 +126,12 @@ class FormTest extends \PHPUnit_Framework_TestCase
<input type="submit" />',
array(),
),
array(
'does not take into account input fields with an empty name attribute value',
'<input type="text" name="" value="foo" />
<input type="submit" />',
array(),
),
array(
'takes into account disabled input fields',
'<input type="text" name="foo" value="foo" disabled="disabled" />

View File

@ -96,8 +96,8 @@ class NumberToLocalizedStringTransformerTest extends LocalizedTestCase
public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot()
{
if ($this->isLowerThanIcuVersion('4.5')) {
$this->markTestSkipped('Please upgrade ICU version to 4.5+');
if ($this->isLowerThanIcuVersion('4.7')) {
$this->markTestSkipped('Please upgrade ICU version to 4.7+');
}
\Locale::setDefault('fr');
@ -117,8 +117,8 @@ class NumberToLocalizedStringTransformerTest extends LocalizedTestCase
*/
public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot()
{
if ($this->isLowerThanIcuVersion('4.5')) {
$this->markTestSkipped('Please upgrade ICU version to 4.5+');
if ($this->isLowerThanIcuVersion('4.7')) {
$this->markTestSkipped('Please upgrade ICU version to 4.7+');
}
$transformer = new NumberToLocalizedStringTransformer(null, true);
@ -131,8 +131,8 @@ class NumberToLocalizedStringTransformerTest extends LocalizedTestCase
*/
public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot_noGroupSep()
{
if ($this->isLowerThanIcuVersion('4.5')) {
$this->markTestSkipped('Please upgrade ICU version to 4.5+');
if ($this->isLowerThanIcuVersion('4.7')) {
$this->markTestSkipped('Please upgrade ICU version to 4.7+');
}
$transformer = new NumberToLocalizedStringTransformer(null, true);
@ -151,8 +151,8 @@ class NumberToLocalizedStringTransformerTest extends LocalizedTestCase
public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma()
{
if ($this->isLowerThanIcuVersion('4.5')) {
$this->markTestSkipped('Please upgrade ICU version to 4.5+');
if ($this->isLowerThanIcuVersion('4.7')) {
$this->markTestSkipped('Please upgrade ICU version to 4.7+');
}
\Locale::setDefault('ak');
@ -172,8 +172,8 @@ class NumberToLocalizedStringTransformerTest extends LocalizedTestCase
*/
public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma()
{
if ($this->isLowerThanIcuVersion('4.5')) {
$this->markTestSkipped('Please upgrade ICU version to 4.5+');
if ($this->isLowerThanIcuVersion('4.7')) {
$this->markTestSkipped('Please upgrade ICU version to 4.7+');
}
\Locale::setDefault('en');
@ -187,8 +187,8 @@ class NumberToLocalizedStringTransformerTest extends LocalizedTestCase
*/
public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma_noGroupSep()
{
if ($this->isLowerThanIcuVersion('4.5')) {
$this->markTestSkipped('Please upgrade ICU version to 4.5+');
if ($this->isLowerThanIcuVersion('4.7')) {
$this->markTestSkipped('Please upgrade ICU version to 4.7+');
}
\Locale::setDefault('en');

View File

@ -141,11 +141,12 @@ class DigestData
public function __construct($header)
{
$this->header = $header;
$parts = preg_split('/, /', $header);
preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER);
$this->elements = array();
foreach ($parts as $part) {
list($key, $value) = explode('=', $part);
$this->elements[$key] = '"' === $value[0] ? substr($value, 1, -1) : $value;
foreach ($matches as $match) {
if (isset($match[1]) && isset($match[3])) {
$this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3];
}
}
}
@ -156,7 +157,7 @@ class DigestData
public function getUsername()
{
return $this->elements['username'];
return strtr($this->elements['username'], array("\\\"" => "\"", "\\\\" => "\\"));
}
public function validateAndDecode($entryPointKey, $expectedRealm)
@ -188,7 +189,7 @@ class DigestData
$this->nonceExpiryTime = $nonceTokens[0];
if (md5($this->nonceExpiryTime.':'.$entryPointKey) !== $nonceTokens[1]) {
new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText));
throw new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText));
}
}

View File

@ -0,0 +1,181 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Tests\Http\Firewall;
use Symfony\Component\Security\Http\Firewall\DigestData;
class DigestDataTest extends \PHPUnit_Framework_TestCase
{
public function testGetResponse()
{
$digestAuth = new DigestData(
'username="user", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('b52938fc9e6d7c01be7702ece9031b42', $digestAuth->getResponse());
}
public function testGetUsername()
{
$digestAuth = new DigestData(
'username="user", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('user', $digestAuth->getUsername());
}
public function testGetUsernameWithQuote()
{
$digestAuth = new DigestData(
'username="\"user\"", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('"user"', $digestAuth->getUsername());
}
public function testGetUsernameWithQuoteAndEscape()
{
$digestAuth = new DigestData(
'username="\"u\\\\\"ser\"", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('"u\\"ser"', $digestAuth->getUsername());
}
public function testGetUsernameWithSingleQuote()
{
$digestAuth = new DigestData(
'username="\"u\'ser\"", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('"u\'ser"', $digestAuth->getUsername());
}
public function testGetUsernameWithSingleQuoteAndEscape()
{
$digestAuth = new DigestData(
'username="\"u\\\'ser\"", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('"u\\\'ser"', $digestAuth->getUsername());
}
public function testGetUsernameWithEscape()
{
$digestAuth = new DigestData(
'username="\"u\\ser\"", realm="Welcome, robot!", ' .
'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$this->assertEquals('"u\\ser"', $digestAuth->getUsername());
}
public function testValidateAndDecode()
{
$time = microtime(true);
$key = 'ThisIsAKey';
$nonce = base64_encode($time . ':' . md5($time . ':' . $key));
$digestAuth = new DigestData(
'username="user", realm="Welcome, robot!", nonce="' . $nonce . '", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
try {
$digestAuth->validateAndDecode($key, 'Welcome, robot!');
} catch (\Exception $e) {
$this->fail(sprintf('testValidateAndDecode fail with message: %s', $e->getMessage()));
}
}
public function testCalculateServerDigest()
{
$this->calculateServerDigest('user', 'Welcome, robot!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
}
public function testCalculateServerDigestWithQuote()
{
$this->calculateServerDigest('\"user\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
}
public function testCalculateServerDigestWithQuoteAndEscape()
{
$this->calculateServerDigest('\"u\\\\\"ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
}
public function testCalculateServerDigestEscape()
{
$this->calculateServerDigest('\"u\\ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
$this->calculateServerDigest('\"u\\ser\\\\\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5');
}
public function testIsNonceExpired()
{
$time = microtime(true) + 10;
$key = 'ThisIsAKey';
$nonce = base64_encode($time . ':' . md5($time . ':' . $key));
$digestAuth = new DigestData(
'username="user", realm="Welcome, robot!", nonce="' . $nonce . '", ' .
'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", ' .
'response="b52938fc9e6d7c01be7702ece9031b42"'
);
$digestAuth->validateAndDecode($key, 'Welcome, robot!');
$this->assertFalse($digestAuth->isNonceExpired());
}
protected function setUp()
{
class_exists('Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener', true);
}
private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri)
{
$time = microtime(true);
$nonce = base64_encode($time . ':' . md5($time . ':' . $key));
$response = md5(
md5($username . ':' . $realm . ':' . $password) . ':' . $nonce . ':' . $nc . ':' . $cnonce . ':' . $qop . ':' . md5($method . ':' . $uri)
);
$digest = sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"',
$username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response
);
$digestAuth = new DigestData($digest);
$this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method));
}
}