2013-08-26 43 views
6

Tôi muốn điều chỉnh các phím máy một cách linh hoạt trong mã trong khi chạy, cho một trang web lưu trữ ASP.NET MVC 4 IIS.Khóa máy ASP.NET đặt mã số

Phím máy, mã hóa và khóa xác thực cũng như thuật toán sử dụng, được lưu trữ trong cơ sở dữ liệu. Thay vì đọc các giá trị từ tệp web.config, tôi muốn chèn các giá trị đó trong khi khởi động ứng dụng và để cho hệ thống sử dụng các giá trị đó thay thế.

Có cách nào để thực hiện điều đó mà không phải thay đổi web.config chút nào (chỉ thay đổi cấu hình bộ nhớ)?

Tôi đã thử truy cập phần cấu hình nhưng nó được đánh dấu là chỉ đọc và cũng được niêm phong, vì vậy tôi không thể ghi đè IsReadOnly(). Tuy nhiên, có một setter đó là một chỉ báo, với tôi, rằng có thể có một cách để có khả năng loại bỏ cờ chỉ đọc.

var configSection = (MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey"); 
if (!configSection.IsReadOnly()) 
{ 
     configSection.ValidationKey = _platformInfo.MachineKey.ValidationKey; 
     configSection.DecryptionKey = _platformInfo.MachineKey.EncryptionKey; 
     ... 
} 

Có cách nào để thực hiện việc này không? Cách thay thế duy nhất tôi có thể thấy là sử dụng một phương pháp tùy chỉnh như AppHarbor, tuy nhiên tôi thà gắn bó với cách tiếp cận tích hợp nếu có thể.

Trong trường hợp ai đó hỏi tại sao tôi muốn làm điều đó, lý do là, điều này là dành cho một số lượng lớn các trang web giống hệt nhau đang chạy trong webfarm. Do đó, có các khóa không được tạo tự động là phải (phải giống nhau trên mỗi máy chủ). Ngoài ra, mỗi trang web phải được phân lập và không được chia sẻ cùng một khóa. Vì tất cả các trang web đều giống hệt nhau về thể chất, chúng chia sẻ cùng một vị trí thực tế. Đó là lý do tệp web.config không thể chứa cài đặt ứng dụng cụ thể.

Chỉnh sửa: Sẽ rất hữu ích khi xác nhận, ít nhất, nếu đơn giản là không thể. Như đã nói, người ta có thể sử dụng các phương thức mã hóa và xác thực tùy chỉnh, điều này sẽ tránh được việc sử dụng các cài đặt khóa máy hoàn toàn. Cảm ơn.

Trả lời

5

Không có cách nào để đặt chương trình này một khi ứng dụng web bắt đầu. Tuy nhiên, vẫn có thể đạt được mục tiêu của bạn.

Nếu mỗi ứng dụng đang chạy trong hồ bơi ứng dụng của riêng mình và nếu mỗi hồ bơi ứng dụng có danh tính riêng, hãy kiểm tra công tắc CLRConfigFile trong applicationHost.config. Bạn có thể sử dụng nhóm ứng dụng này để chèn một cấp cấu hình mới. Xem http://weblogs.asp.net/owscott/archive/2011/12/01/setting-an-aspnet-config-file-per-application-pool.aspx để biết ví dụ về cách sử dụng tính năng này. Bạn có thể thiết lập phần tử <system.web/machineKey> rõ ràng và độc đáo trong mỗi tệp cấu hình CLR tùy chỉnh của mỗi nhóm ứng dụng.

Đây là cơ chế tương tự được sử dụng bởi Azure Web Sites, GoDaddy và các máy chủ khác cần phải đặt các khóa máy rõ ràng mặc định trên cơ sở mỗi ứng dụng. Hãy nhớ ACL mỗi tệp .config đích một cách thích hợp cho nhóm ứng dụng sẽ truy cập vào nó.

+0

thanks a lot, giúp tôi (và hy vọng những người khác nữa). Thông thường các trang web lớn hơn đang sử dụng các hồ bơi ứng dụng riêng biệt. Nhưng các trang web nhỏ hơn có khả năng chia sẻ một hồ bơi ứng dụng. Nhưng chính xác những gì tôi cần, như tôi có thể xây dựng xung quanh đó. – michael81

+0

Cấu trúc của tệp cấu hình CLR tùy chỉnh có phải là "/configuration/system.web/machineKey" không?Có cách nào để hiển thị hoặc kiểm tra giá trị machineKey thực tế trên ứng dụng để xác nhận rằng tệp cấu hình CLR tùy chỉnh thực sự có hiệu lực đúng không? – John

+0

Có. Bạn có thể sử dụng ConfigurationManager.GetSection ("system.web/machineKey"), đưa đối tượng được trả về về MachineKeySection và xem các thuộc tính treo của nó để xác minh rằng các thay đổi của bạn đã được chọn chính xác. – Levi

2

Nó xấu xí, nhưng tôi đã có thể sử dụng phản ánh để tạm thời loại bỏ các bit chỉ đọc từ phần cấu hình, thiết lập các phím, sau đó khôi phục lại nó:

var getter = typeof(MachineKeySection).GetMethod("GetApplicationConfig", BindingFlags.Static | BindingFlags.NonPublic); 
var config = (MachineKeySection)getter.Invoke(null, Array.Empty<object>()); 

var readOnlyField = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 
readOnlyField.SetValue(config, false); 

config.DecryptionKey = myKeys.EncryptionKey; 
config.ValidationKey = myKeys.ValidationKey; 

readOnlyField.SetValue(config, true);