2010-08-30 31 views
6

Các mã sau đây tồn tại trong LogEntry.cs trong Logging Application Block Thư viện của Doanh nghiệp:Quyền không được quản lý. Nó là gì?

private bool UnmanagedCodePermissionAvailable 
{ 
    get 
    { 
    if (!unmanagedCodePermissionAvailableInitialized) 
    { 
     // check whether the unmanaged code permission is available to avoid three potential stack walks 
     bool internalUnmanagedCodePermissionAvailable = false; 
     SecurityPermission unmanagedCodePermission = 
        new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); 
     // avoid a stack walk by checking for the permission on the current assembly. this is safe because there are no 
     // stack walk modifiers before the call. 
     if (SecurityManager.IsGranted(unmanagedCodePermission)) 
     { 
     try 
     { 
      unmanagedCodePermission.Demand(); 
      internalUnmanagedCodePermissionAvailable = true; 
     } 
     catch (SecurityException) 
     { } 
     } 

     this.UnmanagedCodePermissionAvailable = 
      internalUnmanagedCodePermissionAvailable; 
    } 

    return this.unmanagedCodePermissionAvailable; 
    } 
    set 
    { 
    this.unmanagedCodePermissionAvailable = value; 
    unmanagedCodePermissionAvailableInitialized = true; 
    } 
} 

Các hàm được gọi trước khi bất kỳ một số P/Gọi các cuộc gọi được thực hiện để lấy thông tin khác nhau để giúp điền vào các cấu trúc LogEntry . Nếu "UnmanagedCodePermission" không có sẵn, thì thuộc tính LogEntry tương ứng được đặt thành một chuỗi cho biết ("XXX không khả dụng").

Ví dụ, LogEntry muốn lấy id chuỗi Win32 và nó sử dụng hàm Win32, GetCurrentThreadId, được gọi bằng P/Invoke để lấy nó. Trước khi gọi GetCurrentThreadId, nó sẽ kiểm tra xem "quyền mã unamanged" có sẵn hay không. Nếu vậy, nó làm cho cuộc gọi, nếu không, nó không. Một cái gì đó như thế này:

private void InitializeWin32ThreadId() 
{ 
    if (this.UnmanagedCodePermissionAvailable) 
    { 
    try 
    { 
     this.Win32ThreadId = LogEntryContext.GetCurrentThreadId(); 
    } 
    catch (Exception e) 
    { 
     this.Win32ThreadId = string.Format(
            CultureInfo.CurrentCulture, 
            Properties.Resources.IntrinsicPropertyError, 
            e.Message); 
    } 
    } 
    else 
    { 
    this.Win32ThreadId = string.Format(CultureInfo.CurrentCulture, 
       Properties.Resources.IntrinsicPropertyError, 
       Properties.Resources. 
       LogEntryIntrinsicPropertyNoUnmanagedCodePermissionError); 
    } 
} 

Từ những gì tôi hiểu, trong đó, phải thừa nhận, không phải là nhiều, thực hiện cuộc gọi đến unmanaged code (ví dụ P/Invoke) không phải lúc nào cũng có thể do an ninh/permissions/tin tưởng. Có kiểm tra này để xem liệu các cuộc gọi mã không được quản lý có thể thực hiện được hay không, làm cho nó có thể bảo vệ tất cả các cuộc gọi không được quản lý một cách thống nhất.

Khi tôi biên dịch mã này, tôi nhận được một cảnh báo về dòng này:

  if (SecurityManager.IsGranted(unmanagedCodePermission)) 

Đây là cảnh báo:

System.Security.SecurityManager.IsGranted (System.Security.IPermission) đã lỗi thời: 'IsGranted đã lỗi thời và sẽ bị xóa trong bản phát hành .NET Framework trong tương lai. Vui lòng sử dụng thuộc tính PermissionSet của AppDomain hoặc Assembly thay thế.

(Lưu ý rằng tôi đang xây dựng tính năng này trên .Net 4.0 sử dụng VS2010).

Vì vậy, có vẻ IsGranted đã lỗi thời. Tôi nhìn vào thuộc tính PermissionSet cho AppDomain và Assembly, và nó không rõ ràng chính xác cách thực hiện kiểm tra tương tự.

Trong trường hợp của LogEntry, có vẻ như thông tin này không quan trọng, do đó, nó không được coi là một thất bại quan trọng nếu không được phép quản lý không có sẵn. Hãy xem xét các câu hỏi sau đây từ cùng một quan điểm. Đó là, nếu không được phép quản lý mã không có sẵn, nó không phải là một việc lớn, tôi có thể sống mà không có thông tin.

Cuối cùng, một vài câu hỏi:

  1. có phải là một ý tưởng tốt để cố gắng bảo vệ các cuộc gọi đến unmanaged code (ví dụ P/Invoke)? Đôi khi, luôn luôn, không bao giờ?

  2. Nếu bạn nên bảo vệ các cuộc gọi này, đây có phải là mô hình hợp lý để làm như vậy không? Có cách nào tốt hơn?

  3. Cách nào chính xác (ví dụ: không lỗi thời) để thực hiện đăng ký tương đương .Net 4.0?

Trả lời

8

Trước .NET 4, Mã bảo mật truy cập (CAS) là mô hình bảo mật được .NET Fx sử dụng. Ý tưởng là để xác định những gì mã có thể làm dựa trên bằng chứng và không cho phép để làm điều đó bất kỳ những thứ khác (SandBoxing). Ví dụ, mã hiện tại trên máy tính cục bộ của bạn theo mặc định được tin cậy đầy đủ (về cơ bản nó có thể làm bất cứ điều gì) trong khi mã đến từ internet sẽ có các quyền hạn chế (một phần tin cậy).

IMO, nếu bạn đang viết mã không có khả năng chạy trong môi trường đáng tin cậy một phần thì bạn có thể không quan tâm nhiều về nó. Tuy nhiên đối với các hội đồng được ủy thác một phần,

  1. Nếu họ có thể nói với máy chủ của họ (ví dụ như IE), quyền truy cập cần thiết là máy chủ nào có thể quyết định có cấp phép hay không. để ghi đè. Hoặc quản trị viên sẽ biết sự cho phép được thiết lập bằng cách kiểm tra lắp ráp và anh ta có thể quyết định cập nhật chính sách để cho phép nó.
  2. Trong trường hợp, máy chủ không cấp quyền cần thiết cho mã thì mã có thể kiểm tra và xử lý nó một cách duyên dáng thay vì tạo ra ngoại lệ bảo mật.

Vì vậy, mã trên minh họa các cách để đạt được điều này trước .NET. 4. Trong .NET 4, có mô hình bảo mật mới đơn giản hơn để sử dụng. Xem this & this bài viết để biết thêm thông tin.

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