簡體   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