Hur man programmerar med Yii2 Kontroller för användaråtkomst

Vad du ska skapa

Om du frågar, "Vad är Yii?" kolla in min tidigare handledning: Introduktion till Yii Framework, som granskar fördelarna med Yii och innehåller en översikt över vad som är nytt i Yii 2.0, släppt i oktober 2014.

I denna programmering med Yii2-serien guidar jag läsare som använder den nyuppgraderade Yii2 Framework for PHP. 

I del ett startade vi Yii2 lokalt, byggde ett Hello World-program, satte upp en fjärrserver och använde Github för att distribuera vår kod. I del två lärde vi oss om Yii: s genomförande av sin Model View Controller-arkitektur och hur man bygger webbsidor och formulär som samlar in och validerar data. 

I del tre använde vi Yiis databas och aktiva rekordmöjligheter för att automatisera kodgenerering för en grundläggande webbapplikation. I del fyra lärde vi oss att integrera användarregistrering. Och i del fem undersökte vi lokalisering med I18n för att förbereda din ansökan för globala användare. 

I den här handledningen kommer jag att visa dig hur du implementerar åtkomstkontroller för att säkerställa att bara de rätta användarna kan komma åt de delar av vår ansökan som vi önskar dem att.

För dessa exempel fortsätter vi att föreställa oss att vi bygger ett ramverk för att skicka enkla statusuppdateringar, t.ex. vår egen mini-Twitter.

Bara en påminnelse, jag deltar i kommentera trådarna nedan. Jag är särskilt intresserad om du har olika tillvägagångssätt, ytterligare idéer, eller vill föreslå ämnen för framtida handledning.

Vad är åtkomstkontroll?

Access Control integreras med ramens autentiseringsfunktioner för att tillåta eller begränsa åtkomst till specifika funktioner eller sidor på din webbplats. 

Koden som vi hittills har skrivit gör det möjligt för någon att skapa inlägg även om de inte har loggat in. Till exempel i vår programprogram kan du besöka statussidan och posta objekt utan att logga in. 

Vi kan använda Yii2s enkla åtkomstkontrollfunktioner för att säkerställa att användarna registrerar och inloggar innan de lägger till och tittar på statusposter. 

Yii2 erbjuder också mer avancerad (och komplex) rollbaserad åtkomstkontroll (RBAC) som vi inte kommer att genomföra vid denna tidpunkt. Med RBAC definierar du en sofistikerad hierarki av behörigheter för varje möjlig aktivitet inom din ansökan.

Yii2 är inbyggd i Access Control stöder endast två roller som standard: gäst (inte inloggad), representerad av '?' Och autentiserad, representerad av '@'. Med enkla åtkomstkontroller kan vi bara begränsa åtkomsten till specifika sidor eller kontrolleråtgärder baserat på inloggningsstaten. Om användarna inte är inloggade när de besöker platssidorna kommer Yii att omdirigera dem till inloggningssidan.

I den här handledningen presenterar jag dig för att använda Yii2s enkla åtkomstkontroller för vår provprogram. Då utökar vi enkel åtkomst med ytterligare roller som moderator och administratör.

Genomföra enkla åtkomstkontroller

För närvarande tillåter vår applikation tillgång till StatusController även utan att logga in. Låt oss fixa det.

Ramverket gör det ganska enkelt att genomföra dessa kontroller. Vi lägger bara till beteenden till StatusController.php som definierar åtkomstreglerna för varje åtgärd, t.ex. index, skapa, visa, etc.. 

Här granskar vi åtkomstbeteendet, men om du är intresserad kan Yii-verbsfilter låta dig begränsa begäran om HTTP-förfrågningar baserat på din kontrolleråtgärd.

