讨论的问题。
我们有 REST 服务 (WCF),在登录后 - 接收令牌并将其发送到客户端。HTTPS当然是定义的。
每个请求在"授权"标头中发送此令牌。
问题是,如果有人转储内存,他将能够获得令牌并随心所欲地使用它。
我们只能在发送之前保护此令牌,因为我们需要将其转换为 C# 字符串 - 无法显式释放。
因此,这种方法存在 2 个问题:
- 垃圾回收器移动托管对象,此字符串可以在内存中复制
- 字符串使用内部表进行管理。 它们是不可变的,无法根据请求清除。
是否有推荐的保护令牌的方法? 也许缓冲每个请求的标头一次 1 个字符?
很想听听你的想法。
你的帖子有点混乱,你是客户/消费者,还是服务/提供者?
如果您是提供商,您应该更关心启用HTTPS,您不会相信通过清晰的网络窃取令牌是多么容易,如果您的服务受到损害,那么转储内存仍然是您最少的问题。
也就是说,您正在寻找的是SecureString
您可以在此处找到更多信息
这里有一个小例子说明如何让它工作......
public void Example()
{
SecureString secureString = ConvertToSecureString("abc");
string normalString = ConvertToString(secureString);
Console.WriteLine (normalString);
}
// Secure it
public SecureString ConvertToSecureString(string password)
{
SecureString secureString = new SecureString();
foreach (char c in password.ToCharArray())
{
secureString.AppendChar(c);
}
return secureString;
}
// Unsecure it
public string ConvertToString(SecureString securePassword)
{
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
当您讨论该主题时,可能也值得查看 DPAPI......
这是我使用它的实用程序类之一
public void DpapiExample()
{
// Adds a level of entropy to our encryption making our encrypted data more secure
string entropy = "603e0f3a0ef74faf93b5e6bc2c2f7c358107";
var dpapi = new Dpapi(entropy);
string textToEncrypt = "I'm a secret";
string encryptedText;
dpapi.TryEncrypt(textToEncrypt, out encryptedText);
Console.WriteLine ("Encrypting");
Console.WriteLine (textToEncrypt);
Console.WriteLine (encryptedText);
string decryptedText;
dpapi.TryDecrypt(encryptedText, out decryptedText);
Console.WriteLine ("rnDecrypting");
Console.WriteLine (encryptedText);
Console.WriteLine (decryptedText);
}
public class Dpapi
{
private readonly byte[] entropy;
public Dpapi(string entropy)
{
this.entropy = Encoding.UTF8.GetBytes(entropy);
}
public Dpapi(string entropy, Encoding encoding)
{
this.entropy = encoding.GetBytes(entropy);
}
public bool TryDecrypt(string encryptedString, out string decryptedString)
{
if (string.IsNullOrWhiteSpace(encryptedString))
{
throw new ArgumentNullException("encryptedString");
}
decryptedString = string.Empty;
try
{
byte[] encryptedBytes = Convert.FromBase64String(encryptedString);
byte[] decryptedBytes = ProtectedData.Unprotect(encryptedBytes, this.entropy, DataProtectionScope.LocalMachine);
decryptedString = Encoding.UTF8.GetString(decryptedBytes);
}
catch
{
return false;
}
return true;
}
public bool TryEncrypt(string unprotectedString, out string encryptedString)
{
if (string.IsNullOrWhiteSpace(unprotectedString))
{
throw new ArgumentNullException("unprotectedString");
}
encryptedString = string.Empty;
try
{
byte[] unprotectedData = Encoding.UTF8.GetBytes(unprotectedString);
byte[] encryptedData = ProtectedData.Protect(unprotectedData, this.entropy, DataProtectionScope.LocalMachine);
encryptedString = Convert.ToBase64String(encryptedData);
}
catch
{
return false;
}
return true;
}
}