web-dev-qa-db-ja.com

ベストプラクティスPHP mvc routing

私は常に進化しているカスタムMVCフレームワークを持っています。ルーティングがどのように機能するかについて、同僚との長年の議論があります。次のディレクトリ構造を検討します。

/core/Router.php
/mvc/Controllers/{Public controllers}
/mvc/Controllers/Private/{Controllers requiring valid user}
/mvc/Controllers/CMS/{Controllers requiring valid user and specific roles}

質問は次のとおりです。「現在のユーザーの認証は、どこで確立する必要がありますか。ルーターで、ロードするコントローラ/ディレクトリを選択するとき、または各コントローラで」

私の主張は、ルーターで認証するときに、要求されたコントローラーの代わりにエラーコントローラーが作成され、事故を通知することです。また、ディレクトリ構造は、必要な認証を明確に示しています。

彼の主張は、ルーターはルーティングを行い、ルーティングのみを行うべきであるというものです。ケースバイケースで処理する場合は、コントローラーに任せてください。これはよりモジュール化されており、ルーターによる変更が必要になった場合の柔軟性を高めます。

https://codereview.stackexchange.com/questions/26345/php-mvc-custom-routing-mechanism ほのめかしましたが、トピックは別の性質のものでした。

代替案も同様に歓迎されます。

6
jweatherby

その間にアクセス権を決定する別のコンポーネントがあります。このコンポーネントは、ユーザーの役割とリソースのマッピングのセットを持つことができ、コントローラーやアクションがリソースになります。実行は次のようになります。

Router -> Authorization -> Controller

Router: determines which controller and action to execute

Auth: find out which user role is logged in and check
if the user has access to the controller/action,
if not, throw an exception that will get caught by the error handler,
or redirect to login page for guests, or whatever

Controller: if the authorization component didn't complain, do work as usual

凝ったものにしたい場合は、php docコメントとリフレクションを使用して、ユーザーロールに許可されたリソースの大きなリストを用意する代わりに、メソッドとコントローラーにその場で注釈を付けることができます。何かのようなもの:

class Controller {
    /**
     * @allow({'admin','user'})
     * @prevent({'guest'})
     */
    public function someAction(){}
}

次に、認証コンポーネントは、役割からリソースへのマッピングの大きなリストを作成する代わりに、注釈を読み取ってアクセス権を決定できます。

2
Ivan Pintar

ここにアイデアがあります。技術的には、多分あなたの両方が正しくありません。おそらく、ユーザーのログインステータスとロールが検証されるのに最適な場所は、Validatorクラスの具象インスタンスです。

enter image description here

これは、ユーザーがログインしているかどうかを確認する以外に、シナリオでControllerValidatorが何をするのかという疑問を投げかけます。それは、HTTPリクエストについて5つの基本的なことをテストして、それが妥当なリクエストであるか、おそらく悪意のあるハッキングであるかどうかを導き出します。

1)最小入力(十分なHTMLコントロールが送信されましたか?)

2)最大入力(送信されたHTMLコントロールが多すぎませんか?)

3)正しい入力(HTMLコントロールは正しいものを送信したか?)

4)正しいエンコーディング(通常、エンコーディングはUTF-8ですが、それが必要なものですか?)このチェックには、独自の特殊バリデータクラスが必要です。このオブジェクトのインスタンスをすべてのControllerValidatorオブジェクトに挿入します。

5)最大入力サイズ(これまでに作成する必要がある許容サイズを超える入力はありますか?).

したがって、答えは、コントローラがユーザーとロールのものをチェックする必要があるということです(これは、最終的なコマンドのキャリアであるHTTPリクエストに関連しているためです)。 HTTP URLの定義により、ユーザー認証が可能になることに注意してください。したがって、HTTP認証を使用していない場合でも、リクエストの一部としてユーザーをチェックすることは正当なタスクです。役割の検証は、単にユーザー認証を拡張したものです。

さて、このUMLダイアグラムは単なる要約です。ただし、HTTPリクエストのintentをチェックすることの本質は把握しています(誠実なリクエスト、または明らかに悪意のあるもの)。 ControllerValidatorのすべてのテストに合格するか、要求が拒否されて終了します。

ただし、要件に応じて、PrivateControllerValidatorCMSControllerValidatorには違いがあることに注意してください。前者はロールチェックを行うことができません。それはあなたが本当にそれを望んでいる方法ですか? CMSControllerValidatorPrivateControllerValidatorのようです。 PrivateControllerValidatorインスタンスがneverロールチェックを使用する必要があることを確信していますか?

Update:URL書き換えWebサーバーとRouterクラスがある場合、上記の5つのテストのみを実行する必要があります最初は、HTTP要求ヘッダーに関連しています。データをRouterに送信するのに十分なテストが完了したら、モデルでページ固有の検証を実行できます(PHPでは、これには$ _POST、$ _ FILES、$ _ GET、$ _ COOKIEなどの検証が含まれます)。

2

私は、ルーターを離れて他の人の責任を負わないことを提案します。私はそれが良いプログラミング慣行であり、他の人も同じことを理解するのに役立つと思います。

ここで、コントローラーについて、先に進んで継承を使用することをお勧めします。すべてのコントローラーに共通するすべての雑用を実行できる親コントローラーBase_Controllerがあります。 Baseから、Secure_ControllerおよびNonSecure_Controllerを派生させます。NonSecure_Controllerは、名前のとおりです。

いつでもコントローラーから例外をスローできます。これは、フックで適切に処理して、ビューを適切に表示できます。

1
Arun