(funktionen) => ['class' => \ yii \ filters \ AccessControl :: className (), 'only' => ['index', 'skapa', 'uppdatera', 'visa'], 'regler' => [/ / tillåta autentiserade användare ['allow' => true, 'roller' => ['@'],], // allt annat nekas],],]; 

En gång till, om du klickar på Status menyn kommer du att dirigeras till inloggningssidan:

Yii hanterar också omdirigeringen tillbaka till Statusindex-sidan när inloggningen är klar.

Lägger till modellägarskap

Nu när användare får tillgång till statussidorna kan vi hitta den nuvarande användaren med den här koden:

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

Och vi kan associera statusposter med deras skapare i modellen.

För att kunna göra detta måste vi förlänga statustabellen med en ny tabellmigration:

./ yii migrera / skapa extend_status_table_for_created_by Yii Migration Tool (baserat på Yii v2.0.1) Skapa ny migrering "/Users/Jeff/Sites/hello/migrations/m150128_003709_extend_status_table_for_created_by.php '? (ja | nej) [nej]: ja Ny migrering skapades framgångsrikt.

Här är migreringskoden som lägger till en kolumn för skapad av. Vi lägger också till en utländsk nyckel för att skapa en relation mellan Status-> created_by fält och User-> id tabell.

db-> drivrutinName === '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');  offentlig funktion ner () $ this-> dropForeignKey ('fk_status_created_by', '% status'); $ This-> dropColumn ( '% status', 'created_by');  

Låt oss köra migreringen:

./ yii migrera / upp Yii Migrationsverktyg (baserat på Yii v2.0.1) Totalt 1 ny migration som ska tillämpas: m150128_003709_extend_status_table_for_created_by Använd ovanstående migrering? (ja | nej) nej: ja *** tillämpa m150128_003709_extend_status_table_for_created_by> lägg till kolumn created_by heltal NOT NULL till tabell % status ... done (tid: 0.009s)> lägg till främmande nyckel fk_status_created_by: % status (created_by) referenser % user (id) ... gjort (tid: 0.007s) *** tillämpas m150128_003709_extend_status_table_for_created_by (tid: 0.020s) Migrerad framgångsrikt.

Jag körde igen Gii-kodgenerationen med den nya statustabellen och kopierade och klistrade in de nya ytterligare elementen. De flesta var mindre men du märker att den lägger till en ny ActiveQuery för relationen:

 / ** * @return \ yii \ db \ ActiveQuery * / allmän funktion getCreatedBy () return $ this-> hasOne (Användare :: klassnamn (), ['id' => 'created_by']);  

Så, precis innan nya statusobjekt sparas kan vi uppdatera skapad av fältet till den för närvarande inloggade användaren. Och vi kan lita på åtkomstkontroll för att säkerställa skapa Metoden är endast tillgänglig av autentiserade användare:

public function actionCreate () $ model = ny status (); om ($ model-> load (Yii :: $ app-> request-> post ())) $ model-> created_by = Yii :: $ app-> user-> getId (); $ model-> created_at = time (); $ model-> updated_at = time (); om ($ model-> save ()) return $ this-> omdirigera (['view', 'id' => $ model-> id]);  returnera $ this-> render ('create', ['model' => $ modell,]); 

Vi utvidgar även visningsgränsen för att inkludera skapad av fält:

  $ model, attributes = = ['id', 'message: ntext', 'created_by', 'permissions', 'created_at', 'updated_at',],])

Vi kan också använda skapad av relation med att visa e-postadressen:

  $ model, attributes = = ['id', 'createdBy.email', 'message: ntext', 'permissions', 'created_at', 'updated_at',],]) 

De createdBy.email åtkomst till Status :: getCreatedBy relation metod. Detta visar användarens e-postadress:

För att kunna stödja denna förmåga med Yii2-användarutbyggnaden som vi genomförde i del fyra, var vi tvungna att göra två modifieringar. Först i vår app \ config \ web.php konfigurationsmatris, lade vi till en modellöverstyrning till App \ modeller \ user.php:

... 'user' => '' dektrium \ user \ Modul ',' enableUnconfirmedLogin '=> true,' confirmWithin '=> 21600,' kostnad '=> 12,' modelMap '=> [' Användare ' => 'app \ models \ User',], 'admins' => ['admin']], 

Vi skapade också denna modell i App \ modeller:

Dessa två förändringar gav stöd för relationen.

Utöka enkla åtkomstkontroller

Vad händer om vi ville ha ytterligare kapacitet kring kontrolleråtgärder? Till exempel, om vi vill begränsa raderingsoperationer till moderatorer eller administratörer? Yii2s enkla åtkomstkontroll har inget moderator eller administratörskoncept om du inte skapar en med RBAC.

Observera att Yii2-användarens tillägg har en administratörsidentifiering för specifika användare, men det saknar också flexibiliteten för ytterligare roller.

Code Ninja skrev ett bra exempel på att utöka enkla åtkomstkontroller för att stödja moderatorer och administratörer (enklare rollbaserad auktorisation i Yii 2.0) utan att behöva tillgripa RBAC. Deras exempel fungerar med Yii2 avancerad applikationsmall. 

Vår ansökan är annorlunda genom att vi använder Yii grundläggande applikationsmall och vi använder Yii2-användarutvidgningen. Därför har jag gjort några ändringar i deras guide:

Först skapar vi en appen \ components katalog och och en AccessRule.php fil som utökar Yiis inbyggda AccessRule modell:

