1

私は VS 2011 を使用して asp.net MVC 4 アプリに取り組んでいます。特定のロールのメンバーでない場合にアクセス拒否ページにリダイレクトするユーザーのロールを決定するカスタム AuthorizeAttribute を持つカスタム ロール プロバイダーがあります。 . これまでに行ったことは、コントローラー アクションをカスタム属性で装飾すると機能しますが、属性をコントローラーに追加すると、IE と FF でさまざまなエラーが発生して失敗します。私のカスタム属性:

public class AccessDeniedAuthorizeAttribute : AuthorizeAttribute
{
    public string RedirectActionName { get; set; }
    public string RedirectControllerName { get; set; }
    private IAccountRepository _accountRepository;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var user = httpContext.User;
        this._accountRepository = new AccountRepository();
        var accessAllowed = false;    
        var allowedRoles = this.Roles.Split(',');

        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        // Get roles for current user
        var roles = this._accountRepository.GetRoles(user.Identity.Name);

        foreach (var allowedRole in allowedRoles)
        {
            if (roles.Contains(allowedRole))
            {
                accessAllowed = true;
            }
        }

        if (!accessAllowed)
        {
            return false;
        }

        return base.AuthorizeCore(httpContext);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.Result is HttpUnauthorizedResult)
        {   
            var values = new RouteValueDictionary(new
            {
                action = this.RedirectActionName == "" ? "AccessDenied" : this.RedirectActionName,
                controller = this.RedirectControllerName == "" ? "Home" : this.RedirectControllerName
            });

            filterContext.Result = new RedirectToRouteResult(values);
        }
    }
}

また、RegisterGlobalFilters にグローバル属性を追加します (これを削除しようとしましたが、それでも同じ問題が発生します)。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new System.Web.Mvc.AuthorizeAttribute());
}

アクションを属性で装飾すると、正常に動作します。

[AccessDeniedAuthorize(RedirectActionName = "AccessDenied", RedirectControllerName = "Home", Roles = "propdat")]
public ActionResult Index()
{
    this.ViewBag.Message = "Welcome.";

    return this.View();
}

しかし、コントローラーに追加すると、完全に壊れます:

[AccessDeniedAuthorize(RedirectActionName = "AccessDenied", RedirectControllerName = "Home", Roles = "propdat")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        this.ViewBag.Message = "Welcome.";

        return this.View();
    }

    public ActionResult AccessDenied()
    {
        this.ViewBag.Message = "You are not authorised to view this page. Please contact your administrator.";

        return this.View();            
    }
}

ロールは、リポジトリを介してデータベースから返されますが、これは問題ないようです。IE では標準の「Internet Explorer では Web ページを表示できません」というエラーが表示され、Firefox では非常に奇妙なエラーが表示されます。

ページが正しくリダイレ​​クトされていません
Firefox は、サーバーがこのアドレスへのリクエストを決して完了しない方法でリダイレクトしていることを検出しました。

  • この問題は、Cookie の受け入れを無効にするか拒否することによって発生することがあります。

IE では、URL はホーム URL のままです。

http://localhost:1989

ただし、属性で指定したビューに URL が変更されると、FF はリダイレクトを実行します。

http://localhost:1989/Home/AccessDenied
4

2 に答える 2

2

あなたのコードをもう一度見てください:)

あなたはあなたで飾ってHomeControllerいますAccessDeniedAuthorizeAttributeが、あなたには否定できなかったHomeControllerあなたの行動が含まれています。AccessDenied

したがって、問題は、現在のユーザーをアクションAccessDeniedAuthorizeAttributeにリダイレクトしようとするたびに false になり、循環ループにロードされます。AccessDeniedaccessAllowed

解決策は次のとおりです。

アクションを別の「 HelperController AccessDenied」に配置し、この HelperController を属性で装飾しないでください。

HomeControllerまたは、アクションを除くすべてのアクションにこの属性を追加しAccessDeniedます。

于 2012-06-04T10:21:42.700 に答える
1

あなたがする必要があるのは次のことだと思います:

  1. グローバル フィルターを削除します。これにより、すべての MVC コントローラー (WebAPI ではない) のすべてのアクションがロックされます。ユーザーが認証されていないか、承認されていない場合、フレームワークは 'login url' 設定へのリダイレクトを返します ( authentication > forms 要素にあります - フォーム認証を使用していると仮定します) - グローバル フィルターはカスタム属性のリダイレクト URL を使用しないことに注意してください。

  2. カスタム属性をホーム コントローラーに配置し、[AllowAnonymous] 属性を AccessDenied アクションに追加します。最も重要なことは、このコードをカスタム属性に追加することです ([AllowAnonymous] 属性を使用したアクションをスキップするために必要です)。

        bool skipAuthorization = 
        filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true) 
        || 
        filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);
    
        if (skipAuthorization)
        {
            return;
        }
    

ところで、Firefox が伝えていることは、無限のリダイレクト ループが発生しているということです...最初のリクエストが承認されていないため、フレームワークはログイン URL にリダイレクトしますが、そのリクエストは承認チェックによってキャッチされ、それ自体がリダイレクトされます...などブラウザがあきらめてループを停止するまで、など。

于 2014-04-21T11:19:15.730 に答える