Authentification dans Slim: une approche combinée middleware, singleton et hook est-elle intelligente?

j'ai écrit mon propre contrôleur d'authentification pour authentifier l'utilisateur dans mon Slim application. Bien que cela fonctionne, Je ne sais pas si C'est la façon dont Slim est censé fonctionner.

Mon contrôleur d'authentification $auth a des méthodes comme $auth->login($user, $password) et $auth->logout() qui changent l'état de la session et les méthodes de l'état, tels que $auth->userIsLoggedIn(). Aussi, en raison d'une demande, il peut déterminer si un utilisateur a accès à la route.

actuellement, j'utilise une seule instance de $auth dans mon application Slim de deux façons différentes: comme un singleton enregistré à $app->auth, et comme middleware de route qui est appliqué à toutes les routes. Ainsi, le Slim application est démarré comme ceci:

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

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

j'utilise l'instance singleton de l'intérieur de mes routes, par exemple, dans la route login:

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

Et je suis en utilisant la version de middleware dans toutes les voies de fixer une méthode pour l' slim.before.dispatch crochet qui vérifie que l'utilisateur est authentifié et redirige vers la page de connexion autrement. Pour ce faire, le wrapper d'authentification étend SlimMiddleware et implémente ainsi le call méthode, comme ceci (simplifié):

class MyAuthenticationWrapper extends SlimMiddleware
{
    // ... 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();
    }
}

utiliser un singleton est un léger odeur de code pour moi, mais l'ajout de l'instance du singleton en tant que middleware $app->add( $app->auth ) se sent tout simplement sale. Et finalement, l'utilisation de l'middleware pour enregistrer une fermeture au crochet de répartition me fait me demander si toute cette stratégie n'est pas trop compliqué pour un cadre appelé Slim. Mais je ne sais pas s'il y a une façon plus facile ou plus élégante d'accomplir ce que je veux.

la question: suis-je sur la bonne voie, ou est-ce que je manque quelque chose au sujet du fonctionnement de Slim qui me permettrait d'accomplir ceci d'une manière moins complexe?

9
demandé sur Wilbo Baggins 2014-09-30 00:55:31

1 réponses

vous êtes absolument sur la bonne voie en utilisant Middleware pour enregistrer un crochet pour authentification. C'est l'approche que j'adopte et l'approche que j'ai mise en œuvre dans ma propre bibliothèque, Slim Auth.

en utilisant un Singleton peut certainement être une odeur de code, mais n'est pas toujours. Si vous ressentez le besoin de reformuler mon brouilleur D'authentification, c'est entièrement à vous de le faire. La façon dont vous utilisez Middleware et crochets avec votre classe personnalisée est, IMHO, 100% Sur cible.

note de Côté: l'Une de mes devises est "le Faire fonctionner, alors refactoriser."On dirait que vous êtes sur la bonne voie là aussi, alors bravo.

Enfin, l'authentification et l'autorisation sont des sujets complexes nécessitant des solutions complexes. Complexe n signifie des spaghettis alambiqués, difficiles à entretenir, mais le faire correctement peut entraîner plus de code que ce que j'espérais écrire (ou plus de dépendances que ce que j'espérais tirer dans via Compositeur.)

UPDATE

Si $app->auth Middleware, alors oui, vous êtes hors piste un peu. Votre instinct pour créer Middleware pour enregistrer un crochet est mort sur, mais Middleware est Middleware et ne devrait pas être utilisé en dehors de ce contexte. Idéalement, vous devriez créer (ou mieux encore trouver un paquet sur Packagist) une classe auth que vous pouvez utiliser à la fois dans vos routes et dans votre Middleware. Le Pseudo-code ressemblerait à quelque chose comme:

$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();
    }
}

Voici un exemple Middleware de Slim Auth. J'ai mis en place un exemple de mise en oeuvre vous pouvez regarder pour voir comment mettre tout cela ensemble.

6
répondu Jeremy Kendall 2014-09-30 23:05:24