2012-02-22 26 views
5

Tôi có dịch vụ ASP MVC3 an toàn sử dụng xác thực cơ bản. Sau khi tìm kiếm tràn ngăn xếp, tôi đã tạo mã sau đây.asp mvc 3 ActionFilter để xác thực cơ bản

public class BasicAuthentication : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var req = filterContext.HttpContext.Request; 
     if (String.IsNullOrEmpty(req.Headers["Authorization"])) 
     { 
      filterContext.Result = new HttpNotFoundResult(); 
     } 
     else 
     { 
      var credentials = System.Text.ASCIIEncoding.ASCII 
         .GetString(Convert.FromBase64String(req.Headers["Authorization"].Substring(6))) 
         .Split(':'); 
      var user = new { Name = credentials[0], Password = credentials[1] }; 
      if(!(user.Name == "username" && user.Password == "passwords")) 
      { 
       filterContext.Result = new HttpNotFoundResult(); 
      } 
     } 
    } 
} 

1) ActionFilter có phải là cách tốt nhất để làm điều này không?

2) Thiết lập bộ lọcContext.Result cách chính xác để từ chối truy cập vào phương pháp điều khiển?

3) Có điều gì tôi đang làm sai không?

Cảm ơn.

-Nick

+0

bạn đang sử dụng cơ bản cho các hình thức/tùy chỉnh loại auth với cơ bản (hai giai đoạn auth) hoặc vẫn còn sử dụng các tài khoản tên miền? –

Trả lời

12

1) Có phải cách ActionFilterAttribute cách tốt nhất để làm điều này?
Tôi nghĩ vậy. Cách tiếp cận này phản ánh việc thực hiện thuộc tính được xây dựng trong thuộc tính Authorize.

2) Cài đặt filterContext.Result cách chính xác để từ chối truy cập vào phương pháp điều khiển?
Có. Đó là những gì nó có cho. (1)

3) Tôi có làm gì sai không?

  • Bạn cho rằng nội dung của tiêu đề Cấp quyền ở định dạng chính xác và được mã hóa chính xác.
  • Bạn giả định rằng yêu cầu này là để xác thực cơ bản và không phải bất kỳ phương thức xác thực khác nào khác.
  • Tôi muốn sử dụng HttpUnauthorizedResult() để gửi lỗi http 401 thay vì lỗi http 404 qua HttpNotFoundResult().

Dưới đây trong việc triển khai mã của bạn (tôi cũng chắc chắn có vấn đề của nó).

public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     try 
     { 
      if (String.IsNullOrEmpty(filterContext.HttpContext.Request.Headers["Authorization"])) 
      { 
       filterContext.Result = new HttpUnauthorizedResult(); 
      } 
      else 
      { 
       if (filterContext.HttpContext.Request.Headers["Authorization"].StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase)) 
       { 
        string[] credentials = ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(filterContext.HttpContext.Request.Headers["Authorization"].Substring(6))).Split(':'); 

        if (credentials.Length == 2) 
        { 
         if (String.IsNullOrEmpty(credentials[0])) 
         { 
          filterContext.Result = new HttpUnauthorizedResult(); 
         } 
         else if (!(credentials[0] == "username" && credentials[1] == "passwords")) 
         { 
          filterContext.Result = new HttpUnauthorizedResult(); 
         } 
        } 
        else 
        { 
         filterContext.Result = new HttpUnauthorizedResult(); 
        } 
       } 
       else 
       { 
        filterContext.Result = new HttpUnauthorizedResult(); 
       } 
      } 

      base.OnActionExecuting(filterContext); 
     } 
     catch 
     { 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 
    } 

Ghi chú

  • Tôi chưa bao gồm kiểm tra ký tự không hợp cho tên người dùng và mật khẩu.
  • Tôi không thể giải quyết về cách thực hiện xử lý ngoại lệ vì vậy tôi đã đi với sự đơn giản.

Tài liệu tham khảo

(1) http://msdn.microsoft.com/en-us/magazine/gg232768.aspx

-2

1) Không, thuộc tính ActionFilter không phải là cách tiếp cận tốt để xác thực người dùng. (Như chúng ta cần phải xác thực một lần và thiết lập xác thực cookie, nên HttpContext.User sẽ vẫn được chứng thực cho đến khi cookie hết hạn)

2) Có, thiết filtercontext.Result là một cách lý tưởng để ngăn chặn truy cập. (Nhưng thay vì chỉ định HttpNotFoundResult, hãy sử dụng RedirectResult để chuyển hướng đến trang đăng nhập)

3) Tôi thực sự không hiểu tại sao lại thực hiện như vậy cho Ủy quyền. Cách tiếp cận tốt nhất sẽ là có một hành động sẽ nhận được dữ liệu đã đăng biểu mẫu (tên người dùng và mật khẩu). và sử dụng thuộc tính Authorize để ngăn không cho phép truy cập.

sau đây là mã từ ứng dụng mẫu MVC3 mặc định trong VS2010.

[HttpPost] 
    public ActionResult LogOn(LogOnModel model, string returnUrl) 
    { 
     if (ModelState.IsValid) 
     { 
      if (Membership.ValidateUser(model.UserName, model.Password)) 
      { 
       FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
       if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") 
        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
       { 
        return Redirect(returnUrl); 
       } 
       else 
       { 
        return RedirectToAction("Index", "Home"); 
       } 
      } 
      else 
      { 
       ModelState.AddModelError("", "The user name or password provided is incorrect."); 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 
+0

Tôi hiểu mẫu đăng nhập biểu mẫu và sử dụng mô hình đó cho một trang web thông thường. Làm thế nào điều này làm việc cho một dịch vụ an toàn? Người dùng cung cấp thông tin đăng nhập như thế nào? – Nikhil

+0

MVC vẫn an toàn bằng cách sử dụng xác thực biểu mẫu.Bạn đang tìm kiếm một số hệ thống/dịch vụ sẽ gọi uri mvc, chuyển thông tin đăng nhập mạng. Nếu bạn có thể viết cùng mã như trên trong phương thức OnActionExecuting, ** Trừ khi không phải tất cả mã của bạn được gọi bởi một API **) – Manas

+2

tôi nghĩ bạn đã hoàn thành bỏ qua các từ "dịch vụ" và "xác thực cơ bản" trong tiêu đề câu hỏi trong khi trả lời. – humblelistener

8

phiên bản refactored của Adrian

public class BasicAuthenticationAttribute : ActionFilterAttribute 
{ 
    private static readonly string AuthorizationHeader = "Authorization"; 
    private static readonly string BasicHeader = "Basic "; 
    private static readonly string Username = "username"; 
    private static readonly string Password = "password"; 
    private static readonly char[] Separator = ":".ToCharArray(); 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     try 
     { 
      if (!Authenticated(filterContext.HttpContext.Request)) 
       filterContext.Result = new HttpUnauthorizedResult(); 

      base.OnActionExecuting(filterContext); 
     } 
     catch 
     { 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 
    } 

    private bool Authenticated(HttpRequestBase httpRequestBase) 
    { 
     bool authenticated = false; 

     if (String.IsNullOrEmpty(httpRequestBase.Headers[AuthorizationHeader]) == false && 
      httpRequestBase.Headers[AuthorizationHeader].StartsWith(BasicHeader, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(
       httpRequestBase.Headers[AuthorizationHeader].Substring(BasicHeader.Length))).Split(Separator); 

      if (credentials.Length == 2 && credentials[0] == Username && credentials[1] == Password) 
      { 
       authenticated = true; 
      } 
     } 

     return authenticated; 
    } 
} 
+1

+1 cho thời gian và công sức. Rất hữu dụng. Tuy nhiên, điều kiện đầu tiên là nếu "không" được xác thực thì hãy nâng cấp HttpUnauthorisedResult. – fluent

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