Skip to content

Commit 79d5590

Browse files
committed
nette/security 3.2.4
1 parent d974627 commit 79d5590

6 files changed

Lines changed: 70 additions & 4 deletions

File tree

security/cs/authentication.texy

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ Co je důležité, tak že při odhlášení pomocí `$user->logout()` **se iden
166166

167167
Díky tomu můžete nadále předpokládat, který uživatel je u počítače a například mu v e-shopu zobrazovat personalizované nabídky, nicméně zobrazit mu jeho osobní údaje můžete až po přihlášení.
168168

169+
.{data-version:3.2.4}
170+
Kromě smazání identity u konkrétního volání pomocí `logout(true)` lze její uchovávání vypnout úplně vlastností `$persistIdentity`. Když ji nastavíte na `false`, identita se zahodí při každém odhlášení i při expiraci, takže `getIdentity()` pak vrací `null`. Uchování identity navíc závisí na úložišti: cookie úložiště ji po odhlášení neuchová, protože cookie vždy smaže.
171+
169172
Identita je objekt implementující rozhraní [api:Nette\Security\IIdentity], výchozí implementací je [api:Nette\Security\SimpleIdentity]. A jak bylo zmíněno, udržuje se v session, takže pokud tedy například změníme roli některého z přihlášených uživatelů, zůstanou stará data v jeho identitě až do jeho opětovného přihlášení.
170173

171174

@@ -174,7 +177,7 @@ Identita je objekt implementující rozhraní [api:Nette\Security\IIdentity], v
174177

175178
Dvě základní informace o uživateli, tedy zda-li je přihlášen a jeho [#identita], se zpravidla přenášejí v session. Což lze změnit. Ukládání těchto informací má na starosti objekt implementující rozhraní `Nette\Security\UserStorage`. K dispozici jsou dvě standardní implementace, první přenáší data v session a druhá v cookie. Jde o třídy `Nette\Bridges\SecurityHttp\SessionStorage` a `CookieStorage`. Zvolit si uložiště a nakonfigurovat jej můžete velmi pohodlně v konfiguraci [security › authentication |configuration#Úložiště].
176179

177-
Dále můžete ovlivnit, jak přesně bude probíhat ukládání identity (*sleep*) a obnovování (*wakeup*). Stačí, aby authenticator implementoval rozhraní `Nette\Security\IdentityHandler`. To má dvě metody: `sleepIdentity()` se volá před zápisem identity do úložiště a `wakeupIdentity()` po jejím přečtení. Metody mohou obsah identity upravit, případně ji nahradit novým objektem, který vrátí. Metoda `wakeupIdentity()` může dokonce vrátit `null`, čímž uživatele jej odhlásí.
180+
Dále můžete ovlivnit, jak přesně bude probíhat ukládání identity (*sleep*) a obnovování (*wakeup*). Stačí, aby authenticator implementoval rozhraní `Nette\Security\IdentityHandler`. Metoda `sleepIdentity()` se volá před zápisem identity do úložiště a `wakeupIdentity()` po jejím přečtení. Metody mohou obsah identity upravit, případně ji nahradit novým objektem, který vrátí. Metoda `wakeupIdentity()` může dokonce vrátit `null`, čímž uživatele jej odhlásí. Rozhraní deklaruje i metodu `getGuestIdentity()`, viz [#Identita hosta].
178181

179182
Jako příklad si ukážeme řešení časté otázky, jak aktualizovat role v identitě hned po načtení ze session. V metodě `wakeupIdentity()` předáme do identity aktuální role např. z databáze:
180183

@@ -196,6 +199,12 @@ final class Authenticator implements
196199
$identity->setRoles($this->facade->getUserRoles($userId));
197200
return $identity;
198201
}
202+
203+
public function getGuestIdentity(): ?IIdentity
204+
{
205+
// identitu hosta zde nepoužíváme
206+
return null;
207+
}
199208
```
200209

201210
A nyní se vrátíme k úložišti na bázi cookies. Dovoluje vám vytvořit web, kde se mohou přihlašovat uživatelé a přitom nepotřebuje sessions. Tedy nepotřebuje zapisovat na disk. Ostatně tak funguje i web, který právě čtete, včetně fóra. V tomto případě je implementace `IdentityHandler` nutností. Do cookie totiž budeme ukládat jen náhodný token reprezentující přihlášeného uživatele.
@@ -231,9 +240,30 @@ final class Authenticator implements
231240
? new SimpleIdentity($row->id, null, (array) $row)
232241
: null;
233242
}
243+
244+
public function getGuestIdentity(): ?IIdentity
245+
{
246+
// identitu hosta zde nepoužíváme
247+
return null;
248+
}
249+
}
250+
```
251+
252+
253+
Identita hosta .{data-version:3.2.4}
254+
====================================
255+
256+
Někdy se hodí, aby měli identitu i nepřihlášení návštěvníci, například abyste jim přiřadili výchozí sadu rolí nebo jim předali nějaká data. Pokud autentikátor implementuje `IdentityHandler`, může ji poskytnout přes metodu `getGuestIdentity()`, která se použije vždy, když není nikdo přihlášený. Metody `getIdentity()`, `getId()` a `getRoles()` se pak na ni odkážou, takže hosté mohou mít vlastní role místo pouhé role `guest`. Pokud identitu hosta nechcete, vraťte `null`.
257+
258+
```php
259+
public function getGuestIdentity(): ?IIdentity
260+
{
261+
return new SimpleIdentity('guest', ['guest'], ['name' => 'Guest']);
234262
}
235263
```
236264

265+
Identita hosta se nikdy neukládá do úložiště a přihlášení ji vždy nahradí.
266+
237267

238268
Více nezávislých přihlášení
239269
===========================

security/cs/authorization.texy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ if ($user->isInRole('admin')) { // je uživatel v roli admina?
3030
}
3131
```
3232

33-
Jak už víte, po odhlášení uživatele se nemusí smazat jeho identita. Tedy i nadále metoda `getIdentity()` vrací objekt `SimpleIdentity`, včetně všech udělených rolí. Nette Framework vyznává princip „less code, more security“, kdy méně psaní vede k více zabezpečenému kódu, proto při zjišťování rolí nemusíte ještě ověřovat, zda je uživatel přihlášený. Metoda `isInRole()` pracuje s **efektivními rolemi,** tj. pokud je uživatel přihlášen, vychází z rolí uvedených v identitě, pokud přihlášen není, má automaticky speciální roli `guest`.
33+
Jak už víte, po odhlášení uživatele se nemusí smazat jeho identita. Tedy i nadále metoda `getIdentity()` vrací objekt `SimpleIdentity`, včetně všech udělených rolí. Nette Framework vyznává princip „less code, more security“, kdy méně psaní vede k více zabezpečenému kódu, proto při zjišťování rolí nemusíte ještě ověřovat, zda je uživatel přihlášený. Metoda `isInRole()` pracuje s **efektivními rolemi,** tj. pokud je uživatel přihlášen, vychází z rolí uvedených v identitě, pokud přihlášen není, má automaticky speciální roli `guest` (nebo role [identity hosta |authentication#Identita hosta], pokud je nějaká poskytnuta).
3434

3535

3636
Autorizátor

security/cs/configuration.texy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ security:
5353

5454
# kam ukládat informace o přihlášeném uživateli
5555
storage: session # (session|cookie) výchozí je session
56+
57+
# zachovat identitu i po odhlášení a expiraci
58+
persistIdentity: true # (bool) výchozí je true
5659
```
5760

5861
Pokud zvolíte jako úložiště `cookie`, můžete nastavit ještě tyto volby:

security/en/authentication.texy

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ What's important is that when logging out using `$user->logout()`, **the identit
166166

167167
Thanks to this, you can still assume which user is at the computer and, for example, display personalized offers in an e-shop, but you can only display their personal information after they log in.
168168

169+
.{data-version:3.2.4}
170+
Besides clearing the identity per call with `logout(true)`, you can disable its retention entirely using the `$persistIdentity` property. When set to `false`, the identity is discarded on every logout and on expiration, so `getIdentity()` then returns `null`. Keeping the identity also depends on the storage: the cookie storage cannot retain it after logout, because it always deletes the cookie.
171+
169172
An identity is an object implementing the [api:Nette\Security\IIdentity] interface. The default implementation is [api:Nette\Security\SimpleIdentity]. And as mentioned, it is maintained in the session, so if, for example, we change the role of one of the logged-in users, the old data will remain in their identity until they log in again.
170173

171174

@@ -174,7 +177,7 @@ Storage for Logged-in User
174177

175178
The two basic information about the user, namely whether they are logged in and their [#identity], are usually transmitted in the session. Which can be changed. An object implementing the `Nette\Security\UserStorage` interface is responsible for storing this information. Two standard implementations are available: `Nette\Bridges\SecurityHttp\SessionStorage`, which transmits data in the session, and `CookieStorage`, which transmits data in a cookie. You can choose the storage and configure it very conveniently in the [security › authentication |configuration#User Storage] configuration.
176179

177-
Furthermore, you can influence how exactly the identity saving (*sleep*) and restoring (*wakeup*) will proceed. All that is needed is for the authenticator to implement the `Nette\Security\IdentityHandler` interface. This interface has two methods: `sleepIdentity()` is called before the identity is written to storage, and `wakeupIdentity()` after it's read. These methods can modify the identity content, or replace it with a new object that it returns. The `wakeupIdentity()` method can even return `null`, which logs the user out.
180+
Furthermore, you can influence how exactly the identity saving (*sleep*) and restoring (*wakeup*) will proceed. All that is needed is for the authenticator to implement the `Nette\Security\IdentityHandler` interface. The `sleepIdentity()` method is called before the identity is written to storage, and `wakeupIdentity()` after it's read. These methods can modify the identity content, or replace it with a new object that it returns. The `wakeupIdentity()` method can even return `null`, which logs the user out. The interface also declares the `getGuestIdentity()` method, see [#Guest Identity].
178181

179182
As an example, let's show a solution to the frequent question of how to update roles in the identity right after loading from the session. In the `wakeupIdentity()` method, we pass the current roles, e.g., from a database, into the identity:
180183

@@ -196,6 +199,12 @@ final class Authenticator implements
196199
$identity->setRoles($this->facade->getUserRoles($userId));
197200
return $identity;
198201
}
202+
203+
public function getGuestIdentity(): ?IIdentity
204+
{
205+
// no guest identity is used here
206+
return null;
207+
}
199208
```
200209

201210
Now let's return to storage based on cookies. It allows you to create a website where users can log in while not needing sessions. Thus, it does not need to write to the disk. This is how the website you are currently reading works, including the forum. In this case, the implementation of `IdentityHandler` is a necessity. We will only store a random token representing the logged-in user in the cookie.
@@ -231,9 +240,30 @@ final class Authenticator implements
231240
? new SimpleIdentity($row->id, null, (array) $row)
232241
: null;
233242
}
243+
244+
public function getGuestIdentity(): ?IIdentity
245+
{
246+
// no guest identity is used here
247+
return null;
248+
}
249+
}
250+
```
251+
252+
253+
Guest Identity .{data-version:3.2.4}
254+
====================================
255+
256+
Sometimes it is handy for visitors who are not logged in to have an identity too, for example to give them a default set of roles or some data. If the authenticator implements `IdentityHandler`, it can supply one through the `getGuestIdentity()` method, which is used whenever nobody is logged in. Then `getIdentity()`, `getId()` and `getRoles()` fall back to it, so guests can have their own roles instead of just the plain `guest` role. Return `null` if you don't want a guest identity.
257+
258+
```php
259+
public function getGuestIdentity(): ?IIdentity
260+
{
261+
return new SimpleIdentity('guest', ['guest'], ['name' => 'Guest']);
234262
}
235263
```
236264

265+
The guest identity is never saved to storage, and logging in always replaces it.
266+
237267

238268
Multiple Independent Logins
239269
===========================

security/en/authorization.texy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ if ($user->isInRole('admin')) { // is the user in the admin role?
3030
}
3131
```
3232

33-
As you already know, logging out the user does not have to delete their identity. Thus, the `getIdentity()` method still returns the `SimpleIdentity` object, including all granted roles. Nette Framework espouses the principle "less code, more security," where less writing leads to more secure code. Therefore, when checking roles, you do not need to verify whether the user is logged in. The `isInRole()` method works with **effective roles**: if the user is logged in, it is based on the roles specified in the identity; if not logged in, they automatically have the special role `guest`.
33+
As you already know, logging out the user does not have to delete their identity. Thus, the `getIdentity()` method still returns the `SimpleIdentity` object, including all granted roles. Nette Framework espouses the principle "less code, more security," where less writing leads to more secure code. Therefore, when checking roles, you do not need to verify whether the user is logged in. The `isInRole()` method works with **effective roles**: if the user is logged in, it is based on the roles specified in the identity; if not logged in, they automatically have the special role `guest` (or the roles of the [guest identity |authentication#Guest Identity], if one is provided).
3434

3535

3636
Authorizer

security/en/configuration.texy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ security:
5353

5454
# where to store information about the logged-in user
5555
storage: session # (session|cookie) default is session
56+
57+
# keep the identity available after logout and expiration
58+
persistIdentity: true # (bool) defaults to true
5659
```
5760

5861
If you choose `cookie` as the storage, you can also set these options:

0 commit comments

Comments
 (0)