Аутентификация в Slim: разумно ли использовать комбинированное промежуточное ПО, синглтон и хук?

Я написал свой собственный контроллер аутентификации для выполнения аутентификации пользователя в моем приложении Slim. Хотя это работает, я не уверен, что именно так Слим предназначен для работы.

Мой контроллер аутентификации $auth имеет такие методы, как $auth->login($user, $password) а также $auth->logout() которые изменяют состояние сеанса и методы, которые сообщают о состоянии, такие как $auth->userIsLoggedIn(), Кроме того, по запросу он может определить, есть ли у пользователя доступ к запрошенному маршруту.

В настоящее время я использую один экземпляр $auth в моем приложении Slim двумя различными способами: в качестве зарегистрированного $app->authи как промежуточное ПО маршрутов, которое применяется ко всем маршрутам. Итак, приложение Slim загружается так:

// Create singleton instance of MyAuthWrapper
$app->auth = new MyAuthenticationWrapper( array() );

// Attach the same instance as middleware to all routes
$app->add( $app->auth );

Я использую экземпляр singleton из моих маршрутов, например, в маршруте входа в систему:

$app->post( '/login', function() use ($app)
{
// ...
$user = $app->auth->authenticate( $app->request()->post('username'), $app->request()->post('password') );
// ...
}

И я использую версию промежуточного программного обеспечения на всех маршрутах, прикрепляя метод к slim.before.dispatch хук, который проверяет, что пользователь аутентифицирован, и перенаправляет на страницу входа в противном случае. Для этого оболочка аутентификации расширяет \ Slim \ Middleware и, таким образом, реализует call метод, как это (упрощенно):

class MyAuthenticationWrapper extends \Slim\Middleware
{
// ... Implementation of methods such as authenticate(), isLoggedIn(), logout(), etc.

public function call()
{
$app = $this->app;

$isAuthorized = function () use ($app) {

$hasIdentity = $this->userIsLoggedIn(); // Assume this to work
$isAllowed = $this->userHasAccessToRequestedRoute(); // Assume this to work

if ($hasIdentity && !$isAllowed)
{
throw new Exception("You have no access to this route");
}

if (!$hasIdentity && !$isAllowed)
{
return $app->redirect( $loginPath );
}
};

$app->hook('slim.before.dispatch', $isAuthorized);

$this->next->call();
}
}

Использование синглтона является небольшим запах кода для меня, но затем добавив экземпляр Singleton в качестве промежуточного программного обеспечения с $app->add( $app->auth ) чувствует себя просто грязно И, наконец, использование промежуточного программного обеспечения для регистрации замыкания в диспетчерском хуке заставляет задуматься, не слишком ли сложна вся эта стратегия для платформы под названием Slim. Но я не могу понять, есть ли более простой или более элегантный способ выполнить то, что я хочу.

Вопрос: Я на правильном пути, или я что-то упускаю из-за того, как работает Слим, что позволило бы мне сделать это менее сложным способом?

9

Решение

Вы абсолютно на правильном пути, используя Middleware, чтобы зарегистрировать хук для аутентификации. Это подход, который я использую, и подход, который я реализовал в своей собственной библиотеке, Slim Auth.

Используя одиночка может определенно быть запахом кода, но не всегда. Если вы чувствуете, что вам нужно реорганизовать MyAuthenticationWrapper, это полностью ваше дело. То, как вы используете Middleware и Hooks со своим пользовательским классом, на мой взгляд, 100% на цели.

Примечание: один из моих девизов: «Сделай так, чтобы потом работал рефакторинг». Похоже, вы тоже на трассе, так что слава.

Наконец, аутентификация и авторизация являются сложными темами, требующими сложных решений. Комплекс делает не Я имею в виду извилистые, трудно поддерживаемые спагетти, но их правильное использование может привести к большему количеству кода, чем я надеялся написать (или большему количеству зависимостей, чем я надеялся получить через Composer).

ОБНОВИТЬ

Если $app->auth это Middleware, тогда да, вы немного не в курсе. Ваш инстинкт создания Middleware для регистрации ловушки мертв, но Middleware является Middleware и не должен использоваться вне этого контекста. В идеале вы должны создать (или еще лучше найти пакет на Packagist) класс аутентификации, который вы можете использовать как в своих маршрутах, так и в промежуточном программном обеспечении. Псевдокод будет выглядеть примерно так:

$auth = new Auth(); // This is *not* middleware
$app->auth = $auth;

// Login route looks the same

// Middleware
class MyAuthenticationWrapper extends \Slim\Middleware
{
public function call()
{
$app = $this->app;
$auth = $app->auth;

// Register your hook using appropriate methods from Auth class ...

$this->next->call();
}
}

Вот пример Middleware от Slim Auth. Я собрал пример реализации Вы можете посмотреть, как я все это собрал.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]