繁体   English   中英

C#客户端-保护客户端计算机上的REST身份验证令牌

[英]C# client - securing REST authentication tokens on client machine

我想讨论的问题。

我们拥有REST服务(WCF),该服务在登录后-接收到令牌并将其发送给客户端。 HTTPS当然是定义的。

每个请求都会在“授权”标头中发送此令牌。

问题是,如果有人转储了内存,他将能够获取令牌并按自己的意愿使用它。

我们只能在发送之前确保此令牌的安全,因为我们需要将其转换为C#字符串-无法显式处理。

因此,此方法存在两个问题:

  1. 垃圾收集器移动托管对象,并且此字符串可以在内存中重复
  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 ("\r\nDecrypting");
    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;
   }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM