Comment programmer avec Yii2 Contrôles d'accès utilisateur

Ce que vous allez créer

Si vous demandez, "Qu'est-ce que Yii?" Découvrez mon tutoriel précédent: Introduction au framework Yii, qui passe en revue les avantages de Yii et inclut un aperçu des nouveautés de Yii 2.0, publiées en octobre 2014.

Dans cette série de programmation avec Yii2, je guide les lecteurs dans l'utilisation du framework Yii2 pour PHP récemment mis à jour. 

Dans la première partie, nous avons configuré Yii2 localement, créé une application Hello World, configuré un serveur distant et utilisé Github pour déployer notre code. Dans la deuxième partie, nous avons appris comment Yii avait implémenté son architecture Model View Controller et expliqué comment créer des pages Web et des formulaires permettant de collecter et de valider des données.. 

Dans la troisième partie, nous avons utilisé les fonctionnalités de base de données et d'enregistrement actif de Yii pour automatiser la génération de code pour une application Web de base. Dans la quatrième partie, nous avons appris à intégrer l'enregistrement des utilisateurs. Et dans la cinquième partie, nous avons exploré la localisation avec I18n pour préparer votre application aux utilisateurs mondiaux.. 

Dans ce tutoriel, je vais vous montrer comment implémenter des contrôles d'accès pour vous assurer que seuls les bons utilisateurs peuvent accéder aux parties de notre application que nous leur souhaitons..

Pour ces exemples, nous allons continuer à imaginer que nous construisons un cadre pour la publication de mises à jour de statut simples, par exemple. notre propre mini-Twitter.

Juste un rappel, je participe aux commentaires ci-dessous. Je suis particulièrement intéressé si vous avez des approches différentes, des idées supplémentaires ou si vous souhaitez suggérer des sujets pour de futurs tutoriels..

Qu'est-ce que le contrôle d'accès??

Le contrôle d'accès s'intègre aux fonctionnalités d'authentification de la structure pour autoriser ou restreindre l'accès à des fonctionnalités ou à des pages spécifiques de votre site Web.. 

Le code que nous avons écrit jusqu'à présent permet à quiconque de créer des publications, même s'il n'est pas connecté. Par exemple, dans notre exemple d'application, vous pouvez visiter la page Statut et publier des éléments sans vous connecter.. 

Nous pouvons utiliser les fonctionnalités simples de contrôle d'accès de Yii2 pour nous assurer que les utilisateurs s'enregistrent et se connectent avant d'ajouter et d'afficher des messages d'état.. 

Yii2 propose également un contrôle d'accès basé sur le rôle (RBAC) plus avancé (et complexe) que nous ne mettrons pas en œuvre pour le moment. Avec RBAC, vous définissez une hiérarchie sophistiquée d'autorisations pour chaque activité possible dans votre application..

Le contrôle d'accès intégré à Yii2 ne prend en charge que deux rôles par défaut: invité (non connecté), représenté par '?', Et authentifié, représenté par '@'. Avec des contrôles d'accès simples, nous pouvons simplement limiter l'accès à des pages spécifiques ou aux actions du contrôleur en fonction de l'état de connexion. Si les utilisateurs ne sont pas connectés lorsqu'ils visitent les pages de lieu, Yii les redirigera vers la page de connexion..

Dans ce tutoriel, je vais vous expliquer comment utiliser les contrôles d'accès simples de Yii2 pour notre exemple d'application. Ensuite, nous étendrons l’accès simple à des rôles supplémentaires tels que modérateur et administrateur..

Implémentation de contrôles d'accès simples

Actuellement, notre application permet d’accéder à StatusController même sans se connecter..

Le cadre facilite la mise en œuvre de ces contrôles. Nous ajoutons simplement des comportements au StatusController.php qui définissent les règles d’accès pour chaque action, par exemple. indexer, créer, voir, etc.. 

Nous examinerons ici le comportement d'accès, mais si cela vous intéresse, les filtres de verbe de Yii vous permettent de restreindre les opérations de requête http en fonction de l'action de votre contrôleur..

fonction publique comportements () return ['verbs' => ['class' => VerbFilter :: className (), 'actions' => ['delete' => ['post'],],], 'accès' => ['class' => \ yii \ filters \ AccessControl :: className (), 'only' => ['index', 'create', 'update', 'view'], 'rules' => [/ / autoriser les utilisateurs authentifiés ['autoriser' => vrai, 'rôles' => ['@'],], // tout le reste est refusé],],]; 

Une fois ajouté, si vous cliquez sur le Statut menu, vous serez redirigé vers la page de connexion:

Yii gère également la redirection vers la page d'index d'état une fois la connexion établie..

Ajout de la propriété du modèle

Maintenant, lorsque les utilisateurs accèdent aux pages d'état, nous pouvons trouver l'utilisateur actuel avec ce code:

Yii :: $ app-> user-> getId ();

Et nous pouvons associer les postes de statut à leur créateur dans le modèle.

Pour ce faire, nous devons étendre la table Status avec une nouvelle migration de table:

./ yii migrate / create extend_status_table_for_created_by Yii Outil de migration (basé sur Yii v2.0.1) Créer une nouvelle migration '/Users/Jeff/Sites/hello/migrations/m150128_003709_extend_status_table_for_created_by.php'? (oui | non) [non]: oui Nouvelle migration créée avec succès.

Voici le code de migration qui ajoute une colonne pour créé par. Nous ajoutons également une clé étrangère pour créer une relation entre le Statut-> created_by terrain et Utilisateur-> id table.

db-> nomDuPort === 'mysql') $ tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> addColumn ('% status', 'created_by', Schema :: TYPE_INTEGER. 'NOT NULL'); $ this-> addForeignKey ('fk_status_created_by', '% status', 'created_by', '% user', 'id', 'CASCADE', 'CASCADE');  public function down () $ this-> dropForeignKey ('fk_status_created_by', '% status'); $ this-> dropColumn ('% status', 'created_by');  

Lançons la migration:

./ yii migrate / up Yii Outil de migration (basé sur Yii v2.0.1) Total 1 nouvelle migration à appliquer: m150128_003709_extend_status_table_for_created_by Appliquer la migration ci-dessus? (yes | no) [no]: yes *** application de m150128_003709_extend_status_table_for_created_by> ajouter une colonne created_by entier NOT NULL à la table % status… done (heure: 0.009s)> ajouter une clé étrangère fk_status_created_by: % status (created_by) références % user (id)… terminé (heure: 0,007s) *** appliqué m150128_003709_extend_status_table_for_created_by (heure: 0.020s) Migration réussie.

J'ai relancé la génération de code Gii avec la nouvelle table Status, puis copié et collé les nouveaux éléments supplémentaires. La plupart étaient mineurs, mais vous remarquerez qu'il ajoute une nouvelle requête ActiveQuery à la relation:

 / ** * @return \ yii \ db \ ActiveQuery * / fonction publique getCreatedBy () return $ this-> hasOne (User :: className (), ['id' => 'created_by']);  

Donc, juste avant que les nouveaux éléments d’état soient sauvegardés, nous pouvons mettre à jour le créé par champ à l'utilisateur actuellement connecté. Et nous pouvons faire confiance aux contrôles d’accès pour assurer la créer Cette méthode est accessible uniquement aux utilisateurs authentifiés:

fonction publique actionCreate () $ model = new Status (); if ($ model-> load (Yii :: $ app-> request-> post ())) $ model-> created_by = Yii :: $ app-> user-> getId (); $ model-> created_at = time (); $ model-> updated_at = time (); if ($ model-> save ()) return $ this-> redirect (['view', 'id' => $ model-> id]);  return $ this-> render ('create', ['model' => $ model,]); 

Nous allons également étendre le widget de vue pour inclure le créé par champ:

  $ modèle, 'attributs' => ['id', 'message: ntext', 'created_by', 'permissions', 'created_at', 'updated_at',],])?>

Nous pouvons aussi utiliser le créé par relation pour afficher l'adresse email:

  $ modèle, 'attributs' => ['id', 'createdBy.email', 'message: ntext', 'permissions', 'created_at', 'updated_at',],])?> 

le createdBy.email accède au Status :: getCreatedBy méthode de la relation. Ceci affiche l'adresse email de l'utilisateur:

Cependant, afin de prendre en charge cette fonctionnalité avec l'extension Yii2-user que nous avons implémentée dans la quatrième partie, nous avons dû apporter deux modifications. Tout d'abord, dans notre app \ config \ web.php tableau de configuration, nous avons ajouté un remplacement de modèle à app \ models \ User.php:

… 'User' => ['class' => 'dektrium \ user \ Module', 'enableUnconfirmedLogin' => true, 'confirmWithin' => 21600, 'cost' => 12, 'modelMap' => ['Utilisateur' => 'app \ models \ user',], 'admins' => ['admin']], 

Nous avons également créé ce modèle en app \ modèles:

Ces deux changements apportent un soutien à la relation.

Extension des contrôles d'accès simples

Et si nous voulions avoir une capacité supplémentaire autour des actions du contrôleur? Par exemple, que se passe-t-il si nous voulons limiter les opérations de suppression aux modérateurs ou aux administrateurs? Le contrôle d'accès simple de Yii2 n'a pas de concept de modérateur ou d'administrateur, sauf si vous en créez un avec RBAC..

Notez que l'extension Yii2-user a un identifiant d'administrateur pour des utilisateurs spécifiques, mais manque également de flexibilité pour des rôles supplémentaires..

Code Ninja a donné un bon exemple d'extension des contrôles d'accès simples afin de prendre en charge les modérateurs et les administrateurs (autorisation simplifiée basée sur les rôles dans Yii 2.0) sans avoir à recourir à RBAC. Leur exemple fonctionne avec le modèle d'application avancée Yii2. 

Notre application est différente car nous utilisons le modèle d'application de base de Yii et nous utilisons l'extension Yii2-user. Par conséquent, j'ai apporté quelques modifications à leur guide:

Tout d'abord, nous créons un app \ composants répertoire et et un AccessRule.php fichier qui étend intégré de Yii Règle d'accès modèle:

rôles)) return true;  foreach ($ this-> rôles as $ role) if ($ role == '?') if ($ user-> getIsGuest ()) return true;  elseif ($ role == User :: ROLE_USER) if (! $ user-> getIsGuest ()) return true;  // Vérifie si l'utilisateur est connecté et que les rôles correspondent elseif (! $ User-> getIsGuest () && $ role == $ user-> identity-> role) return true;  return false; 

Ensuite, nous ajoutons des définitions de rôle à notre app \ modèles \ utilisateur modèle:

Yii2-utilisateur n'implémente pas la colonne de rôle lors de la création de nouveaux utilisateurs. Vous pouvez donc spécifier manuellement les rôles des modérateurs et des administrateurs dans MySQL ou créer ultérieurement votre propre interface utilisateur Web pour l'attribution des rôles..

Dans vendor \ dektrium \ yii2-user \ models \ RegistrationForm.php, J'ai ajouté cette ligne pour définir le rôle d'utilisateur pour les utilisateurs par défaut:

Remarque: vous devrez effectuer cette modification manuellement si vous le souhaitez car mon répertoire des fournisseurs n'est pas archivé dans notre arborescence GitHub. Et oui, il existe probablement un moyen plus élégant de le faire dans la base de code après l'enregistrement. , par exemple étendre la méthode createUser dans app / models / User.php. La meilleure pratique peut être de bifurquer le référentiel de fournisseurs et de le placer dans votre propre arborescence de codes..

** * Enregistre un nouveau compte utilisateur. * @return bool * / public function register () if ($ this-> validate ()) $ user = $ this-> module-> manager-> createUser (['scenario' => 'register', 'email '=> $ this-> email,' nom d'utilisateur '=> $ this-> nom d'utilisateur,' password '=> $ this-> mot de passe,' role '=> 10, // utilisateur :: ROLE_USER;]); return $ user-> register ();  return false; 

Enfin, dans StatusController.php, nous ajoutons quelques bibliothèques et ces définitions d'accès. Dans l'exemple ci-dessous, les actions de mise à jour sont réservées aux modérateurs et les actions de suppression aux administrateurs..

 ['class' => VerbFilter :: className (), 'actions' => ['delete' => ['post'],],], 'access' => ['class' => AccessControl :: className ( ), // Nous allons remplacer la configuration de règle par défaut par la nouvelle classe AccessRule 'ruleConfig' => ['class' => AccessRule :: className (),], 'only' => ['index', 'create', 'update', 'delete'], 'rules' => [['' actions '=> [' index ',' create '],' allow '=> true, // Autorise les utilisateurs, modérateurs et administrateurs à créer des' rôles ' '=> [Utilisateur :: ROLE_USER, Utilisateur :: ROLE_MODERATOR, Utilisateur :: ROLE_ADMIN],], [' actions '=> [' update '],' allow '=> true, // Autorise les modérateurs et les administrateurs à mettre à jour' roles '=> [Utilisateur :: ROLE_MODERATOR, Utilisateur :: ROLE_ADMIN],], [' actions '=> [' supprimer '],' autoriser '=> vrai, // Autoriser les administrateurs à supprimer' rôles '=> [Utilisateur :: ROLE_ADMIN],],],],]; 

Maintenant, quand vous vous déconnectez et visitez le Statut page de la barre de navigation, vous serez redirigé vers l’écran de connexion:

Lorsque vous vous connectez, vous revenez à la vue index:

Cependant, si je clique Effacer, Je vais obtenir cette erreur d'accès interdit, car je suis un utilisateur modeste, et non un administrateur:

Si vous souhaitez devenir administrateur, vous pouvez le faire dans la base de données en modifiant la colonne de rôle de la table User pour votre user_id en 20 pour le modérateur et 30 pour en tant qu'administrateur. Essayez les opérations de mise à jour et de suppression à nouveau et vous serez autorisé en fonction du rôle que vous avez choisi.

Les contrôles d'accès sont l'une des nombreuses fonctionnalités qui font de moi un ardent défenseur de l'utilisation du framework Yii. Yii fait de moi un développeur beaucoup plus efficace, capable de fournir des solutions beaucoup plus rapidement que je ne le peux avec PHP vanilla.

Et après?

Surveillez les prochains tutoriels de ma série Programming With Yii2 pendant que je continue à plonger dans différents aspects du cadre. Vous pouvez également consulter ma série Construire votre démarrage avec PHP, qui utilise le modèle avancé de Yii2 pour créer une application du monde réel..

Si vous souhaitez savoir quand le prochain tutoriel Yii2 arrive, suivez-moi @reifman sur Twitter ou consultez ma page d'instructeur. Ma page d'instructeur comprendra tous les articles de cette série dès leur publication. Vous pouvez également m'envoyer un email sur mon site web Lookahead Consulting.

Liens connexes

  • Yii Framework Site
  • Introduction au framework Yii (Tuts +)
  • Yii2 Developer Exchange, mon site de ressources Yii2