php认证/数据库代码风格
Posted
技术标签:
【中文标题】php认证/数据库代码风格【英文标题】:php authentication/database code style 【发布时间】:2012-07-20 01:31:27 【问题描述】:我想知道将诸如散列和加密之类的东西嵌入到较低级别代码中的常见做法。似乎最好使用某种对象或宏约定,以便在发现漏洞并提高效率时可以轻松评估和更新安全功能。例如,我在处理身份验证的 php 代码中看到了以下约定(博客、代码峡谷、框架 wiki 等)……这里有一个虚构的例子来说明这一点。
if ($myhash !== md5(shaX($this->key) . blah($this->salt) . blah($this->var))
与其把它埋得很深,这不是更好吗
if ($myhash != MY_HASH($key))
在配置文件或其他易于访问的对象中使用 MY_HASH,从而在可用时更容易更新/维护并提高安全性?为什么不将任何加密或散列的金块放入仅包含转换函数的配置文件或特殊散列文件中?
另外 - 考虑数据库访问。 PHP 有很多抽象,但我看到应用程序这样做:
// grab some data from the database
if ($this->mongo_flag)
$this->mongo_abstraction
->where($blah1, $x)
->update($blah2);
elseif ($this->mysql_flag)
$this->mysql_abstraction
->where($blah1, $y)
->update($blah2);
elseif ($this->couch_flag)
$this->couch_abstraction
->where($blah1, $z)
->update($blah2);
也许只有 x,y,z 不同。
不能实例化一个预先具有正确 db 方法的对象,从而消除 if/else 逻辑,该逻辑在进行数据库访问的任何地方都会重复?
即
$mydata = $this->db_get_method($blah1, $blah2);
或
$mydata = $DB_GET_METHOD($db_type, $blah1, $blah2);
如果首选 if/else 区分,那么您似乎应该跳过抽象的东西,而只使用原生 API,使其更高效、更易于维护,因为原生 api 可能不会改变并且抽象通过调出每种可能的数据库类型,大多数情况下都无效/无效。还是不行?
我的主要经验是实时嵌入式 C 编程(很多 PHP 代码看起来像用全局结构设计的过程 C)所以我想知道性能是否可能是最终答案,即它只是以这种方式运行得更快?对象是否会引入过多的延迟/复杂性?
【问题讨论】:
在我看来 PHP 开发人员对密码哈希函数的想法是一样的,php 5.5 的 rfc 将引入 password_hash() 函数以简化整个哈希过程:wiki.php.net/rfc/password_hash 正如@complex857所说,使用密码_* 【参考方案1】:我喜欢你的建议。特别是对于散列,我认为将其包装到一个易于访问的位置是明智的。我也喜欢你关于调用 db 方法的建议。但是,使用 PHP 执行您的建议需要反思,并且存在性能问题,请查看此帖子 PHP 5 Reflection API performance。性能冲击似乎并不算太糟糕,但性能仍有下降。我认为实现 db 方法调用的更好方法是使用 OOP 继承而不是传递动态方法。每个数据库应该有不同的对象。
【讨论】:
【参考方案2】:正如@complex857 在他的评论中所说,PHP 有一些努力来简化散列过程。不管怎样,你可以自己做(简单的函数,或者更复杂的类)。
也许我没有理解你的意思,但是关于 DB 抽象,使用 PHP PDO(以及 PEAR 的 DB 和 MDB2)你可以为特定的 DB 引擎构建一个对象,然后,方法大致相同(只有在处理任何引擎的特定功能时才会出现差异)。
还有一个关于 PHP 的大问题:有时您会偶然发现编写得非常糟糕的脚本,这些脚本可能是由业余程序员编写的。因此,如果您多次看到相同的不良做法,这并不意味着使用 PHP 没有更好的方法。还要考虑这些脚本的年龄:PHP 在其生命周期中已经发展了很多。
【讨论】:
【参考方案3】:身份验证和数据库抽象都是常见的痛点。程序员的狂妄自大或缺乏经验确实会导致大量糟糕的再发明(偶尔还有有用的创新)。
就数据库抽象而言,当后端实现显着不同时,您的示例很快就会崩溃。例如,Couch 或 MongoDB 等 NoSQL 数据库的查询语言和数据建模与 SQL 数据库使用的传统关系查询不能很好地匹配。您最终会得到一个leaky abstraction,您可以在其中使用“通用”接口,其中包含很多关于什么适用于给定后端的警告.. 或者严格限制的最低公分母。这是ORMs 的一个常见问题。他们经常难以表示不太适合预期的 ObjectClass DatabaseTable 映射的连接或子选择。
即使在“类似”产品(例如支持SQL 等通用关系语言的数据库)中也是如此。每个数据库通常都有自己的 SQL 方言,这些方言通常从支持的数据类型开始有所不同,并且随着实现扩展到触发器、存储过程和视图等更高级的功能,差异甚至更大。
从您其他示例的外观来看,您还遇到了一些 spaghetti code,开发人员可能在实现自己的抽象方面做得很差。
如果性能是一个问题,最好的结果可能是针对特定的数据库后端进行优化并利用独特的功能。
如果支持多种数据库后端更为优先,则有标准的关系接口,例如PDO、Doctrine 或MDB。一种新兴的数据库抽象类别是用于 MongoDB 和 Couch 等 NoSQL 数据库的 ODM(对象文档映射器)。
【讨论】:
以上是关于php认证/数据库代码风格的主要内容,如果未能解决你的问题,请参考以下文章