Авторизация и ограничение доступа в Symfony framework (Урок 14)

Итак, в этой заметке мы научимся ограничивать доступ к разделам сайта, написанного с использованием Symfony framework. Symfony framework предоставляет мощные средства для контроля доступа, которые позволяют ограничивать доступ как по url, так и целым контроллерам.

Если вы путаетесь в понятиях аутентификация, идентификация и авторизация, советую для начала прочитать это.

Сначала немного теории.

То, что нам необходимо, делается с помощью конфигурационного файла (yaml по умолчанию, app/config/security.yml).

Когда пользователь делает запрос до защищенного с помощью firewall url, активируется система защиты.

 

Процесс аутентификации/авторизации в Symfony framework
Процесс аутентификации/авторизации в Symfony framework

 

Система сначала определяет, нужна ли аутентификация, если да - тогда возвращает ответ пользователю, инициирующий процесс аутентификации. После введения данных проверяется наличие пользователя, его права, и, если их достаточно, возвращается изначально запрашиваемая страница.

Информация о пользователях может находится как в конфигурационном файле (app/config/security.yml) (если у вас 1-2 пользователя, включая админа - сойдет =)) или в базе данных (если у вас сложная многопользовательская система).

Рассмотрим базовый пример:


# app/config/security.yml
security:
    firewalls:
        secured_area:
            pattern: ^/
            anonymous: ~
        form_login:
            login_path: login
            check_path: login_check
    access_control: - { path: ^/admin, roles: ROLE_ADMIN }
    providers: in_memory: memory: users: ryan: { password: ryanpass, roles: 'ROLE_USER' } admin: { password: kitten, roles: 'ROLE_ADMIN' }
    encoders: SymfonyComponentSecurityCoreUserUser: plaintext

 

В секции firewalls мы указали, что система защиты активируется для всех входящих запросов, (pattern задает шаблон url`ов), также в следующей строке мы открыли доступ для неавторизированных пользователей.

Параметры form_login login_path и check_path указывают роуты для формы авторизации и проверки данных (Форма - обычный action контроллера, login_check action в простейшем случае описывать не понадобится).

В следующей секции, access_control, мы снова задали шаблон url, но уже для защищенной части ресурса, и указали, какие типы ("роли" в терминах Symfony framework) пользователей имеют доступ к защищенной части.

Следующая секция позволяет указать источники учетных данных пользователей. У примере - прямо в конфигурационном файле. Учтите, что если пароль начинается из цифр, его нужно взять в кавычки. Так же учтите, что получив доступ к конфигурационному файлу, сторонние лица могут легко узнать ваш пароль.

Для отображения логин формы, необходимо создать для нее роутинг. Например, так:

# app/config/routing.yml
login:
  pattern: /login
  defaults: { _controller: AcmeSecurityBundle:Security:login }
login_check:
  pattern: /login_check

И сам action контроллера (взят с официального руководства по Symfony framework):

// src/Acme/SecurityBundle/Controller/SecurityController.php;
namespace AcmeSecurityBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentSecurityCoreSecurityContext;
class SecurityController extends Controller
{
  public function loginAction()
  {
  $request = $this->getRequest();
  $session = $request->getSession();
  // get the login error if there is one
  if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
   $error = $request->attributes->get(
   SecurityContext::AUTHENTICATION_ERROR
  );
  } else {
   $error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
   $session->remove(SecurityContext::AUTHENTICATION_ERROR);
  }
 return $this->render(
 'AcmeSecurityBundle:Security:login.html.twig',
 array(
 // last username entered by the user
 'last_username' => $session->get(SecurityContext::LAST_USERNAME),
 'error' => $error)
 );
 }
}

И сам шаблон:


{# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #}
{% if error %}
    <div>{{ error.message }}</div>
{% endif %}

<form action="{{ path('login_check') }}" method="post"> 
    <label for="username">Username:</label>
    <input type="text" id="username" name="_username" value="{{ last_username }}" />

    <label for="password">Password:</label>
    <input type="password" id="password" name="_password" />
    
    <button type="submit">login</button>
</form>

Итак, мы научились ограничивать доступ к разделам проекта, написанного на  Symfony framework с помощью конфигурационных файлов. Список пользователей сохраняется в этих же файлах. В следующих заметках научимся, как задействовать для этого БД.