2010-06-09 38 views
8

Chúng tôi đang sử dụng ASP.NET với rất nhiều lời gọi AJAX "Page Method". Các dịch vụ Web được định nghĩa trong Trang gọi các phương thức từ BusinessLayer của chúng tôi. Để ngăn các tin tặc gọi phương thức trang, chúng tôi muốn thực hiện một số bảo mật trong BusinessLayer.Tạo phương thức bảo mật cho lớp doanh nghiệp. thực hành tốt nhất/mô hình tốt nhất

Chúng tôi đang đấu tranh với hai vấn đề khác nhau.

Đầu tiên một:

public List<Employees> GetAllEmployees() 
{ 
    // do stuff 
} 

Phương pháp này nên được gọi là bởi người sử dụng ủy quyền với vai trò "nhân sự".

Second một:

public Order GetMyOrder(int orderId) 
{ 
    // do sutff 
} 

Phương pháp này chỉ nên được gọi là chủ sở hữu của Dòng.

Tôi biết đó là dễ dàng để thực hiện bảo mật cho từng phương pháp như:

public List<Employees> GetAllEmployees() 
{ 
    // check if the user is in Role HR 
} 

hoặc

public Order GetMyOrder(int orderId) 
{ 
    // check if the order.Owner = user 
} 

Những gì tôi đang tìm kiếm là một số mô hình/thực hành tốt nhất để thực hiện các loại bảo mật này theo một cách chung chung (nếu không có mã hóa nếu sau đó khác mọi lúc) Tôi hy vọng bạn hiểu ý tôi là :-)

+1

