2010-07-30 61 views
7

Cập nhật: Nhờ sự giúp đỡ ở đây tôi đã tạo ra các giải pháp sau đây:thuộc tính yêu cầu người dùng đăng nhập thay vì truy cập bị từ chối?

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"} 
      }); 
     } 
    } 
} 

tôi bắt đầu từ NerdDinner và đang sử dụng FormsAuthentication với ActiveDirectory là nhà cung cấp thành viên của tôi. Tôi đã thêm hỗ trợ cho các vai trò thông qua db của tôi với Global.asax & AccountController (bên dưới).

Vì vậy, bây giờ trong bộ điều khiển của tôi tôi có thuộc tính ủy quyền của tôi thiết lập vai trò của quản trị chỉ (bên dưới). Người dùng đã đăng nhập của tôi là tác giả. Khi tôi nhấp vào xóa nó yêu cầu tôi đăng nhập ngay cả khi tôi đã làm như vậy. Tôi có thể đặt logic để trả lại chế độ xem bị từ chối truy cập ở đâu?

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) 

Trả lời

5

Đây là những gì AuthorizeAttribute thực hiện, out-of-the-box: Nó kiểm tra xem người dùng hiện tại có được phép cho yêu cầu hiện tại hay không và trả về HHTP 401/UNAUTHORIZED nếu không, hoặc vì họ không đăng nhập trong tất cả, hoặc họ không có trong danh sách người dùng/vai trò được ủy quyền cho yêu cầu hiện tại.

Web forms authentication HTTP module sees this 401 response, intercepts that, and turns it into an HTTP 302 (redirect) response to the login page, nếu thuộc tính loginUrl được định cấu hình trong web.config. Suy nghĩ chung là nếu người dùng bị từ chối truy cập vào trang web vì họ không đăng nhập, nhưng điều tiếp theo họ sẽ muốn làm là đăng nhập.

Vì những gì bạn muốn làm là chuyển hướng đến nơi khác, đề nghị của Hal ghi đè lên HandleUnauthorizedRequest và chuyển hướng không phải là không hợp lý. Chỉ cần nhớ rằng nếu bạn vẫn muốn người dùng không được xác thực xem trang đăng nhập (trái với xác thực, nhưng không có trong danh sách người dùng/vai trò được phép), thì bạn sẽ phải thêm logic cho điều đó. Tôi khuyên bạn nên chống lại ý tưởng của AuthorizeCore hoặc OnAuthorization; không thực sự trong số này giải quyết được vấn đề, và chúng dễ dàng hơn nhiều so với HandleUnauthorizedRequest.

+0

Craig là hoàn toàn đúng - bạn sẽ phải xử lý một vai trò ngoại lệ so với một người dùng không được thẩm định. Tôi không nghĩ điều đó sẽ quá khó, nhưng tôi chưa thử YMMV. Tôi cũng khuyên bạn không nên can thiệp vào AuthorizeCode hoặc OnAuthorization trừ khi bạn thực sự muốn triển khai chương trình xác thực của riêng mình. – Hal

+0

Tôi cần đọc thêm. Trong thời gian chờ đợi, tôi có thể sử dụng một số trợ giúp với HandleUnauthorizedRequest. Tôi hiểu làm thế nào để cuộn lớp của riêng tôi mà kế thừa từ AuthorizeAttribute và sau đó ghi đè HandleUnauthorizedRequest. Tôi không cần thuộc tính của riêng mình vì đây là điều duy nhất tôi thay đổi. Vậy làm thế nào để ghi đè lên HandleUnauthorizedRequest mà không phát sinh? – ryan

+0

Bạn phải lấy được một loại mới và ghi đè phương thức đó. Nhưng phương pháp đó là điều duy nhất bạn cần thay đổi. –

2

Tôi cho rằng bạn có thể bắt nguồn từ AuthorizeAttribute và sau đó ghi đè HandleUnauthorizedRequest và đặt bạn logic chuyển hướng riêng tại đó.

Cảm ơn,

Hal

+0

Tôi đoán tôi đang thiếu lý do tại sao HandleUnauthorizedRequest hiện không làm bất cứ điều gì? Hay tôi chỉ không chụp được sự kiện đó? – ryan

+0

Người dùng đã đăng nhập của bạn trong quyền Tác giả, không phải là Quản trị viên? Hành vi mong muốn là người dùng có đủ đặc quyền sẽ được chuyển hướng đến trang ngoại lệ, không phải trang cố gắng đăng nhập bằng thông tin đăng nhập nâng cao (mà tôi tin là hành vi mặc định). Tôi có hiểu chính xác không? – Hal

+0

Đúng vậy! – ryan

1

Hoặc bạn có thể ghi đè lên các thuộc tính Authorize. Bạn sẽ ghi đè lên phương thức OnAuthorization và nhận kết quả từ phương thức AuthorizeCore từ cơ sở của bạn. Dựa trên kết quả đó, bạn có thể ném ngoại lệ hoặc ngoại lệ tùy chỉnh (ví dụ: Có thể ngoại lệ bảo mật tùy chỉnh ghi nhật ký trạng thái) ngay từ trong OnAuthirziation.

Các vấn đề liên quan