【发布时间】:2015-09-11 05:01:06
【问题描述】:
我正在编写一个库,并且我有一个接收字典的方法。字典的值是不受信任/不安全的,但密钥是受信任的,如果最终用户能够输入任意密钥名称,则可能会发生“坏事”。
所以当其他开发者使用这个库函数时,我想强制他们在编译时知道键名。所以这样的事情是允许的:
string userInput = Console.ReadLine();
Dictionary<string, string> something = new Dictionary<string, string>();
something.Add("MyKey", userInput);
因为“MyKey”是一个字符串文字,在编译时就知道了。但是这样的事情会引发编译或运行时异常:
string userInput = Console.ReadLine();
string userKey = Console.ReadLine();
Dictionary<string, string> something = new Dictionary<string, string>();
something.Add(userKey, userInput);
因为用户输入用于密钥 (userKey),因此在编译时它是未知的。
我查看了 GetType() 并没有真正区分文字字符串和在运行时创建的字符串。
【问题讨论】:
-
你不能创建(或重用)一个可以查看字符串值并对其进行清理或确定它是否安全的方法吗?然后,您可以保护自己免受有问题的字符串文字的影响,并允许使用非文字安全值。
-
如果我没记错的话,属性中的表达式保证是不变的。因此,您还可以尝试创建自定义属性,并让客户端代码向您传递一个成员或使用该属性修饰的类型。然后,您可以从该属性中读取元数据。 (虽然可能有反射技巧可以伪造,使用动态程序集。)
-
问题是密钥本质上是不安全的。这就是为什么它在任何情况下都不应该来自用户输入。现在我的选择是要么在编译时检查它是否已知,要么将其硬编码到我的库中,这样外部开发人员就无法更改它。
-
只要您的密钥是字符串,您执行此操作的任何方式都将是 hacky。关闭对象实例怎么样,它们的类型必须扩展您在库中定义的抽象基本类型?实现者必须扩展该类型才能创建实例,然后将其传递给您以用作键。
-
我确实喜欢@Theo的解决方案,这该死的好。