roller)) return true;  foreach ($ this-> roller som $ roll) if ($ role == '?') if ($ user-> getIsGuest ()) return true;  elseif ($ role == Användare :: ROLE_USER) if (! $ user-> getIsGuest ()) return true;  // Kontrollera om användaren är inloggad och rollerna matchar elseif (! $ User-> getIsGuest () && $ role == $ användar-> identitet-> roll) return true;  returnera false; 

Sedan lägger vi till rolldefinitioner till vår app \ modeller \ Användare modell:

Yii2-användare Implementerar inte rollkolumnen när du skapar nya användare. Så du kan antingen ange roller för moderatorer och administratörer manuellt i MySQL eller senare bygga ditt eget användargränssnitt för att ge roller.

I leverantör \ dektrium \ yii2 användare \ modeller \ RegistrationForm.php, Jag lade till den här raden för att definiera användarrollen för standardanvändare:

Obs! Du måste göra den här ändringen manuellt om du vill ha det eftersom min leverantörskatalog inte får checkas in i vårt GitHub-träd - och det är säkert en mer elegant sätt att göra detta i kärnkodsbasen efter registreringen , t.ex förlänga createUser-metoden i app / models / User.php. Bästa praxis kan vara att gaffla försäljningsförvaret och ta med det i ditt eget kodträd.

** * Registrerar ett nytt användarkonto. * @return bool * / public function register () if ($ this-> validate ()) $ user = $ this-> module-> manager-> createUser (['scenario' => 'register' '=> $ this-> email,' användarnamn '=> $ this-> användarnamn,' lösenord '=> $ this-> lösenord,' roll '=> 10, // Användare :: ROLE_USER;]); returnera $ user-> register ();  returnera false; 

Slutligen, i StatusController.php, Vi lägger till några bibliotek och dessa åtkomstdefinitioner. I exemplet nedan är uppdateringsåtgärder begränsade till moderatorer och raderingsåtgärder är begränsade till administratörer.

 ['class' => VerbFilter :: className (), 'actions' => ['delete' => ['post'],],], 'access' => ['class' => AccessControl :: className ), // Vi kommer att åsidosätta standardregeln config med den nya AccessRule-klassen ruleConfig '=> [' class '=> AccessRule :: className (),],' only '=> [' index ',' create ' 'uppdatera', 'ta bort'], 'regler' => [['actions' => ['index', 'skapa'], 'tillåta' => true // Tillåt användare, moderatorer och administratörer att skapa roller '=> [Användare :: ROLE_USER, Användare :: ROLE_MODERATOR, Användare :: ROLE_ADMIN],], [' actions '=> [' update '],' allow '=> true, // Tillåt moderatorer och administratörer att uppdatera' roles '=> [Användare :: ROLE_MODERATOR, Användare :: ROLE_ADMIN],], [' actions '=> [' delete '],' allow '=> true, // tillåta administratörer att ta bort' roller '=> :: ROLE_ADMIN],],],],]; 

Nu när du loggar ut och besöker Status sida från navigeringsfältet, kommer du till inloggningsskärmen:

När du loggar in skickas du till indexvisningen igen:

Men om jag klickar på Radera, Jag kommer att få detta åtkomst förbjudna fel - för att jag är en låg användare, inte en administratör:

Om du vill höja dig själv till administratören kan du göra det i databasen, ändra användartabellens rollkolumn för din user_id till 20 för moderator och 30 för admin. Prova uppdateringen och radera operationerna igen och du kommer att tillåtas beroende på din valda roll.

Åtkomstkontroll är en av de många funktionerna som gör mig till en stor förespråkare för att använda Yii Framework. Yii gör mig till en mycket effektivare utvecklare, som kan leverera lösningar mycket snabbare än jag kan med vanilj PHP.

Vad kommer härnäst?

Titta på kommande handledningar i min programmering med Yii2-serien när jag fortsätter att dyka in i olika aspekter av ramen. Du kanske också vill kolla in min Building Your Startup With PHP-serie, som använder Yii2s avancerade mall när jag bygger en verklig världsapplikation.

Om du vill veta när nästa Yii2 handledning kommer, följ mig @ reifman på Twitter eller kolla min instruktörssida. Min instruktörssida kommer att innehålla alla artiklar från denna serie så snart de publiceras. Du kan också maila mig på min Lookahead Consulting webbplats.

relaterade länkar

  • Yii Framework Website
  • Introduktion till Yii Framework (Tuts +)
  • Yii2 Developer Exchange, min Yii2 resurs webbplats