web-dev-qa-db-ja.com

PHP MVC / PAC-ログイン/管理者が配置を確認

Webアプリケーション用にMVC/PACのような構造をセットアップしました(それがこれらの設計パターンのいずれかに完全に適合するかどうかは不明です)。つまり、それは:

  • index.phpでのルーティング。URLを使用してコントローラーとメソッドを選択しますhttp://example.com/controller/method/<params>
  • コントローラのメソッドは、「モデル」からのデータを要求し、それをビューに割り当てます。

ログインチェックに最適な場所は何でしょうか。ユーザーがログインしている管理者である必要があるhttp://example.com/controller-one/method-one/にページがあるとします。ユーザーが実際にどこにいるかどうかはどこで確認できますか?ルーティング、コントローラ、またはモデルで?

コントローラまたはモデル、あるいはその両方に、異なる「権限」を持つメソッドが含まれる場合があることに注意してください。

注:ユーザーがログインしているかどうかに基づいてtrueまたはfalseを返すisLogged()というメソッドとIsLoggedAdmin()という別のメソッドを含むAuthenticationというモデルがあります。ユーザーがログインしている管理者かどうかに基づいて、trueまたはfalseを返します。

だから...:メソッドisLoggedまたはisLoggedAdminを呼び出すのに最適な場所はどこですか。コントローラーの構築および/またはメソッド、またはモデルの構築および/またはメソッドで?

7
kgongonowdoe

認証はルーティングの後、コントローラまたはそのメソッドを呼び出す前に行われる必要があります。

その時点で、どのルートが要求されたかがわかり、ユーザーが特定のアクションを実行する特権を持っているかどうかを確認できます(コントローラーを呼び出す)。

これにより、関心事を分離するだけでなく、コントローラにヒットする前に非承認リクエストを処理する方法を決定することもできます。それらを403応答で他のコントローラーに内部的にリダイレクトします。

認証/承認は、モデルより上位のレイヤーで行われます。ユーザーインスタンスに依存している場合-既に認証/承認されたインスタンスを渡します。また、-要件が変更され、他のロールが以前に禁止されたメソッドの呼び出しを許可されている場合-ACLのみを変更し、モデルは変更しません。

Symfonyフレームワークは彼らがどのようにしたかについての素晴らしい説明を持っていました、それはv.2でまだ利用可能です: http://symfony.com/doc/2.0/book/security.html

3
potfur

私はJava=世界の出身ですが、物事はかなり似ているので、私の意見での権利チェックについてのヒントをいくつか示します。

あなたの権利が「アクションXを実行する権利を持っている」のような権利である場合。次に、ルーティングの前とサービス層で確認する必要があります。

  • サービス層でのチェックは、そのサービスを呼び出すたびに、必ずチェックが行われるようにすることです。
  • 本当に早い段階でのチェックは、正しいかどうかをチェックする前に発生する可能性のあるコード(データのフェッチなど)の一部を含まないようにするためです。 DDOS攻撃をより効率的に持続させるためにも行われたと言われました。リクエストを拒否するのは早ければ早いほど良いでしょう。

「Yに対してアクションXを実行する権利を持っている」などの権利がある場合、以前の手順で可能なように、サービスレイヤーでのみ許可することができます。ただし、ルーティングを実行するときにフレームワークがそれを実行する機能を提供している場合は、これを実行してください。ただし、サービスの機能はさまざまな場所から使用できるため、率直に言ってサービスチェックを希望します。

あなたは完全に2セットのロレスを持つことができます:

  1. 1つのような:ADMIN/GUEST/USER:ユーザーセッションに格納されている高速ルーティングチェックに使用
  2. 権限:サービスレイヤーで使用され、データベースまたは永続ストレージに保存されます。
2
Walfrat

単純化および明確化する試み。

ステップ1:ルートが存在するかどうかを確認します。ルートが存在しない場合は、他の何に加えて404 (Not Found) HTTP応答コードを送信することを忘れないでください。

ステップ2:ルートが存在する場合、認証(IDの確立)が必要かどうかを判断します。

