2010-08-15 22 views
25

我試圖構建自定義AuthorizeAttribute,所以在我的核心項目(類庫),我有這樣的代碼:重寫AuthorizeCore定製授權屬性導致「沒有合適的方法來否定」的錯誤

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項目沒有編譯器錯誤。
+0

該方法的簽名和使用看起來幾乎相同的東西,對我來說很好...... – Tahbaza 2010-08-15 17:13:23

+1

你引用了什麼版本的'System.Web.Mvc'程序集? – 2010-08-16 07:31:43

+0

2.0我認爲這是問題,但我檢查和雙重檢查和三重檢查......我結束了離開Web應用程序中的屬性繼續前進,但我很想知道爲什麼它會給出編譯器錯誤,如果我移動它到一個類庫。 – JoseMarmolejos 2010-08-16 12:33:27

回答

29

是的,我也摸索了一段時間,並從對象瀏覽器中找出它。它肯定不是從MSDN文檔清楚,除非您一直向下滾動到HttpContextBase類的用戶註釋。當然,網絡上有很多例子,但沒有人能夠顯示完整的課程文件! :)

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

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

+0

我正在使用mvc 5.2.3。在我的情況下,即使我在我的項目中引用了'System.Web.Abstractions',我沒有使用'using'關鍵字導入命名空間 – 2018-01-18 07:35:03

23

這裏是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(); 
     } 

    } 
} 
6

而且,因爲我已經看到這種情況發生前,小心讓Visual Studio中自動添加usings你。如果你不注意,你最終可能會添加System.Web.Http而不是System.Web.Mvc。

0

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

2

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

原來,有2個AuthrizeAttributes。一個在System.Web.Mvc中,另一個在System.Web.Http中。 Mvc有AuthrizeCore,而Http沒有。

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

0

使用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); 
    } 
} 
1

我也有這種錯誤。事實證明,Visual Studio默認添加到了我的ActionFilter中:

using System.Web.Http;

即使當我添加System.Web.Mvc我仍然有錯誤。註釋掉System.Web.Http並使用System.Web.Mvc似乎爲我解決了這個問題。

希望這可以幫助別人!

相關問題