1

これは、フォーム認証を使用した MVC 4 インターネット プロジェクトに関する問題です。ホテルがあり、許可されたユーザーが異なる役割でそれぞれにアクセスしたいとしましょう。

そのため、ユーザーはログインします。次に、ドロップダウンリストから対象のホテルを選択すると、アプリケーションのセキュリティがそれに応じて応答します。

[Authorize(Roles = "Administrator")] のようなものが必要ですが、そのホテルのスコープでのみ必要です。

私の最初のアプローチは AuthorizeAttribute から継承し、このスレッドに示されているように AuthorizeCore をオーバーライドすることでした

そこから HttpContext.Session["HotelId"] を取得し、UserRolesInHotel テーブルにクエリを実行できます。つまり、UserId、RoleId、HotelId に似た構造を持つ独自のロール テーブルが必要です。そのため、SimpleRolePrivider ではこのタスクを実行できず、CustomeRoleProvider を作成する必要があります。RoleProvider メソッドは、新しいロールをユーザーに追加するときに HotelId のように必要なため、追加のパラメーターを処理しません。

明確にするために:

  1. ユーザー A がユーザー/パスワードでログイン -> OK (SimpleMembershipProvider)
  2. 認証されたユーザー A がホテル 1 を選択 -> ユーザー A はホテル 1 の「管理者」です。
  3. 認証されたユーザー A がホテル 2 に変更 -> ユーザー A はホテル 2 の「ユーザー」

ホテルはいくつでも持つことができます。

  1. ユーザー A -> ホテル 1 -> { "管理者", "ユーザー"}
  2. ユーザー A -> ホテル 2 -> { "ユーザー" }
  3. ユーザー A -> ホテル 3 -> { "所有者" }
  4. ユーザー A -> ホテル 4 -> { "管理者" }

役割のリストは常に同じです。

私はこの実装に数日間苦労してきましたが、実用的な解決策を思いつくことができませんでした. どんな考えでも大歓迎です。

ありがとう!

4

1 に答える 1

0

これは私がしたことです:

  • ユーザー プロファイルに DefaultBuildingId を追加しました。
  • 次に、CustomRoleProvider を作成し、このように GetRolesForUser メソッドをオーバーライドしました

    public override string[] GetRolesForUser(string userName)
    {
        if (HttpContext.Current.Session != null)
        {
            var user = _userRepository.GetByName(userName);
    
            if (!user.IsActive)
            {
                throw new ApplicationException(string.Format("some message {0}", userName));
            }
    
            if (HttpContext.Current.Session["BuildingId"] == null)
            {
                var building = _buildingRepository.Get(user.DefaultBuildingId);
                if (building == null)
                {
                    throw new ApplicationException("error message");
                }
    
                HttpContext.Current.Session["BuildingId"] = building.BuildingId;
            }
    
            int buildingId = Convert.ToInt32(HttpContext.Current.Session["BuildingId"]);
            return _userRepository.GetRolesForUserInBuilding(user.UserId, buildingId).ToArray();
        }
    
        throw new ApplicationException("error message.");
    }
    
    • カスタム AuthorizeAttribute を追加しました

      protected override bool AuthorizeCore(HttpContextBase httpContext)
      {
      var authorized = base.AuthorizeCore(httpContext);
      if (!authorized)
      {
          return false;
      }
      
      var repo = UnityManager.Resolve<IUserRepository>();
      var buildingId = (int)httpContext.Session["BuildingId"];
      var userName = httpContext.User.Identity.Name;
      var user = repo.GetByName(userName);
      var userRolesInBuilding = repo.GetRolesForUserInBuilding(user.UserId, buildingId);
      
      foreach (var role in Roles.Split(','))
      {
          if (userRolesInBuilding.Contains(role.Trim()))
          {
              return true;
          }
      }
      
      return false;
      

      }

    • 最後にコントローラーやアクションレベルでの使い方です。

      [BuildingAthorize(Roles = "Administrators")]

また、レイアウトに ddl を追加して、ユーザーが建物を変更し、新しい BuildingId を設定してセッション/データベースの値をオーバーライドできるようにしました。このようにして、ユーザーは同じセッション中に別のホテルで作業し、その特定のホテルのエリアと機能にのみアクセスできます。

于 2013-09-15T07:33:58.510 に答える