Symfony 5 - Semaphore extension (sysvsem) is required

7.9k views Asked by At

I have implemented the brand new Symfony authentication system : https://symfony.com/doc/current/security/experimental_authenticators.html

And I added the new Login Throttling : https://symfony.com/blog/new-in-symfony-5-2-login-throttling

Everything is correctly configured.

I also installed the RateLimiter component, which created an environment variable:

LOCK_DSN=semaphore

But I have a problem. First, the Login Throttling seems to be half ignored. I have no error message once the limit is exceeded. On the other hand, if I try to connect with good credentials, I have the following error which appears :

Semaphore extension (sysvsem) is required.

I tried to install the Semaphore component ( https://symfony.com/doc/current/components/semaphore.html )

But same problem.

This is my security.yaml

security:
  enable_authenticator_manager: true

  encoders:
    App\Application\Entity\User:
      algorithm: auto

  # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
  providers:
    in_memory: { memory: ~ }
    # used to reload user from session & other features (e.g. switch_user)
    in_database:
      entity:
        class: App\Application\Entity\User
        property: email
  firewalls:
    dev:
      pattern: ^/(_(profiler|wdt)|css|images|js)/
      security: false

    main:
      user_checker: App\Application\Security\UserChecker
      provider: in_database
      lazy: true

      remember_me:
        secret: '%kernel.secret%'

      form_login:
        login_path: app_login
        check_path: app_login
        default_target_path: home

      logout:
        path: app_logout
        target: app_login

      custom_authenticators:
        - App\Application\Security\AppCustomAuthenticator

      entry_point: App\Application\Security\AppCustomAuthenticator

      # configuring the maximum login attempts (per minute)
      login_throttling:
        max_attempts: 2

I searched if there was an extension to add to PHP but couldn't find anything. So I don't know what to do. I'm on Windows 10

2

There are 2 answers

0
Nodoka Murmevent On BEST ANSWER

i also had this problem, you can change the store for locking: https://symfony.com/doc/current/components/lock.html#available-stores

my solution was to change in .env.local

###> symfony/lock ###
# Choose one of the stores below
# postgresql+advisory://db_user:db_password@localhost/db_name
LOCK_DSN=semaphore
###< symfony/lock ###

to :

###> symfony/lock ###
# Choose one of the stores below
# postgresql+advisory://db_user:db_password@localhost/db_name
LOCK_DSN=flock
###< symfony/lock ###

0
chadyred On

It seems extension (module) PHP is missing.

I have this error too and when I read the installation doc of the PHP library behind here : https://www.php.net/manual/en/sem.installation.php

To enable System V semaphore support compile PHP with the option --enable-sysvsem. To enable the System V shared memory support compile PHP with the option --enable-sysvshm. To enable the System V messages support compile PHP with the option --enable-sysvmsg.

As I use a docker image, then I added this extension in a Dockerfile on the php image like

RUN docker-php-ext-install sysvmsg sysvsem sysvshm

Don't forget to run docker compose build or a docker build on the Dockerfile directory and it works.

With Symfony a simple test could be :

<?php

declare(strict_types=1);

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\SemaphoreStore;

#[AsCommand('app:test:lock')]
class LockCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $store = new SemaphoreStore();
        $lockFactory = new LockFactory($store);

        $lock = $lockFactory->createLock('my-lock-on-shared-memory');

        $i = 0;
        while($i < 1000) {
            sleep(1);
            if ($lock->acquire()){
                $output->writeln('Got the lock :)');
            } else {
                $output->writeln('It seems the lock is already acquire by another process...');
            }
            
            $i++;
        }

        return self::SUCCESS;
    }
}

It important to run on the same PHP container / process.

Run the first with the "&" at the end of the command like bin/console app:test:lock & to be able to run directly a second command bin/console app:test:lock

You will see that all works fine.