Tôi thấy bạn đã tham gia SO một thời gian. Tuy nhiên, tôi sẽ đề nghị bạn để thẻ ([.net/C#]) ra khỏi tiêu đề. Hãy để họ ở lại trong các thẻ. Ngoài ra, "Xin chào" và "Cảm ơn", trong khi thích hợp cho một diễn đàn thảo luận, không thích hợp cho một trang Hỏi & Đáp như SO. Cảm ơn. –

+0

@John ok. Cảm ơn các gợi ý. – gsharp

Trả lời

9

Người dùng @mdma mô tả một chút về Lập trình hướng Aspect. Đối với điều này, bạn sẽ cần phải sử dụng một thư viện bên ngoài (chẳng hạn như PostSharp tuyệt vời), bởi vì .NET không có nhiều chức năng AOP. Tuy nhiên, .NET đã có một cơ chế AOP cho bảo mật dựa trên vai trò, có thể giải quyết một phần vấn đề của bạn. Hãy xem ví dụ sau đây của mã NET tiêu chuẩn:

[PrincipalPermission(SecurityAction.Demand, Role="HR")] 
public List<Employees> GetAllEmployees() 
{ 
    // do stuff 
} 

Các PrincipalPermissionAttribute là một phần của không gian tên System.Security.Permissions và là một phần của .NET (kể từ NET 1.0). Tôi đã sử dụng nó trong nhiều năm nay để thực hiện bảo mật dựa trên vai trò trong các ứng dụng web của tôi. Điều tốt đẹp về thuộc tính này là trình biên dịch .NET JIT thực hiện tất cả việc dệt cho bạn trên nền và thậm chí bạn có thể định nghĩa nó trên một cấp lớp. Trong trường hợp đó tất cả các thành viên thuộc loại đó sẽ kế thừa thuộc tính đó và các thiết lập bảo mật của nó.

Tất nhiên nó có những hạn chế của nó. Không thể triển khai mẫu mã thứ hai của bạn bằng thuộc tính bảo mật dựa trên vai trò .NET. Tôi nghĩ bạn không thể thực sự tìm thấy một số kiểm tra bảo mật tùy chỉnh trong phương pháp này hoặc gọi một số thư viện bảo mật nội bộ.

public Order GetMyOrder(int orderId) 
{ 
    Order o = GetOrderInternal(orderId); 
    BusinessSecurity.ValidateOrderForCurrentUser(o); 
} 

Tất nhiên bạn có thể sử dụng khung công tác AOP nhưng bạn vẫn phải viết thuộc tính khung đặc biệt sẽ gọi lại lớp bảo mật của riêng bạn. Điều này sẽ chỉ hữu ích khi một thuộc tính như vậy sẽ thay thế nhiều cuộc gọi phương thức, ví dụ khi phải đặt mã bên trong try, catch, finally statements. Khi bạn thực hiện một cuộc gọi phương thức đơn giản, sẽ không có nhiều khác biệt giữa một cuộc gọi phương thức đơn lẻ hoặc một thuộc tính IMO duy nhất.

Khi bạn đang trở về một bộ sưu tập của các đối tượng và muốn lọc ra tất cả các đối tượng mà người sử dụng hiện nay không có quyền thích hợp, LINQ cây biểu thức có thể có ích:

public Order[] GetAllOrders() 
{ 
    IQueryable orders = GetAllOrdersInternal(); 
    orders = BusinessSecurity.ApplySecurityOnOrders(orders); 
    return orders.ToArray(); 
} 

static class BusinessSecurity 
{ 
    public static IQueryable<Order> ApplySecurityOnOrders(
     IQueryable<Order> orders) 
    { 
     var user = Membership.GetCurrentUser(); 

     if (user.IsInRole("Administrator")) 
     { 
      return orders; 
     } 

     return 
      from order in orders 
      where order.Customer.User.Name == user.Name 
      select order; 
    } 
} 

Khi O/RM hỗ trợ LINQ thông qua các cây biểu thức (như NHibernate, LINQ to SQL và Entity Framework), bạn có thể viết một phương thức bảo mật như vậy một lần và áp dụng nó ở mọi nơi. Tất nhiên điều tốt đẹp về điều này là, rằng truy vấn đến cơ sở dữ liệu của bạn sẽ luôn luôn được tối ưu. Nói cách khác, không có thêm hồ sơ sẽ được lấy ra hơn cần thiết.

UPDATE (năm sau):

tôi sử dụng thuộc tính này trong một thời gian dài trong cơ sở mã của tôi, nhưng vài năm trở lại, tôi đi đến kết luận rằng thuộc tính dựa AOP có nhược điểm khủng khiếp. Ví dụ, nó cản trở khả năng kiểm tra. Vì mã bảo mật được dệt bằng mã thông thường, bạn không thể chạy các kiểm tra đơn vị bình thường mà không phải mạo danh người dùng hợp lệ. Điều này là giòn và không phải là một mối quan tâm của các bài kiểm tra đơn vị (đơn vị kiểm tra chính nó vi phạm nguyên tắc trách nhiệm duy nhất). Bên cạnh đó, nó buộc bạn phải xả rác cơ sở mã của bạn với thuộc tính đó.

Vì vậy, thay vì sử dụng PrincipalPermissionAttribute, tôi thay vì áp dụng các mối quan tâm chéo như bảo mật bằng mã gói với decorators. Điều này làm cho ứng dụng của tôi linh hoạt hơn và dễ kiểm tra hơn nhiều. Tôi đã viết một số bài viết về kỹ thuật này trong vài năm qua (ví dụ: this onethis one).

0

Nếu bạn đang sử dụng SOA, bạn có thể tạo Dịch vụ bảo mật, và mỗi hành động (phương thức) sẽ gửi ngữ cảnh của nó (UserId, OrderId, v.v.). Dịch vụ bảo mật biết về các quy tắc bảo mật kinh doanh.

Đề án có thể là cái gì đó như thế này

UI -> Security -> BLL -> DAL 
+0

bất kỳ mẫu/văn học nào? – gsharp

+1

Tôi đồng ý đặt mức bảo mật ở cấp ứng dụng chứ không phải ở cấp "Khung" như các câu trả lời khác. Điều gì sẽ xảy ra nếu vai trò năng động? –

2

One "thực hành tốt nhất" là thực hiện một khía cạnh an ninh. Điều này giữ cho các quy tắc bảo mật tách biệt khỏi logic nghiệp vụ chính, tránh viết mã cứng và giúp dễ dàng thay đổi các quy tắc bảo mật trong các môi trường khác nhau.

Bài viết dưới đây liệt kê 7 cách triển khai các khía cạnh và giữ mã riêng biệt. Một cách tiếp cận đơn giản và không thay đổi giao diện logic nghiệp vụ của bạn là sử dụng proxy. Điều này cho thấy cùng một giao diện như bạn hiện có, nhưng cho phép triển khai thay thế, có thể trang trí việc triển khai hiện tại. Các yêu cầu bảo mật có thể được đưa vào giao diện này, sử dụng các thuộc tính mã hóa hoặc tùy chỉnh cứng. Proxy chặn các cuộc gọi phương thức đến lớp nghiệp vụ của bạn và gọi các kiểm tra bảo mật thích hợp. Thực hiện đánh chặn thông qua proxy được mô tả chi tiết tại đây - Decouple Components by Injecting Custom Services into your Object's Invocation Chain. Các phương pháp AOP khác được đưa ra trong Understanding AOP in .NET.

Dưới đây là một số forum post thảo luận về bảo mật dưới dạng một khía cạnh, với việc triển khai sử dụng tư vấn và các thuộc tính bảo mật. Kết quả cuối cùng là

public static class Roles 
{ 
    public const string ROLE_ADMIN = "Admin"; 
    public const string ROLE_CONTENT_MANAGER = "Content Manager"; 
} 

// business method  
[Security(Roles.ROLE_HR)] 
public List<Employee> GetAllEmployees(); 

Bạn có thể đặt thuộc tính trực tiếp vào phương thức kinh doanh, ghép nối chặt chẽ hoặc tạo proxy dịch vụ với các thuộc tính này, vì vậy chi tiết bảo mật được giữ riêng biệt.

+0

Giải pháp này quá gắn với khung theo ý kiến ​​của tôi (bằng phương pháp trang trí). Tôi sẽ thực hiện các tính năng bảo mật là một phần của hệ thống vì nó không phải là bên ngoài của logic kinh doanh như nó có vẻ. Tôi thích đề xuất proxy mặc dù .. 2 xu của tôi. –

+0

@Mike - thuộc tính là của riêng bạn, vì vậy tôi không thấy cách này được gắn với bất kỳ khung công tác nào. Chúng là một chi tiết thực hiện - bảo mật khai báo hơn là viết mã. Bạn vẫn được tự do viết mã, nhưng tự đặt mã trên các đối tượng nghiệp vụ những gì OP nói rằng anh ta muốn tránh. Khi các thuộc tính được đặt trên các đối tượng kinh doanh, chúng vẫn "tách biệt" khỏi mã - tức là dễ nhận biết. Đây không phải là quá nhiều trường hợp nếu bạn thực hiện kiểm tra bảo mật dưới dạng mã và đặt mã đó vào với logic nghiệp vụ. – mdma

+0

Xin chào, tôi thấy nó giống như mã hóa. Đó là lý do tại sao tôi nói "khuôn khổ" xin lỗi. Nếu vai trò là gì? Tôi sẽ tạo các đối tượng bảo mật giống như các đối tượng "Người dùng" chẳng hạn như chúng là một phần của hệ thống giống như bất cứ thứ gì khác. –

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