2010-07-30 80 views
7

更新時間:感謝幫助我在這裏已經創建了以下解決方案:屬性要求用戶登錄而不是拒絕訪問?

public class CustomAuthorize : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs 
     // If user is not logged in prompt 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
     // Otherwise deny access 
     else 
     { 
      filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary { 
       {"controller", "Account"}, 
       {"action", "NotAuthorized"} 
      }); 
     } 
    } 
} 

我從開始的NerdDinner和正在使用FormsAuthentication與ActiveDirectory中爲我的會員供應商。我已通過Global.asax & AccountController(下圖)添加了對角色的支持。

因此,現在在我的控制器中,我的「授權」屬性設置爲僅限admin角色(下圖)。我登錄的用戶是作者。當我點擊刪除時,它會要求我登錄,儘管我已經這樣做了。我在哪裏可以將邏輯返回拒絕訪問視圖?

的Global.asax.cs

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
    { 
     HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; 
     if (authCookie == null || authCookie.Value == "") 
     { 
      return; 
     } 

     FormsAuthenticationTicket authTicket = null; 

     try 
     { 
      authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
     } 
     catch 
     { 
      return; 
     } 

     if (Context.User != null) 
     { 
      string[] roles = authTicket.UserData.Split(new char[] { ';' }); 
      Context.User = new GenericPrincipal(Context.User.Identity, roles); 
     } 
    } 

AccountController.cs

[HttpPost] 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", 
     Justification = "Needs to take same parameter type as Controller.Redirect()")] 
    public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl) 
    { 

     if (!ValidateLogOn(userName, password)) 
     { 
      ViewData["rememberMe"] = rememberMe; 
      return View(); 
     } 

     // Make sure we have the username with the right capitalization 
     // since we do case sensitive checks for OpenID Claimed Identifiers later. 
     userName = this.MembershipService.GetCanonicalUsername(userName); 

     // Lookup user's (CWID) appropriate access level 
     string accessLevel = userRepository.FindUserByUserName(userName).AccessLevel.LevelName; 

     FormsAuthenticationTicket authTicket = new 
         FormsAuthenticationTicket(1, //version 
         userName, // user name 
         DateTime.Now,    //creation 
         DateTime.Now.AddMinutes(30), //Expiration 
         rememberMe, //Persistent 
         accessLevel); // hacked to use roles instead 

     string encTicket = FormsAuthentication.Encrypt(authTicket); 
     this.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)); 

     if (!String.IsNullOrEmpty(returnUrl)) 
     { 
      return Redirect(returnUrl); 
     } 
     else 
     { 
      return RedirectToAction("Index", "Home"); 
     } 
    } 

SpotlightController.cs

[Authorize(Roles="Admin")] 
    public ActionResult Delete(int id) 

回答

5

以下是AuthorizeAttribute的開箱即用功能:它檢查當前用戶是否獲得當前請求的授權,並且如果它們不是,則返回HHTP 401/UNAUTHORIZED,或者因爲它們未被記錄或者它們不在當前請求的授權用戶/角色列表中。

Web forms authentication HTTP module sees this 401 response, intercepts that, and turns it into an HTTP 302 (redirect) response to the login page(如果在web.config中配置了loginUrl屬性)。一般的想法是,如果用戶由於沒有登錄而被拒絕訪問網站,但他們想要做的下一件事是登錄。

因爲你想要做的是重定向到其他地方,Hal的建議壓倒一切的HandleUnauthorizedRequest和重定向並非不合理。請記住,如果您仍希望未經身份驗證的用戶查看登錄頁面(而不是通過身份驗證,但不在允許的用戶/角色列表中),那麼您必須爲此添加邏輯。我建議不要重寫AuthorizeCore或OnAuthorization;這些都不能解決問題,並且比HandleUnauthorizedRequest更容易搞砸。

+0

克雷格是絕對正確的 - 你將不得不處理角色異常與未經身份驗證的用戶。我認爲這不會太困難,但我沒有嘗試過,所以YMMV。 我也會建議不要搞亂AuthorizeCode或OnAuthorization,除非你真的想實現你自己的認證方案。 – Hal 2010-07-30 14:19:50

+0

我需要閱讀更多內容。與此同時,我可以使用一些幫助重寫HandleUnauthorizedRequest。我知道如何推出自己的繼承自AuthorizeAttribute的類,然後重寫HandleUnauthorizedRequest。我不需要我自己的屬性,因爲這是唯一改變的事情。那麼如何重寫HandleUnauthorizedRequest而不派生? – ryan 2010-07-30 14:45:01

+0

您必須派生一個新類型並覆蓋該方法。但是這種方法是你需要改變的唯一東西。 – 2010-07-30 14:48:16

2

我想你可以從AuthorizeAttribute派生,然後覆蓋HandleUnauthorizedRequest,把你的自己的重定向邏輯。

感謝,

哈爾

+0

我想我錯過了爲什麼HandleUnauthorizedRequest現在不做任何事情?或者我只是沒有捕獲該事件? – ryan 2010-07-30 12:47:26

+0

您在作者權限中登錄的用戶,而不是管理員? 希望的行爲是,具有不足特權的用戶將被重定向到異常頁面,而不是嘗試使用提升憑據登錄的頁面(我認爲這是缺省行爲)。 我理解正確嗎? – Hal 2010-07-30 12:52:24

+0

這是正確的! – ryan 2010-07-30 12:56:37

1

或者可以覆蓋授權屬性。您可以重寫OnAuthorization方法並從您的基地獲取來自AuthorizeCore方法的結果。根據該結果,您可以在OnAuthirziation中引發異常或自定義異常(即可能是一個記錄狀態的自定義安全異常)。