Skip to content

Commit

Permalink
best practices: attribute Requires
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Apr 19, 2024
1 parent 0187299 commit 1a18862
Show file tree
Hide file tree
Showing 32 changed files with 2,768 additions and 0 deletions.
1 change: 1 addition & 0 deletions best-practices/bg/@home.texy
Expand Up @@ -17,6 +17,7 @@
- [Как да се върнете към предишна страница |restore-request]
- [Страница на резултатите от базата данни |Pagination]
- [Динамични фрагменти |dynamic-snippets]
- [Как да използвате атрибута #Requires |attribute-requires]

</div>
<div>
Expand Down
172 changes: 172 additions & 0 deletions best-practices/bg/attribute-requires.texy
@@ -0,0 +1,172 @@
Как да използвате `#[Requires]` Атрибут
***************************************

.[perex]
Когато пишете уеб приложение, често се сблъсквате с необходимостта да ограничите достъпа до определени части на приложението. Може би искате някои заявки да могат да изпращат данни само чрез формуляр (като по този начин се използва методът POST) или да са достъпни само за AJAX повиквания. В Nette Framework 3.2 е въведен нов инструмент, който ви позволява да задавате такива ограничения по елегантен и ясен начин: инструментът `#[Requires]` атрибут.

Атрибутът е специален маркер в PHP, който се добавя преди дефиницията на клас или метод. Тъй като по същество това е клас, трябва да включите клаузата use:

```php
use Nette\Application\Attributes\Requires;
```

. `#[Requires]` Атрибутът може да се използва за класовете на презентаторите и следните методи:

- `action<Action>()`
- `render<View>()`
- `handle<Signal>()`
- `createComponent<Name>()`

Последните два метода също се отнасят за всички компоненти.

Ако условията не са изпълнени, се задейства HTTP 40x грешка.


HTTP методи .[#toc-http-methods]
--------------------------------

Можете да зададете кои HTTP методи (като GET, POST и т.н.) са разрешени за достъп. Например, ако искате да разрешите достъп само чрез изпращане на формуляр, задайте:

```php
#[Requires(methods: 'POST')]
class FormPresenter extends Nette\Application\UI\Presenter
{
}
```


Извиквания AJAX .[#toc-ajax-calls]
----------------------------------

Ако искате даден презентатор или метод да бъде достъпен само за AJAX заявки, използвайте:

```php
#[Requires(ajax: true)]
class AjaxPresenter extends Nette\Application\UI\Presenter
{
}
```


Същият произход .[#toc-same-origin]
-----------------------------------

За да повишите сигурността, можете да изисквате заявката да бъде направена от същия домейн:

```php
#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}
```

За `handle<Signal>()` методи това се изисква автоматично. И обратното, ако искате да разрешите достъп от всеки домейн, посочете:

```php
#[Requires(sameOrigin: false)]
public function handleList(): void
{
}
```


Достъп чрез Forward .[#toc-access-via-forward]
----------------------------------------------

Понякога искате да ограничите достъпа до даден презентатор, така че той да е достъпен само косвено, например чрез метода `forward()` от друг презентатор. По този начин се защитават презентаторите на грешки, така че да не могат да бъдат извикани от URL адрес:

```php
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
```

Можете също така да ограничите определени изгледи, до които може да се получи достъп въз основа на логиката в презентатора:

```php
class ProductPresenter extends Nette\Application\UI\Presenter
{

public function actionDefault(int $id): void
{
$product = this->facade->getProduct($id);
if (!product) {
this->setView('notfound');
}
}

#[Requires(forward: true)]
public function renderNotFound(): void
{
}
}
```


Специфични действия .[#toc-specific-actions]
--------------------------------------------

Можете също така да ограничите достъпа до определен код, като например създаване на компонент, само за определени действия в презентатора:

```php
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
```

За едно действие не е необходимо да се пише масив: `#[Requires(actions: 'default')]`


Потребителски атрибути .[#toc-custom-attributes]
------------------------------------------------

Ако искате да използвате `#[Requires]` атрибут с едни и същи настройки, можете да създадете свой собствен атрибут, който ще наследи `#[Requires]` и да го настроите според нуждите си.

Например, `#[SingleAction]` позволява достъп само чрез действието `default`:

```php
#[Attribute]
class SingleAction extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(actions: 'default');
}
}

#[SingleAction]
class SingleActionPresenter extends Nette\Application\UI\Presenter
{
}
```

Или `#[AllowAllMethods]` позволява достъп чрез всички HTTP методи, което стандартните презентатори [не позволяват от съображения за сигурност |application:presenters#toc-http-method-control].

```php
#[\Attribute]
class AllowAllMethods extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']);
}
}

#[AllowAllMethods]
class OpenPresenter extends Nette\Application\UI\Presenter
{
}
```


Заключение .[#toc-conclusion]
-----------------------------

На `#[Requires]` ви дава голяма гъвкавост и контрол върху начина, по който се осъществява достъпът до вашите уеб страници. С помощта на прости, но мощни правила можете да повишите сигурността и правилното функциониране на вашето приложение. Както виждате, използването на атрибути в Nette може не само да опрости работата ви, но и да я осигури.

{{sitename: Best Practices}}
1 change: 1 addition & 0 deletions best-practices/cs/@home.texy
Expand Up @@ -17,6 +17,7 @@ Nette Aplikace
- [Jak se vrátit k dřívější stránce |restore-request]
- [Stránkování výsledků databáze |pagination]
- [Dynamické snippety |dynamic-snippets]
- [Jak používat atribut #Requires |attribute-requires]

</div>
<div>
Expand Down
172 changes: 172 additions & 0 deletions best-practices/cs/attribute-requires.texy
@@ -0,0 +1,172 @@
Jak používat atribut `#[Requires]`
**********************************

.[perex]
Když píšete webovou aplikaci, často se setkáte s potřebou omezit přístup k určitým částem vaší aplikace. Možná chcete, aby některé požadavky mohly odesílat data pouze pomocí formuláře (tedy metodou POST), nebo aby byly přístupné pouze pro AJAXové volání. V Nette Frameworku 3.2 se objevil nový nástroj, který vám umožní taková omezení nastavit velmi elegantně a přehledně: atribut `#[Requires]`.

Atribut je speciální značka v PHP, kterou přidáte před definici třídy nebo metody. Protože jde vlastně o třídu, je nutné uvést klauzuli use:

```php
use Nette\Application\Attributes\Requires;
```

Atribut `#[Requires]` můžete použít na třídy presenterů i na tyto metody:

- `action<Action>()`
- `render<View>()`
- `handle<Signal>()`
- `createComponent<Name>()`

Poslední dvě metody se týkají také všech komponent.

Pokud nejsou splněny podmínky, dojde k vyvolání HTTP chyby 40x.


Metody HTTP
-----------

Můžete specifikovat, které HTTP metody (jako GET, POST atd.) jsou pro přístup povolené. Například, pokud chcete povolit přístup pouze odesíláním formuláře, nastavíte:

```php
#[Requires(methods: 'POST')]
class FormPresenter extends Nette\Application\UI\Presenter
{
}
```


AJAXové volání
--------------

Pokud chcete, aby byl presenter nebo metoda dostupná pouze pro AJAXové požadavky, použijte:

```php
#[Requires(ajax: true)]
class AjaxPresenter extends Nette\Application\UI\Presenter
{
}
```


Stejný původ
------------

Pro zvýšení bezpečnosti můžete vyžadovat, aby byl požadavek učiněn ze stejné domény:

```php
#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}
```

U metod `handle<Signal>()` je tohle vyžadováno automaticky. Pokud naopak chcete povolit přístup z jakékoliv domény, uveďte:

```php
#[Requires(sameOrigin: false)]
public function handleList(): void
{
}
```


Přístup přes forward
--------------------

Někdy chcete omezit přístup k presenteru tak, aby byl dostupný pouze nepřímo, například použitím metody `forward()` z jiného presenteru. Takto se třeba chrání error-presentery, aby je nebylo možné vyvolat z URL:

```php
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
```

Také můžete omezit určité views, ke kterým se lze dostat až na základě logiky v presenteru:

```php
class ProductPresenter extends Nette\Application\UI\Presenter
{

public function actionDefault(int $id): void
{
$product = $this->facade->getProduct($id);
if (!$product) {
$this->setView('notfound');
}
}

#[Requires(forward: true)]
public function renderNotFound(): void
{
}
}
```


Konkrétní akce
--------------

Můžete také omezit, že určitý kód, třeba vytvoření komponenty, bude dostupné pouze pro specifické akce v presenteru:

```php
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
```

V případě jedné akce není potřeba zapisovat pole: `#[Requires(actions: 'default')]`


Vlastní atributy
----------------

Pokud chcete použít atribut `#[Requires]` opakovaně s týmž nastavením, můžete si vytvořit vlastní atribut, který bude dědit `#[Requires]` a nastaví ho podle potřeb.

Například `#[SingleAction]` umožní přístup pouze přes akci `default`:

```php
#[\Attribute]
class SingleAction extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(actions: 'default');
}
}

#[SingleAction]
class SingleActionPresenter extends Nette\Application\UI\Presenter
{
}
```

Nebo `#[AllowAllMethods]` umožní přístup přes všechny HTTP metody, což standardně presentery z bezpečnostních důvodů [nedovolují |application:presenters#toc-kontrola-http-metody].

```php
#[\Attribute]
class AllowAllMethods extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']);
}
}

#[AllowAllMethods]
class OpenPresenter extends Nette\Application\UI\Presenter
{
}
```


Závěr
-----

Atribut `#[Requires]` vám dává velkou flexibilitu a kontrolu nad tím, jak jsou vaše webové stránky přístupné. Pomocí jednoduchých, ale mocných pravidel můžete zvýšit bezpečnost a správné fungování vaší aplikace. Jak vidíte, použití atributů v Nette může vaši práci nejen usnadnit, ale i zabezpečit.

{{sitename: Best Practices}}
1 change: 1 addition & 0 deletions best-practices/de/@home.texy
Expand Up @@ -17,6 +17,7 @@ Nette Bewerbung
- [Wie man zu einer früheren Seite zurückkehrt |restore-request]
- [Paginieren von Datenbankergebnissen |Pagination]
- [Dynamische Schnipsel |dynamic-snippets]
- [Wie man das Attribut #Requires verwendet |attribute-requires]

</div>
<div>
Expand Down

0 comments on commit 1a18862

Please sign in to comment.