<machineKey>這個節允許你設置用於加密數據和創建數字簽名的服務器特定的密鑰。ASP.NET自動使用它來保護表單驗證Cookie,你也可以將它用於受保護的視圖狀態數據。同時,這個密鑰還用於驗證進程外的會話狀態提供程序。
如果你在使用Web集群並在多台計算機上運行同一個應用程序,如果對頁面的請求由一台計算機處理,而頁面回發又由另一台計算機處理,第二個服務器就不能解密來自第一台服務器的視圖狀態和表單Cookie。這個問題之所以會發生,是因為兩台服務器使用了不同的密鑰。
要解決這個問題,你必須顯式的在machine.config文件中定義這個密鑰:
<machineKey validationKey = "6efa......." decryptionKey = "ACE09876A7......." />
其中,validationKey 的值可以是48到128個字符長,強烈建議使用可用的最長密鑰。decryptionKey 的值可以是16到48字符長,建議使用48字符長。
自己去手動創建驗證密鑰和解密密鑰並沒有多大的意義。如果你這么做的話,它們可能隨機性不足,這就可能允許某種類型的攻擊。更好的辦法是使用代碼和.NET加密類(System.Security.Cryptography 命名空間)生成隨機密鑰,代碼如下:
using System;
using System.Security.Cryptography;
using System.Text;
/// <summary>
/// 各類工具
/// </summary>
public class Tools
{
/// <summary>
/// 使用加密服務提供程序實現加密生成隨機數
/// </summary>
/// <param name="length"></param>
/// <returns>16進制格式字符串</returns>
public static string CreateMachineKey(int length)
{
// 要返回的字符格式為16進制,byte最大值255
// 需要2個16進制數保存1個byte,因此除2
byte[] random = new byte[length / 2];
// 使用加密服務提供程序 (CSP) 提供的實現來實現加密隨機數生成器 (RNG)
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
// 用經過加密的強隨機值序列填充字節數組
rng.GetBytes(random);
StringBuilder machineKey = new StringBuilder(length);
for (int i = 0; i < random.Length; i++)
{
machineKey.Append(string.Format("{0:X2}", random[i]));
}
return machineKey.ToString();
}
}
調用:
string decryptionKey = Tools.CreateMachineKey(48);
string validationKey = Tools.CreateMachineKey(128);
使用這個方法可以創建需要的密鑰,然后可以復制這些信息並粘貼到Web集群中每台計算機的machine.config文件中,這要比手工創建密鑰更安全,更便捷。