feature #24335 [Security][SecurityBundle] Deprecate the HTTP digest auth (ogizanagi)

This PR was merged into the 3.4 branch.

Discussion
----------

[Security][SecurityBundle] Deprecate the HTTP digest auth

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | no <!-- don't forget updating src/**/CHANGELOG.md files -->
| BC breaks?    | no
| Deprecations? | yes <!-- don't forget updating UPGRADE-*.md files -->
| Tests pass?   | yes
| Fixed tickets | #24325  <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | N/A

See https://github.com/symfony/symfony/pull/24336 for the removal PR on master.

Commits
-------

11fe79d77f [Security][SecurityBundle] Deprecate the HTTP digest auth
This commit is contained in:
Fabien Potencier 2017-09-26 15:51:56 -07:00
commit b5103a261f
22 changed files with 453 additions and 9 deletions

View File

@ -270,6 +270,13 @@ Profiler
* The `profiler.matcher` option has been deprecated. * The `profiler.matcher` option has been deprecated.
Security
--------
* Deprecated the HTTP digest authentication: `NonceExpiredException`,
`DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be
removed in 4.0. Use another authentication system like `http_basic` instead.
SecurityBundle SecurityBundle
-------------- --------------
@ -290,6 +297,9 @@ SecurityBundle
* Added `logout_on_user_change` to the firewall options. This config item will * Added `logout_on_user_change` to the firewall options. This config item will
trigger a logout when the user has changed. Should be set to true to avoid trigger a logout when the user has changed. Should be set to true to avoid
deprecations in the configuration. deprecations in the configuration.
* Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0.
Use another authentication system like `http_basic` instead.
Translation Translation
----------- -----------

View File

@ -652,6 +652,10 @@ Security
* Calling `ContextListener::setLogoutOnUserChange(false)` won't have any * Calling `ContextListener::setLogoutOnUserChange(false)` won't have any
effect anymore. effect anymore.
* Removed the HTTP digest authentication system. The `NonceExpiredException`,
`DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` classes
have been removed. Use another authentication system like `http_basic` instead.
SecurityBundle SecurityBundle
-------------- --------------
@ -672,6 +676,9 @@ SecurityBundle
* The firewall option `logout_on_user_change` is now always true, which will * The firewall option `logout_on_user_change` is now always true, which will
trigger a logout if the user changes between requests. trigger a logout if the user changes between requests.
* Removed the HTTP digest authentication system. The `HttpDigestFactory` class
has been removed. Use another authentication system like `http_basic` instead.
Serializer Serializer
---------- ----------

View File

@ -16,6 +16,7 @@ CHANGELOG
* Added `logout_on_user_change` to the firewall options. This config item will * Added `logout_on_user_change` to the firewall options. This config item will
trigger a logout when the user has changed. Should be set to true to avoid trigger a logout when the user has changed. Should be set to true to avoid
deprecations in the configuration. deprecations in the configuration.
* deprecated HTTP digest authentication
3.3.0 3.3.0
----- -----

View File

@ -20,9 +20,18 @@ use Symfony\Component\DependencyInjection\Reference;
* HttpDigestFactory creates services for HTTP digest authentication. * HttpDigestFactory creates services for HTTP digest authentication.
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 3.4, to be removed in 4.0
*/ */
class HttpDigestFactory implements SecurityFactoryInterface class HttpDigestFactory implements SecurityFactoryInterface
{ {
public function __construct($triggerDeprecation = true)
{
if ($triggerDeprecation) {
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
}
}
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
{ {
$provider = 'security.authentication.provider.dao.'.$id; $provider = 'security.authentication.provider.dao.'.$id;
@ -59,6 +68,7 @@ class HttpDigestFactory implements SecurityFactoryInterface
public function addConfiguration(NodeDefinition $node) public function addConfiguration(NodeDefinition $node)
{ {
$node $node
->setDeprecated('The HTTP digest authentication is deprecated since 3.4 and will be removed in 4.0.')
->children() ->children()
->scalarNode('provider')->end() ->scalarNode('provider')->end()
->scalarNode('realm')->defaultValue('Secured Area')->end() ->scalarNode('realm')->defaultValue('Secured Area')->end()

View File

@ -47,7 +47,7 @@ class SecurityBundle extends Bundle
$extension->addSecurityListenerFactory(new JsonLoginFactory()); $extension->addSecurityListenerFactory(new JsonLoginFactory());
$extension->addSecurityListenerFactory(new HttpBasicFactory()); $extension->addSecurityListenerFactory(new HttpBasicFactory());
$extension->addSecurityListenerFactory(new HttpBasicLdapFactory()); $extension->addSecurityListenerFactory(new HttpBasicLdapFactory());
$extension->addSecurityListenerFactory(new HttpDigestFactory()); $extension->addSecurityListenerFactory(new HttpDigestFactory(false));
$extension->addSecurityListenerFactory(new RememberMeFactory()); $extension->addSecurityListenerFactory(new RememberMeFactory());
$extension->addSecurityListenerFactory(new X509Factory()); $extension->addSecurityListenerFactory(new X509Factory());
$extension->addSecurityListenerFactory(new RemoteUserFactory()); $extension->addSecurityListenerFactory(new RemoteUserFactory());

View File

@ -86,6 +86,131 @@ abstract class CompleteConfigurationTest extends TestCase
$configs[0][2] = strtolower($configs[0][2]); $configs[0][2] = strtolower($configs[0][2]);
$configs[2][2] = strtolower($configs[2][2]); $configs[2][2] = strtolower($configs[2][2]);
$this->assertEquals(array(
array(
'simple',
'security.user_checker',
'security.request_matcher.6tndozi',
false,
),
array(
'secure',
'security.user_checker',
null,
true,
true,
'security.user.provider.concrete.default',
null,
'security.authentication.form_entry_point.secure',
null,
null,
array(
'logout',
'switch_user',
'x509',
'remote_user',
'form_login',
'http_basic',
'remember_me',
'anonymous',
),
array(
'parameter' => '_switch_user',
'role' => 'ROLE_ALLOWED_TO_SWITCH',
),
),
array(
'host',
'security.user_checker',
'security.request_matcher.and0kk1',
true,
false,
'security.user.provider.concrete.default',
'host',
'security.authentication.basic_entry_point.host',
null,
null,
array(
'http_basic',
'anonymous',
),
null,
),
array(
'with_user_checker',
'app.user_checker',
null,
true,
false,
'security.user.provider.concrete.default',
'with_user_checker',
'security.authentication.basic_entry_point.with_user_checker',
null,
null,
array(
'http_basic',
'anonymous',
),
null,
),
), $configs);
$this->assertEquals(array(
array(),
array(
'security.channel_listener',
'security.logout_listener.secure',
'security.authentication.listener.x509.secure',
'security.authentication.listener.remote_user.secure',
'security.authentication.listener.form.secure',
'security.authentication.listener.basic.secure',
'security.authentication.listener.rememberme.secure',
'security.authentication.listener.anonymous.secure',
'security.authentication.switchuser_listener.secure',
'security.access_listener',
),
array(
'security.channel_listener',
'security.context_listener.0',
'security.authentication.listener.basic.host',
'security.authentication.listener.anonymous.host',
'security.access_listener',
),
array(
'security.channel_listener',
'security.context_listener.1',
'security.authentication.listener.basic.with_user_checker',
'security.authentication.listener.anonymous.with_user_checker',
'security.access_listener',
),
), $listeners);
$this->assertFalse($container->hasAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', 'No user checker alias is registered when custom user checker services are registered'));
}
/**
* @group legacy
*/
public function testFirewallsWithDigest()
{
$container = $this->getContainer('container1_with_digest');
$arguments = $container->getDefinition('security.firewall.map')->getArguments();
$listeners = array();
$configs = array();
foreach (array_keys($arguments[1]->getValues()) as $contextId) {
$contextDef = $container->getDefinition($contextId);
$arguments = $contextDef->getArguments();
$listeners[] = array_map('strval', $arguments['index_0']->getValues());
$configDef = $container->getDefinition((string) $arguments['index_2']);
$configs[] = array_values($configDef->getArguments());
}
// the IDs of the services are case sensitive or insensitive depending on
// the Symfony version. Transform them to lowercase to simplify tests.
$configs[0][2] = strtolower($configs[0][2]);
$configs[2][2] = strtolower($configs[2][2]);
$this->assertEquals(array( $this->assertEquals(array(
array( array(
'simple', 'simple',

View File

@ -64,7 +64,6 @@ $container->loadFromExtension('security', array(
'simple' => array('pattern' => '/login', 'security' => false), 'simple' => array('pattern' => '/login', 'security' => false),
'secure' => array('stateless' => true, 'secure' => array('stateless' => true,
'http_basic' => true, 'http_basic' => true,
'http_digest' => array('secret' => 'TheSecret'),
'form_login' => true, 'form_login' => true,
'anonymous' => true, 'anonymous' => true,
'switch_user' => true, 'switch_user' => true,

View File

@ -0,0 +1,105 @@
<?php
$container->loadFromExtension('security', array(
'acl' => array(),
'encoders' => array(
'JMS\FooBundle\Entity\User1' => 'plaintext',
'JMS\FooBundle\Entity\User2' => array(
'algorithm' => 'sha1',
'encode_as_base64' => false,
'iterations' => 5,
),
'JMS\FooBundle\Entity\User3' => array(
'algorithm' => 'md5',
),
'JMS\FooBundle\Entity\User4' => array(
'id' => 'security.encoder.foo',
),
'JMS\FooBundle\Entity\User5' => array(
'algorithm' => 'pbkdf2',
'hash_algorithm' => 'sha1',
'encode_as_base64' => false,
'iterations' => 5,
'key_length' => 30,
),
'JMS\FooBundle\Entity\User6' => array(
'algorithm' => 'bcrypt',
'cost' => 15,
),
),
'providers' => array(
'default' => array(
'memory' => array(
'users' => array(
'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
),
),
),
'digest' => array(
'memory' => array(
'users' => array(
'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER, ROLE_ADMIN'),
),
),
),
'basic' => array(
'memory' => array(
'users' => array(
'foo' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => 'ROLE_SUPER_ADMIN'),
'bar' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => array('ROLE_USER', 'ROLE_ADMIN')),
),
),
),
'service' => array(
'id' => 'user.manager',
),
'chain' => array(
'chain' => array(
'providers' => array('service', 'basic'),
),
),
),
'firewalls' => array(
'simple' => array('pattern' => '/login', 'security' => false),
'secure' => array('stateless' => true,
'http_basic' => true,
'http_digest' => array('secret' => 'TheSecret'),
'form_login' => true,
'anonymous' => true,
'switch_user' => true,
'x509' => true,
'remote_user' => true,
'logout' => true,
'remember_me' => array('secret' => 'TheSecret'),
'user_checker' => null,
'logout_on_user_change' => true,
),
'host' => array(
'pattern' => '/test',
'host' => 'foo\\.example\\.org',
'methods' => array('GET', 'POST'),
'anonymous' => true,
'http_basic' => true,
'logout_on_user_change' => true,
),
'with_user_checker' => array(
'user_checker' => 'app.user_checker',
'anonymous' => true,
'http_basic' => true,
'logout_on_user_change' => true,
),
),
'access_control' => array(
array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => array('get', 'POST')),
array('path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'),
array('path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"),
),
'role_hierarchy' => array(
'ROLE_ADMIN' => 'ROLE_USER',
'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'),
'ROLE_REMOTE' => 'ROLE_USER,ROLE_ADMIN',
),
));

View File

@ -15,7 +15,6 @@ $container->loadFromExtension('security', array(
'secure' => array( 'secure' => array(
'stateless' => true, 'stateless' => true,
'http_basic' => true, 'http_basic' => true,
'http_digest' => array('secret' => 'TheSecret'),
'form_login' => true, 'form_login' => true,
'anonymous' => true, 'anonymous' => true,
'switch_user' => true, 'switch_user' => true,

View File

@ -49,7 +49,6 @@
<firewall name="secure" stateless="true"> <firewall name="secure" stateless="true">
<http-basic /> <http-basic />
<http-digest secret="TheSecret" />
<form-login /> <form-login />
<anonymous /> <anonymous />
<switch-user /> <switch-user />

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<config>
<acl />
<encoder class="JMS\FooBundle\Entity\User1" algorithm="plaintext" />
<encoder class="JMS\FooBundle\Entity\User2" algorithm="sha1" encode-as-base64="false" iterations="5" />
<encoder class="JMS\FooBundle\Entity\User3" algorithm="md5" />
<encoder class="JMS\FooBundle\Entity\User4" id="security.encoder.foo" />
<encoder class="JMS\FooBundle\Entity\User5" algorithm="pbkdf2" hash-algorithm="sha1" encode-as-base64="false" iterations="5" key-length="30" />
<encoder class="JMS\FooBundle\Entity\User6" algorithm="bcrypt" cost="15" />
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>
<provider name="digest">
<memory>
<user name="foo" password="foo" roles="ROLE_USER, ROLE_ADMIN" />
</memory>
</provider>
<provider name="basic">
<memory>
<user name="foo" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_SUPER_ADMIN" />
<user name="bar" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_USER, ROLE_ADMIN" />
</memory>
</provider>
<provider name="service" id="user.manager" />
<provider name="chain">
<chain providers="service, basic" />
</provider>
<firewall name="simple" pattern="/login" security="false" />
<firewall name="secure" stateless="true">
<http-basic />
<http-digest secret="TheSecret" />
<form-login />
<anonymous />
<switch-user />
<x509 />
<remote-user />
<user-checker />
<logout />
<remember-me secret="TheSecret"/>
</firewall>
<firewall name="host" pattern="/test" host="foo\.example\.org" methods="GET,POST" logout-on-user-change="true">
<anonymous />
<http-basic />
</firewall>
<firewall name="with_user_checker" logout-on-user-change="true">
<anonymous />
<http-basic />
<user-checker>app.user_checker</user-checker>
</firewall>
<role id="ROLE_ADMIN">ROLE_USER</role>
<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" methods="get,POST" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' path="/blog/.*" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' allow-if="token.getUsername() matches '/^admin/'" path="/blog/524" />
</config>
</srv:container>

View File

@ -15,7 +15,6 @@
<firewall name="secure" stateless="true"> <firewall name="secure" stateless="true">
<http-basic /> <http-basic />
<http-digest secret="TheSecret" />
<form-login /> <form-login />
<anonymous /> <anonymous />
<switch-user /> <switch-user />

View File

@ -46,8 +46,6 @@ security:
secure: secure:
stateless: true stateless: true
http_basic: true http_basic: true
http_digest:
secret: TheSecret
form_login: true form_login: true
anonymous: true anonymous: true
switch_user: true switch_user: true

View File

@ -0,0 +1,85 @@
security:
acl: ~
encoders:
JMS\FooBundle\Entity\User1: plaintext
JMS\FooBundle\Entity\User2:
algorithm: sha1
encode_as_base64: false
iterations: 5
JMS\FooBundle\Entity\User3:
algorithm: md5
JMS\FooBundle\Entity\User4:
id: security.encoder.foo
JMS\FooBundle\Entity\User5:
algorithm: pbkdf2
hash_algorithm: sha1
encode_as_base64: false
iterations: 5
key_length: 30
JMS\FooBundle\Entity\User6:
algorithm: bcrypt
cost: 15
providers:
default:
memory:
users:
foo: { password: foo, roles: ROLE_USER }
digest:
memory:
users:
foo: { password: foo, roles: 'ROLE_USER, ROLE_ADMIN' }
basic:
memory:
users:
foo: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: ROLE_SUPER_ADMIN }
bar: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: [ROLE_USER, ROLE_ADMIN] }
service:
id: user.manager
chain:
chain:
providers: [service, basic]
firewalls:
simple: { pattern: /login, security: false }
secure:
stateless: true
http_basic: true
http_digest:
secret: TheSecret
form_login: true
anonymous: true
switch_user: true
x509: true
remote_user: true
logout: true
remember_me:
secret: TheSecret
user_checker: ~
host:
pattern: /test
host: foo\.example\.org
methods: [GET,POST]
anonymous: true
http_basic: true
logout_on_user_change: true
with_user_checker:
anonymous: ~
http_basic: ~
user_checker: app.user_checker
logout_on_user_change: true
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
ROLE_REMOTE: ROLE_USER,ROLE_ADMIN
access_control:
- { path: /blog/524, role: ROLE_USER, requires_channel: https, methods: [get, POST]}
-
path: /blog/.*
role: IS_AUTHENTICATED_ANONYMOUSLY
- { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" }

View File

@ -10,8 +10,6 @@ security:
secure: secure:
stateless: true stateless: true
http_basic: true http_basic: true
http_digest:
secret: TheSecret
form_login: true form_login: true
anonymous: true anonymous: true
switch_user: true switch_user: true

View File

@ -12,6 +12,7 @@ CHANGELOG
property will trigger a deprecation when the user has changed. As of 4.0 property will trigger a deprecation when the user has changed. As of 4.0
the user will always be logged out when the user has changed between the user will always be logged out when the user has changed between
requests. requests.
* deprecated HTTP digest authentication
3.3.0 3.3.0
----- -----

View File

@ -11,12 +11,16 @@
namespace Symfony\Component\Security\Core\Exception; namespace Symfony\Component\Security\Core\Exception;
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', NonceExpiredException::class), E_USER_DEPRECATED);
/** /**
* NonceExpiredException is thrown when an authentication is rejected because * NonceExpiredException is thrown when an authentication is rejected because
* the digest nonce has expired. * the digest nonce has expired.
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
* @author Alexander <iam.asm89@gmail.com> * @author Alexander <iam.asm89@gmail.com>
*
* @deprecated since 3.4, to be removed in 4.0
*/ */
class NonceExpiredException extends AuthenticationException class NonceExpiredException extends AuthenticationException
{ {

View File

@ -21,6 +21,8 @@ use Psr\Log\LoggerInterface;
* DigestAuthenticationEntryPoint starts an HTTP Digest authentication. * DigestAuthenticationEntryPoint starts an HTTP Digest authentication.
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 3.4, to be removed in 4.0
*/ */
class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{ {
@ -31,6 +33,8 @@ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterfac
public function __construct($realmName, $secret, $nonceValiditySeconds = 300, LoggerInterface $logger = null) public function __construct($realmName, $secret, $nonceValiditySeconds = 300, LoggerInterface $logger = null)
{ {
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
$this->realmName = $realmName; $this->realmName = $realmName;
$this->secret = $secret; $this->secret = $secret;
$this->nonceValiditySeconds = $nonceValiditySeconds; $this->nonceValiditySeconds = $nonceValiditySeconds;

View File

@ -28,6 +28,8 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
* DigestAuthenticationListener implements Digest HTTP authentication. * DigestAuthenticationListener implements Digest HTTP authentication.
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 3.4, to be removed in 4.0
*/ */
class DigestAuthenticationListener implements ListenerInterface class DigestAuthenticationListener implements ListenerInterface
{ {
@ -39,6 +41,8 @@ class DigestAuthenticationListener implements ListenerInterface
public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null) public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null)
{ {
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
if (empty($providerKey)) { if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.'); throw new \InvalidArgumentException('$providerKey must not be empty.');
} }
@ -137,6 +141,9 @@ class DigestAuthenticationListener implements ListenerInterface
} }
} }
/**
* @deprecated since 3.4, to be removed in 4.0.
*/
class DigestData class DigestData
{ {
private $elements = array(); private $elements = array();
@ -145,6 +152,8 @@ class DigestData
public function __construct($header) public function __construct($header)
{ {
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
$this->header = $header; $this->header = $header;
preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER); preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER);
foreach ($matches as $match) { foreach ($matches as $match) {

View File

@ -16,6 +16,9 @@ use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\Security\Core\Exception\NonceExpiredException;
/**
* @group legacy
*/
class DigestAuthenticationEntryPointTest extends TestCase class DigestAuthenticationEntryPointTest extends TestCase
{ {
public function testStart() public function testStart()

View File

@ -8,6 +8,9 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener; use Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener;
/**
* @group legacy
*/
class DigestAuthenticationListenerTest extends TestCase class DigestAuthenticationListenerTest extends TestCase
{ {
public function testHandleWithValidDigest() public function testHandleWithValidDigest()

View File

@ -14,6 +14,9 @@ namespace Symfony\Component\Security\Http\Tests\Firewall;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Http\Firewall\DigestData; use Symfony\Component\Security\Http\Firewall\DigestData;
/**
* @group legacy
*/
class DigestDataTest extends TestCase class DigestDataTest extends TestCase
{ {
public function testGetResponse() public function testGetResponse()