ステップ:認証が必要な場合は、Controllerをインスタンス化する前に、認証ステータス(ユーザーがログインしているか)を確認します。 注、これは、ルートがHTTPリクエストメソッド、Controllerの名前、アクション/コマンド、および次を示すブールフラグの組み合わせによって定義される必要があることを意味しますルートはパブリックまたはプライベート(安全)です

これら4つのものが事前に準備されてRouterで利用できない場合、Controllerのコンピューティングリソースを浪費し、Modelで認証ステータスを解決しようとします。

重要なのは、ControllerPublicController、およびPrivateControllerの抽象クラスを作成し、それに応じて後の2つを拡張することです。ただし、認証の問題が満たされた場合にのみ、PrivateControllerの子をインスタンス化します。 Modelsを使用するには、ViewPrivateControllerを選択する必要があるため、コンストラクターインジェクションを使用している場合、これは不可欠です。

HTTPリクエストメソッド、ルート(コントローラー/アクション)、および認証が解決されていない場合、PrivateControllerの子を(依存関係とともに)インスタンス化しても意味がありません。

ステップ4a:ユーザー/訪問者がnotログインしている場合、303 (See Other) HTTP応答コード。ログインに失敗した場合は、必ず401 (Unauthorized) HTTP応答コードを送信してください。

ステップ4b:ユーザーすでに認証されている場合(ログイン済み)の場合は、問題のリソースおよびアクション/メソッドにアクセスするために必要な権限があるかどうかを確認します( PrivateController子をインスタンス化する前)。権限がない場合は、402 (Forbidden) HTTP応答コードを送信してください。

ログイン/エラー/保護されたコンテンツへのアクセスの認証に失敗した後、誰かがどこに行き着くかを決定します。

手順5Controllerがインスタンス化された後、ユーザーがまだログインしていることを確認してください特定のアクションを実行するための承認(権限)を確認します。

概要

実際には、first認証および承認チェックは、HTTPリクエスト自体の性質に関するものです。システムが要求されているアクション/メソッドに到達するために多くの作業を行うように要求を許可する必要がありますか?

second認証および承認チェックは、要求の状態が時間ドメイン全体でまだ有効であることを確認することです(ただし、時間枠は非常に小さい場合がありますが、確かに)。アカウントは常に停止、降格され、強制的にログアウトされます。最初のリクエストが良いからといって、それが0.005秒後もまだ良いということにはなりません。

実装

このようなクラスを使用すると、RouterPublicControllerの子をすぐにインスタンス化するか、最初に認証の問題に対処するかを決定するのに役立ちます。

/**
 * Class that holds HTTP request method / Controller / action / secure relationships.
 *
 * @version 4.0
 * @author Anthony E. Rutledge
 * @link https://www.linkedin.com/in/anthony-rutledge-2988b0125/
 */
class MvcRouteMap
{
    private $routes = [
        'GET' => [
            'Root' => [
                'index' => ['secure' => false]
            ],
            'Contact' => [
                'index' => ['secure' => false]
            ],
            'Error' => [
                'index' => ['secure' => false]
            ],
            'Login' => [
                'index' => ['secure' => false]
            ],
            'Newsletter' => [
                'index' => ['secure' => false]
            ]
        ],
        'POST' => [
            'Contact' => [
                'send' => ['secure' => false]
            ],
            'Login' => [
                'login' => ['secure' => false]
            ],
            'Newsletter' => [
                'signup' => ['secure' => false]
            ]
        ],
        'PUT'  => [

        ],
        'PATCH' => [

        ],
        'DELETE' => [

        ]
    ];

    public function __construct()
    {

    }

    public function isSecureRoute(string $httpRequstMethod, string $controller, string $action): bool
    {
        if ($this->isRoute($httpRequstMethod, $controller, $action)) {
            return $this->routes[$httpRequstMethod][$controller][$action]['secure'];
        }

        throw new RuntimeException("The resource requested does not exist.");
    }

    private function isRoute(string $httpRequstMethod, string $controller, string $action): bool
    {
        return isset($this->routes[$httpRequstMethod][$controller][$action]);
    }
}
0