レコードは実際には「重複」ではありません。
プロバイダーと aspnet_Users テーブルの役割との関係を理解すると、これを解決するのに役立つ場合があります。
まず、MembershipProvider と RoleProvider は相互に依存していないことを理解してください。ただし、後で説明する MembershipProvider.DeleteUser() メソッドでの懸念事項のいくつかの例外があります。
メンバーシップの役割は、ユーザーを認証し、認証を使用してリソースへのアクセスを保護することです。
役割の役割は、役割の割り当てによってリソースへのアクセスを制御することです。
これらは 2 つの別個の問題であり、aspnet_Users の状態が意味するものに関係なく、関連していません。
顕著な問題は、すべてのプロバイダーを接続するために使用される値がusername
. GUID は類似しており、すべてのプロバイダーが同じアプリケーション名を使用する場合、ユーザー名に対して 1 つのuserid
aspnet_users レコードのみが作成されます。これは、各プロバイダーが最初に aspnet_users で一致するユーザー名とアプリケーション名を確認するためです。見つかった場合はそれを使用し、見つからない場合はそれを作成し、ユーザー ID に GUID を割り当てます。
userId GUID は「グローバル」識別子のように見えるかもしれませんが、そうではありません。
したがって、マイナーな注意点として、次に関連する問題を認識している場合は、メンバーシップの各インスタンスに同じアプリケーション名を使用し、各ロール インスタンスに異なるアプリケーション名を使用することで、共通のメンバーシップ ストアを持つ個別のロール プロバイダーを使用できます。
先に述べた関心の分離の (本当にばかげた) 違反には、DeleteUser(deleteRelatedData) が呼び出されたときに SqlMembershipProvider によって実行されるアクションが含まれます。そのとき、SqlMembershipProvider はまるで自分が唯一の犬であるかのように動作し、ロールとプロファイルに渡ってそのキーのみを使用してレコードを削除し、失われると予想されるレコードを見逃します。
考慮事項: (これは前述の単一メンバーシップ、複数ロールの設定を使用しています)
メンバーシップを持つユーザー「John」を作成し、役割を持ついくつかの役割を彼に割り当てます。John の aspnet_users に記録する必要があり、すべてが問題なく動作します。「ジョン」はマネージャーであり、適切な高レベルの役割が割り当てられています。
「ジョン」は何らかの理由で「解雇された男」になり、メンバーシップを介して削除されます。前に述べたように、私たちの独自のシナリオでは、メンバーシップ レコードは削除されますが、ロール情報は残ります。
電話に応答するために新しい「ジョン」が雇われ、メンバーシップ ユーザーが彼のために作成されます。
余暇に、ジョンは会社のイントラネットを探索し、自分がどれだけ素晴らしいことができるか信じられず、間抜けに HR モジュールで自分を昇給させることにしました。
何だと思う?新しい「ジョン」は、「ユーザー名」から切り離された孤立した役割のために、すぐにマネージャーになります。
したがって、これは、組み込みの十分にテストされた既知のプロバイダー スタックを利用するか、この場合は強制するかを決定する際に注意しなければならない「小さな」警告です。
これと非常によく似たシナリオについては既に取り上げており、この問題を解消する簡単な変更の概念実証をここ と ここで提供しています。
別の方法として、単純にこれを認識して、ユーザーを削除するときにクリーンアップするコードを追加することもできます。
これらはどちらも、カスタム プロバイダーを実装するよりもはるかに魅力的なオプションです。
乾杯と幸運。