可以将`setattr`(和`getattr`)的使用视为不良做法吗?

Tim*_*son 7 python setattr getattr

setattrgetattr那种钻进了我的编程风格(主要是科学的东西,我对蟒蛇知识的自我告知).

考虑到execeval继承了潜在的危险,因为在某些情况下它们可能会导致安全问题,我想知道是否setattr认为相同的论点是有效的.(关于getattr我发现这个问题包含一些信息 - 虽然论证不是很有说服力.)

据我所知,setattr可以毫不费力地使用,但说实话,我不相信我的python知识足以确定,如果我错了,我想尝试摆脱使用的习惯setattr.

任何输入都非常感谢!

aba*_*ert 11

首先,它肯定可以使现有的安全漏洞更容易.

例如,假设你有没有代码exec,eval,SQL查询或通过网址字符串格式化等建成并假设你传递,比如说,locals()或者过滤__dict__的格式化命令或作为eval背景或什么的.使用setattr明显加宽了安全漏洞,使我更容易找到攻击代码的方法,因为您无法确定将要传递给这些函数的内容.

但是,如果你不做任何其他不安全的事情呢?是setattr安全的呢?

没那么糟糕,但它仍然不安全.如果我可以影响您正在设置的属性的名称,我可以,例如,替换您想要的对象上的任何方法.

您可以尝试通过例如首先检查旧值是否不可调用,或者不是方法类型描述符或其他来防止这种情况.以同样的方式,您可以尝试防止人们调用函数eval或在SQL参数中添加引号和分号等.这实际上与任何其他情况相同.尝试关闭所有通往开门的非法路径要困难得多,而不是首先不打开门.

如果名称永远不会来自可能受用户影响的任何内容,该怎么办?

那么,在那种情况下,你为什么要使用setattrsetattr用文字打电话是没有充分理由的.

无论如何,当Lattyware说通常有更好的方法来解决手头的问题时,他几乎肯定会谈论可读性,可维护性和惯用性.但使用这些更好的方法的副作用是你也经常避免任何安全隐患.

90%的时候,解决方案是使用一个dict而不是一个对象.与Javascript不同,它们在Python中并不相同,并且它们并不意味着以相同的方式使用.A dict没有方法,继承或内置特殊名称,因此您不必担心任何问题.它还有一个更方便的语法,你可以说d['foo']而不是setattr(o, 'foo').它可能更有效率.等等.但最终,使用a的原因dict是概念上的原因:a dict是一个命名的值集合; 类实例是模型空间对象的表示,并且它们不是同一个东西.

那么,为什么setattr甚至存在呢?

它的存在相同的基本理由,其他低级别的功能,如能够访问im_funcfunc_closure,或有类似的模块tracebackimp,或治疗特殊的方法,就像任何其他的方法,或为此事execeval.

首先,您可以使用这些低级工具构建更高级别的东西.例如,要构建collections.namedtuple,您需要exec或者setattr.

其次,您偶尔需要在运行时编写代码,因为您无法在编译时修改它(或者甚至可能看到它),并且这样的工具setattr可能是必不可少的.

这个setattr功能很像eval- 经常被来自Javascript,Tcl或其他一些语言的人滥用.但只要它可以用得很好,你就不想把它从语言中拿出来.(TOOWTDI不应该这样理解,只能编写一个程序.)

但这并不意味着你应该尽可能地使用这些东西.你不会写mylist.__getitem__(slice(1, 10, 2))而不是mylist[1:10:2].有时,能够__getitem__直接调用或slice明确构建对象是一些基础,可以使代码的其余部分更加pythonic,或者本地化变通方法以避免感染其余代码.否则,有更清晰,更简单的方法.

  • @detly:当然,如果我只想运行您的代码的本地副本。但谁在乎呢?想必我想通过数据攻击你的代码的原因是它是一个 web 服务、根守护进程等。 所以我想让你‘评估’我的表达式,或者将我的 SQL 注入你的 SQL 语句,或者替换你的方法,或者其他什么,所以以 root 身份运行/在网络上运行的副本/任何我想要的东西,而不仅仅是我无用的本地副本。 (2认同)