簡體   English   中英

在自定義Authorize屬性中覆蓋AuthorizeCore會導致“找不到合適的方法來覆蓋”錯誤

[英]Overriding AuthorizeCore in custom Authorize attribute results in “no suitable method found to override” error

我正在嘗試構建自定義AuthorizeAttribute,所以在我的Core項目(類庫)中我有這樣的代碼:

using System;
using System.Web;
using System.Web.Mvc;
using IVC.Core.Web;
using System.Linq;

namespace IVC.Core.Attributes
{
    public class TimeShareAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if(!httpContext.Request.IsAuthenticated)
                return false;

            var rolesProvider = System.Web.Security.Roles.Providers["TimeShareRoleProvider"];

            string[] roles = rolesProvider.GetRolesForUser(httpContext.User.Identity.Name);

            if(roles.Contains(Website.Roles.RegisteredClient, StringComparer.OrdinalIgnoreCase))
            {
                return true;
            }

            return false;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectResult("/TimeShare/Account/LogOn");

            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

當我嘗試構建該東西時,我收到此錯誤:錯誤2'IVC.Core.Attributes.TimeShareAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase)': 找不到合適的方法來覆蓋 ...

我在這里錯過了什么嗎? 我已經搜索了所有網站,但我找到的每個網站都告訴我要完成我在這里所做的事情。 我正在使用mvc2 btw。

  • 編輯添加:如果我在同一個解決方案中將類移動到mvc項目,則沒有編譯器錯誤。

是的,我也偶然發現了那個,並從對象瀏覽器中弄明白了。 除非你一直向下滾動到HttpContextBase類的用戶注釋,否則從MSDN文檔中肯定不清楚。 當然,網上有很多例子,但是沒有人能夠顯示完整的類文件! :)

嘗試將對System.Web.Abstractions的引用添加到項目中。

更新:剛從MSDN注意到在v3.5下,它在System.Web.Abstractions下,但在v4下,它在System.Web下。

這是AuthorizationAttribute.cs

/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/

namespace System.Web.Mvc {
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq;
    using System.Security.Principal;
    using System.Web;

[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "Unsealed so that subclassed types can set properties in the default constructor or override our behavior.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter {

        private string _roles;
        private string[] _rolesSplit = new string[0];
        private string _users;
        private string[] _usersSplit = new string[0];

        public string Roles {
            get {
                return _roles ?? String.Empty;
            }
            set {
                _roles = value;
                _rolesSplit = SplitString(value);
            }
        }

        public string Users {
            get {
                return _users ?? String.Empty;
            }
            set {
                _users = value;
                _usersSplit = SplitString(value);
            }
        }

        // This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
        protected virtual bool AuthorizeCore(HttpContextBase httpContext) {
            if (httpContext == null) {
                throw new ArgumentNullException("httpContext");
            }

            IPrincipal user = httpContext.User;
            if (!user.Identity.IsAuthenticated) {
                return false;
            }

            if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) {
                return false;
            }

            if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) {
                return false;
            }

            return true;
        }

        private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        public virtual void OnAuthorization(AuthorizationContext filterContext) {
            if (filterContext == null) {
                throw new ArgumentNullException("filterContext");
            }

            if (AuthorizeCore(filterContext.HttpContext)) {
                // ** IMPORTANT **
                // Since we're performing authorization at the action level, the authorization code runs
                // after the output caching module. In the worst case this could allow an authorized user
                // to cause the page to be cached, then an unauthorized user would later be served the
                // cached page. We work around this by telling proxies not to cache the sensitive page,
                // then we hook our custom authorization code into the caching mechanism so that we have
                // the final say on whether a page should be served from the cache.

                HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
            }
            else {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }

        // This method must be thread-safe since it is called by the caching module.
        protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) {
            if (httpContext == null) {
                throw new ArgumentNullException("httpContext");
            }

            bool isAuthorized = AuthorizeCore(httpContext);
            return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest;
        }

        internal static string[] SplitString(string original) {
            if (String.IsNullOrEmpty(original)) {
                return new string[0];
            }

            var split = from piece in original.Split(',')
                        let trimmed = piece.Trim()
                        where !String.IsNullOrEmpty(trimmed)
                        select trimmed;
            return split.ToArray();
        }

    }
}

此外,由於我之前已經看到過這種情況,因此請小心讓Visual Studio自動添加使用。 如果您沒有注意,最終可能會添加System.Web.Http而不是System.Web.Mvc。

當我將舊代碼復制到我的新項目時,發生了同樣的問題。

事實證明,有2個AuthrizeAttributes。 一個在System.Web.Mvc中,另一個在System.Web.Http中。 Mvc有一個AuthrizeCore,而Http沒有。

您可能需要添加對System.Web.Mvc的引用以訪問正確的引用。

我也有這個錯誤。 原來,Visual Studio默認添加到我的ActionFilter:

使用System.Web.Http;

即使我添加了System.Web.Mvc,我仍然遇到錯誤。 注釋掉System.Web.Http並且只是使用System.Web.Mvc似乎為我解決了這個問題。

希望這可能對某人有所幫助!

使用System.Web.Mvc命名空間。

示例代碼:

using System.Web.Mvc;

public class CustomAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        var service = new AuthService();
        return service.GetCurrentUser() != null;
    }

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

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
    }
}

在fw v4.5下,它現在顯然在System.Web.Mvc下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM