2012-06-14 22 views
16

Tôi có một phương pháp điều khiển gọi là Edit trong đó người dùng có thể chỉnh sửa dữ liệu mà họ đã tạo ra như vậy ...ASP.NET MVC thuộc tính để chỉ cho phép người dùng chỉnh sửa/nội dung của riêng mình

public ActionResult Edit(int id) 
{ 
    Submission submission = unit.SubmissionRepository.GetByID(id); 
    User user = unit.UserRepository.GetByUsername(User.Identity.Name); 

    //Make sure the submission belongs to the user 
    if (submission.UserID != user.UserID) 
    { 
     throw new SecurityException("Unauthorized access!"); 
    } 

    //Carry out method 
} 

phương pháp này hoạt động tốt tuy nhiên nó là một chút lộn xộn để đặt trong mọi phương pháp điều khiển chỉnh sửa. Mỗi bảng luôn có một UserID vì vậy tôi đã tự hỏi nếu có một cách dễ dàng hơn để tự động hóa điều này thông qua một thuộc tính [Authorize] hoặc một số cơ chế khác để làm cho mã sạch hơn.

Trả lời

24

Vâng, bạn có thể đạt được điều đó thông qua một tùy chỉnh Ủy quyền cho thuộc tính:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 

     var rd = httpContext.Request.RequestContext.RouteData; 

     var id = rd.Values["id"]; 
     var userName = httpContext.User.Identity.Name; 

     Submission submission = unit.SubmissionRepository.GetByID(id); 
     User user = unit.UserRepository.GetByUsername(userName); 

     return submission.UserID == user.UserID; 
    } 
} 

và sau đó:

[MyAuthorize] 
public ActionResult Edit(int id) 
{ 
    // Carry out method 
} 

và chúng ta hãy giả sử rằng bạn cần phải ăn dụ trình này mà chúng ta lấy vào tùy chỉnh thuộc tính làm thông số hành động để tránh nhấn cơ sở dữ liệu một lần nữa, bạn có thể thực hiện các thao tác sau:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var authorized = base.AuthorizeCore(httpContext); 
     if (!authorized) 
     { 
      return false; 
     } 

     var rd = httpContext.Request.RequestContext.RouteData; 

     var id = rd.Values["id"]; 
     var userName = httpContext.User.Identity.Name; 

     Submission submission = unit.SubmissionRepository.GetByID(id); 
     User user = unit.UserRepository.GetByUsername(userName); 

     rd.Values["model"] = submission; 

     return submission.UserID == user.UserID; 
    } 
} 

và sau đó:

[MyAuthorize] 
public ActionResult Edit(Submission model) 
{ 
    // Carry out method 
} 
+1

Cảm ơn bạn! Tôi sẽ làm điều này chung chung hơn. Giống như việc đệ trình thực hiện một giao diện được gọi là IUserOwnable có một UserID. Và sau đó vượt qua trong kho lưu trữ vào Thuộc tính nơi nó tìm nạp IUserOwnable và so sánh UserID đó của người dùng với UserID của IUserOwnable –

+0

Chắc chắn, điều này có thể được thực hiện như bạn muốn cho phù hợp với yêu cầu cụ thể của bạn. –

+0

Cách tiếp cận tốt đẹp. Tôi đã nhảy mà bây giờ nó sẽ có một thuộc tính được xây dựng trong đó –

-1

tôi khuyên bạn nên đọc lên trên AuthorizeAttribute (xem here). Ngoài ra, bạn có thấy this bài đăng không? Nó đi qua làm thế nào để ghi đè lên các thuộc tính xác thực thuộc tính và cách sử dụng IPrincipal và IIdentity.

1

Tôi khuyên bạn nên rút logic ra khỏi hành động/bộ điều khiển và xây dựng một lớp miền để xử lý logic đó.

Phương thức hành động thực sự chỉ nên xử lý việc nhận dữ liệu và gửi dữ liệu đến chế độ xem. Bạn có thể tạo ra một cái gì đó chung chung đủ để xử lý nhu cầu của bạn, nhưng cũng sẽ làm theo các nguyên tắc trách nhiệm duy nhất.

public class AuthorizedToEdit 
{ 
    protected override bool AuthorizeCore(string user, int itemId) 
    { 
     var userName = httpContext.User.Identity.Name; 

     var authUsers = SubmissionRepository.GetAuthoriedUsers(itemId); 

     return authUsers.Contains(user); 
    } 
} 

này cũng sẽ cho phép bạn có sự linh hoạt sau này để cho phép một cái gì đó như người dùng quản trị

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