【问题标题】:How can I create a file that only my application can modify it?如何创建只有我的应用程序才能修改的文件?
【发布时间】:2022-06-25 04:33:57
【问题描述】:

如何创建只有我的应用程序才能修改的文件?我需要它,因为我有一个应用程序创建了一个存储用户信息的.txt 文件,我不希望用户能够通过文件资源管理器修改它,但我的应用程序应该能够创建它,修改它并删除它。

这是我的代码:

        public void Write(List<Queue> Queue)
        {
          try
          {
            CreateFile();
            using (FileStream Stream = new FileStream(Path, FileMode.Open))
            {
                using (StreamWriter file = new StreamWriter(Stream))
                {
                    string Data = JsonSerializer.Serialize(Queue);
                    file.Write(Data);
                    file.Flush();
                    file.Close();
                }
            }
        }
        catch (IOException ex)
        {
            Log.GetInstance().Write(ex.Message);
        }



public void CreateFile()
    {
        if (!FileExist)
        {
            File.Create(Path).Close();
        }
    }

    public List<Queue> ReadFile()
    {
        try
        {
            if (FileExist)
            {
                using (StreamReader file = new StreamReader(Path))
                {
                    string Data= file.ReadToEnd();
                    return JsonSerializer.Deserialize<List<Cola>>(Data);
                }
            }
        }
        catch (JsonException ex)
        {
            Log.GetInstance().Write(ex.Message);
        }
        catch (IOException ex)
        {
            Log.GetInstance().Write(ex.Message);
        }
        return null;
    }

【问题讨论】:

  • I don't want the user can modify it on from File Explorer - 为什么不呢?您的应用打算在文件中存储什么?可能有更好的方法来实现您的目标,但我们必须知道实际目标是什么。
  • 简短回答:你不能。长答案:您可以让用户更难,但您永远(!)无法阻止它,而且根本不值得付出努力。
  • 应用程序实际上无法以其他人无法做到的方式创建和维护文件(或任何其他本地存储的数据)。
  • 您可以保留文件内容的内存版本,如果文件与内存中的内容不匹配,您可以定期替换该文件,但此时即使拥有物理文件又有什么意义。这就是数据库的用途。
  • 您可以加密文件的内容,但其中的诀窍是保持解密密钥的秘密。你可以很难得到但不是不可能

标签: c# file


【解决方案1】:

据我所知,你不能。无论哪种方式,用户和/或管理员都可以访问该文件。但是,您可以通过对文件进行哈希处理并将哈希值与文件进行比较来检测修改

【讨论】:

    【解决方案2】:

    您可以加密文件以防止篡改。好吧,至少任何篡改都会损坏文件。

    CLR 有一种机制可以为特定用户加密数据,而无需单独生成和存储密钥。这使用了System.Security.Cryptography 中的ProtectedData.Protect()ProtectedData.Unprotect() 机制。

    这是一个测试程序。运行它,选择 1 存储数据,输入一些秘密然后退出。再次运行,选择2读取数据,就会出现密文。

    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("Do you want to 1. store data, 2. read data or 0. exit ?");
                Console.ForegroundColor = ConsoleColor.Gray;
                var input = Console.ReadLine();
    
                if (input.Length == 0 || input[0] == '0') break;
    
                if (input[0] == '1')
                {
                    Console.WriteLine("Type in a very secret message to store:");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    var text = Console.ReadLine();
                    Console.ForegroundColor = ConsoleColor.Gray;
                    if (text.Length > 0)
                    {
                        WriteToFile(text);
                    }
                }
    
                if (input[0] == '2')
                {
                    if (ReadFromFile(out string text))
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine(text);
                        Console.ForegroundColor = ConsoleColor.Gray;
                    }
                }
            }
        }
    
        const string filename = "data.enc";
    
        static bool WriteToFile(string text)
        {
            var fn = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename);
            var data = Encoding.Unicode.GetBytes(text);
            try
            {
                var cipher = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
                File.WriteAllBytes(fn, cipher);
                Console.WriteLine($"Encrypted {data.Length} bytes in {fn}.");
                return true;
            }
            catch (CryptographicException ex)
            {
                Console.WriteLine("Error encoding data: ");
                Console.WriteLine(ex.ToString());
            }
            catch (IOException ex)
            {
                Console.WriteLine("Error creating file: ");
                Console.WriteLine(ex.ToString());
            }
            return false;
        }
    
        static bool ReadFromFile(out string text)
        {
            var fn = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename);
            try
            {
                var cipher = File.ReadAllBytes(fn);
                var data = ProtectedData.Unprotect(cipher, null, DataProtectionScope.CurrentUser);
                text = Encoding.Unicode.GetString(data);
                Console.WriteLine($"Decrypted {data.Length} bytes from {fn}.");
                return true;
    
            }
            catch (CryptographicException ex)
            {
                Console.WriteLine("Error decoding data: ");
                Console.WriteLine(ex.ToString());
            }
            catch (IOException ex)
            {
                Console.WriteLine("Error reading file: ");
                Console.WriteLine(ex.ToString());
            }
            text = null;
            return false;
        }
    }
    

    并且data.enc的内容是完全加密的:

    【讨论】:

    【解决方案3】:

    如何创建只有我的应用程序才能修改的文件?

    你不能。就这么简单。

    问题是管理员可以访问所有文件。以及与您一起运行您的应用程序的用户。当然还有黑客。 ;) 通常,您只需将应用程序文件存储在一些完善的位置,例如在 unix 系统中将应用程序文件放在/var/lib/myapp 中是事实上的标准。当然,其他用户仍然可以访问这些文件,但这样至少可以降低意外修改的风险。然而,这也意味着您不应该在本地存储敏感数据

    加密并不是一个真正的选择,因为您必须将加密密钥存储在某个地方,这只会将一堆从一个地方移动到另一个地方。它确实使读/写变得更加困难,但并不能真正解决问题。除非您没有将密钥存储在任何地方,例如您可以在应用程序启动时手动提供它,甚至在运行时更好地提供它,并确保它不会存活太久。根据您的用例,这可能是一个有效的选项。

    修改检测,即散列文件,具有完全相同的问题:您必须将散列存储在某个地方。您只强制恶意用户修改两个位置而不是一个。

    请注意,在本地使用数据库引擎根本无济于事。归根结底,数据库只是一个花哨的文件,您仍然需要将访问密钥存储在某个地方。

    总而言之:如果您存储的是非敏感数据,则将其放在应用程序数据文件夹中,不用担心。

    【讨论】:

    • 您不必自己存储凭据。使用加密存储来保存压缩密钥。
    • @JohnAlexiou 我不明白密码存储如何解决这个问题。如果应用程序可以访问该商店,则恶意用户可以在应用程序之外访问它。你只是把这堆东西移到别处。你增加了混淆,是的,但你根本没有增加安全性。
    • 密钥基于当前用户。因此,有权访问该应用的第 3 方将需要模拟作者凭据。
    • @JohnAlexiou 或者干脆成为那个用户。这听起来像 OP 描述的案例。
    【解决方案4】:

    不确定您的应用程序应该做什么,但实现此目的的方法是在计算机上创建一个新用户或组,并以该用户身份运行您的应用程序。然后,您可以使用SetAccessControl 使用户或组具有读/写权限,而其他所有人都具有读权限。这实际上应该是一个 Windows 服务而不是一个应用程序。

    【讨论】:

      【解决方案5】:

      你不能完全否认它但是 ..
      您可以通过将用户组名称设置为 c# 中的一个简单技巧:将特定文件的 Everyone 设置为 Deny
      一旦你想写进去,Allow ReadWrite 然后在你完成写入文件后
      立即将Everyone的权限更改回Deny
      作为模仿此屏幕截图的一种方式,但来自后面的代码:

      要使用 c# 实现这一点,请参阅: Full Document from MSDN

      【讨论】:

        猜你喜欢
        • 2023-03-19
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 2014-01-13
        • 2012-12-02
        • 1970-01-01
        • 2015-11-14
        • 1970-01-01
        相关资源
        最近更新 更多