1

私は次のようなLoginControllerクラスを持っています:

class LoginController
{
    protected $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function login($username, $password)
    {
        //Query the database, and get back the password_hash, salt, and user id.
        //Hash the incoming password with the salt.
        //Compare the two hashes.
        //return the logged in user object.
    }
}

したがって、データベースからpassword_hashとsaltを取得した後、着信パスワードをハッシュする必要があるステップがあります。これは私には、別のコンポーネントによって処理されるべき2番目の責任のように思えます。おそらくPasswordHashingComponent(または持っている場合はより良い名前)。

abstract class PasswordHashingComponentAbstract
{
    public abstract function hash($data, $salt = "");

    public function verify($hash, $data, $salt = "")
    {
        return $this->hash($data, $salt) == $hash;
    }
}

class MD5PasswordHashingComponent extends PasswordHashingComponentAbstract
{
    public function hash($data, $salt = "")
    {
        return md5($data . md5($salt));
    }
}

class SHA1PasswordHashingComponent extends PasswordHashingComponentAbstract
{
    public function hash($data, $salt = "")
    {
        return sha1($data . sha1($salt));
    }
}

次に、LoginControllerに依存性注入することができます。

public function __construct(PDO $db, PasswordHashingComponentAbstract $passwordhasher);

$loginController = new LoginController($db, new SHA1PasswordHashingComponent());
$loginController->login("username", "password");

だから私の質問は、これがやり過ぎかどうかです。

LoginControllerがログインとパスワードのハッシュおよび比較の両方を処理する場合、これは主要なSRP違反ですか?

私の見方では、このクラスが変更される可能性がある理由は2つあります。

  1. ログインの処理方法が変わる場合。
  2. パスワードをハッシュして比較する方法が変更された場合。

それで、それはSRPに違反しませんか?パスワードハッシュ部分の抽象化を処理できるより良い方法はありますか?

ありがとう!

4

1 に答える 1

0

より多くの機能があり、それらの機能の一部が互いに独立して変更されることが予想され、その変更がクラスのメンテナンスに重要である場合、そのクラスは SRP に違反します。このクラスは、いくつかの機能を実行します。

  1. サーバー側からデータを取得し、

  2. クライアント側からデータを取得し、

  3. クライアント側とサーバー側からのデータを比較して検証します

  4. サーバー側に結論を返し、

  5. クライアント側に結論を返します。

ad 1. このデータは、さまざまなデータ セットで構成できます。たとえば、パスワード、ソルト、ユーザー名、セキュリティの質問と回答が含まれる場合があります。

広告 2. このデータは、複数の情報で構成されている場合があります。時間の経過とともに変化し、さまざまなソース (CAPTCHA およびユーザー データ) から取得する可能性があります。ユーザー名とパスワードだけではありません。

クライアント側とサーバー側には、いくつかの共通情報があります。その情報は、ユーザーの認証に使用されます。

広告 3. 比較方法は、クライアント側とサーバー側からの異なるデータ セットに使用されます。

広告 4. 特定のアカウントまたは IP アドレスによるログインの失敗回数を保存するなど、ログインの成功または失敗後にサーバー側で何かを行うことを決定したり、保存されたソルトとパスワードを変更したりする場合があります。

広告 5. 成功するかどうかに関係なく、クライアントはメッセージを受け取る必要があります。

1、2、および 3 は一緒に変化し、1 と 4 は共通の接続を持ち、2 と 5 は共通の機能接続を持ちます。3 サーバーからのデータ セットとクライアント側からのデータ セットを認識している必要があります。データ セットは一緒に変更されますが、比較に使用される方法に違いがある場合があります。したがって、データセットの変更と比較方法の間には 1:N のカーディナリティがあります。これは、インターフェイスを使用して実装する必要があります。

「結論をサーバー側に返す」関数と「クライアント側に返す」関数は、どちらも他の実装から独立して変更されます。サーバー側は実装する必要はなく、クライアント側へのフィードバックは検証プロセス自体とは無関係にすることをお勧めします。結論をサーバー側に返す処理が実装されている場合、サーバー側からのデータの取得と接続と格納場所に関する情報を共有する可能性が高くなります。そのオーバーラップがデザインに戻るはずです。これまでのところ、結論をサーバー側に返す機能を実装していませんが、これは非常に役立つ可能性があります。ログイン後にサーバー側で実行する次のステップについて考えることができます: 1. 誰かが同じコンピューターまたは同じユーザー名などを使用してログインを試みた回数を保存したい場合があります。 2. ログインが成功するたびに、ハッシュ化されたパスワードとソルトを変更できます。そのとき、あなたは正しいパスワードを記憶していますか。(ちなみに、常にソルトを使用してください。標準化されたデフォルトパスワードが与えられ、管理者がそのパスワードを頭からハッシュ化されていることを知っているアプリケーションを見たことがあります。彼らは、パスワードを変更していない人のパスワードでログインできました。 3. ユーザーのプリファレンスを新しいセッションに追加できます。4. ... このステップは非常に複雑で、クライアントへのフィードバックに影響を与える可能性があります (ログインに 3 回以上失敗しています...

UML クラス図では、次のようになります。

クラス図 LoginController

LoginController とサーバー側クラスの間の関係を集約として描写し、LoginController が使用するデータ モデルまたはその他の構成データに基づいて使用する実装を決定することを示しました。

于 2013-06-15T09:37:47.477 に答える