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
を呼び出すのに最適な場所はどこですか。コントローラーの構築および/またはメソッド、またはモデルの構築および/またはメソッドで?
認証はルーティングの後、コントローラまたはそのメソッドを呼び出す前に行われる必要があります。
その時点で、どのルートが要求されたかがわかり、ユーザーが特定のアクションを実行する特権を持っているかどうかを確認できます(コントローラーを呼び出す)。
これにより、関心事を分離するだけでなく、コントローラにヒットする前に非承認リクエストを処理する方法を決定することもできます。それらを403応答で他のコントローラーに内部的にリダイレクトします。
認証/承認は、モデルより上位のレイヤーで行われます。ユーザーインスタンスに依存している場合-既に認証/承認されたインスタンスを渡します。また、-要件が変更され、他のロールが以前に禁止されたメソッドの呼び出しを許可されている場合-ACLのみを変更し、モデルは変更しません。
Symfonyフレームワークは彼らがどのようにしたかについての素晴らしい説明を持っていました、それはv.2でまだ利用可能です: http://symfony.com/doc/2.0/book/security.html
私はJava=世界の出身ですが、物事はかなり似ているので、私の意見での権利チェックについてのヒントをいくつか示します。
あなたの権利が「アクションXを実行する権利を持っている」のような権利である場合。次に、ルーティングの前とサービス層で確認する必要があります。
「Yに対してアクションXを実行する権利を持っている」などの権利がある場合、以前の手順で可能なように、サービスレイヤーでのみ許可することができます。ただし、ルーティングを実行するときにフレームワークがそれを実行する機能を提供している場合は、これを実行してください。ただし、サービスの機能はさまざまな場所から使用できるため、率直に言ってサービスチェックを希望します。
あなたは完全に2セットのロレスを持つことができます:
ステップ1:ルートが存在するかどうかを確認します。ルートが存在しない場合は、他の何に加えて404 (Not Found)
HTTP応答コードを送信することを忘れないでください。
ステップ2:ルートが存在する場合、認証(IDの確立)が必要かどうかを判断します。
ステップ:認証が必要な場合は、Controller
をインスタンス化する前に、認証ステータス(ユーザーがログインしているか)を確認します。 注、これは、ルートがHTTPリクエストメソッド、Controller
の名前、アクション/コマンド、および次を示すブールフラグの組み合わせによって定義される必要があることを意味しますルートはパブリックまたはプライベート(安全)です。
これら4つのものが事前に準備されてRouter
で利用できない場合、Controller
のコンピューティングリソースを浪費し、Model
で認証ステータスを解決しようとします。
重要なのは、Controller
、PublicController
、およびPrivateController
の抽象クラスを作成し、それに応じて後の2つを拡張することです。ただし、認証の問題が満たされた場合にのみ、PrivateController
の子をインスタンス化します。 Model
sを使用するには、View
とPrivateController
を選択する必要があるため、コンストラクターインジェクションを使用している場合、これは不可欠です。
HTTPリクエストメソッド、ルート(コントローラー/アクション)、および認証が解決されていない場合、PrivateController
の子を(依存関係とともに)インスタンス化しても意味がありません。
ステップ4a:ユーザー/訪問者がnotログインしている場合、303 (See Other)
HTTP応答コード。ログインに失敗した場合は、必ず401 (Unauthorized)
HTTP応答コードを送信してください。
ステップ4b:ユーザーすでに認証されている場合(ログイン済み)の場合は、問題のリソースおよびアクション/メソッドにアクセスするために必要な権限があるかどうかを確認します( PrivateController
子をインスタンス化する前)。権限がない場合は、402 (Forbidden)
HTTP応答コードを送信してください。
ログイン/エラー/保護されたコンテンツへのアクセスの認証に失敗した後、誰かがどこに行き着くかを決定します。
手順5:Controller
がインスタンス化された後、ユーザーがまだログインしていることを確認してください特定のアクションを実行するための承認(権限)を確認します。
実際には、first認証および承認チェックは、HTTPリクエスト自体の性質に関するものです。システムが要求されているアクション/メソッドに到達するために多くの作業を行うように要求を許可する必要がありますか?
second認証および承認チェックは、要求の状態が時間ドメイン全体でまだ有効であることを確認することです(ただし、時間枠は非常に小さい場合がありますが、確かに)。アカウントは常に停止、降格され、強制的にログアウトされます。最初のリクエストが良いからといって、それが0.005秒後もまだ良いということにはなりません。
実装
このようなクラスを使用すると、Router
がPublicController
の子をすぐにインスタンス化するか、最初に認証の問題に対処するかを決定するのに役立ちます。
/**
* 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]);
}
}