如何去管理php的用户名和密码(一) | 71街

Home > 感悟 > 如何去管理php的用户名和密码(一)

如何去管理php的用户名和密码(一)1+

13,034 views / 2010.06.13 / 5:05 下午

目前,多数大型的网站,尤其是SNS社区,都有用户管理系统,这些系统一般都涉及到密码认证的问题。那么这些系统是如何储存用户密码的呢?直接存储密码明文吗?答案是否定的,好的做法是把密码算出一个哈希(hash)值予以存储。我们会发现好多文章教你怎么去计算密码的hash值,杜工的博客(http://71j.cn)也有类似的文章,不过不是用来加密密码的,只是简单的散列,传统的文章推荐使用md5(),后来有些人推荐把密码连接上一个附加值(我们称之为salt值, Discuz就是这么做的),然后计算sha1(),或者hash()(SHA-256等),同时把用户名进行mysql_real_escape_string()处理。虽然这些文章介绍的方法总体方向是对的,但是并没有一篇关于密码安全存储的文章是尽善尽美的。

其实,最近的文章已经开始推荐使用phpass, 这是一个基于php的密码hash算法框架,已经被许多知名的web程序使用,如wordpress、Durpal 7等,但是目前并没有一篇详尽的,一步一步指引我们引用phpass的成型文章,而且密码安全问题,并不只是单纯的如何去hash密码予以存储的问题。

接下来,我将一步步介绍如何把用户密码管理方案引入到一套新的php程序中。首先,将简单阐述密码hash的概念以及如何安全地把这些密码送入数据库,然后通过个示例。从一个简单的创建新用户的程序开始,慢慢展开来,逐渐引入用户登录、修改(重置)密码的功能。

当然,文中会涉及其它相关的概念,如果你已了解,可直接略过。

密码HASH

合格的系统存储在数据库中的并不是密码明文,而是密码hash值。而实际上,单纯的把密码采用php函数,如md5,sha1等,加密后存储,会引发很严重的后果。只要正确的进行了hash,攻击者就很难从获取到的hash值中解析出用户密码,你只需要快速的把弱口令密码解决掉,就能把损失降到最低了。

当用户输入用户名和之前设定好的密码,点击登录进行验证后,程序先要根据用户名查询一些额外信息,如密码哈希类型,salt值,哈希重复的次数等,然后根据这些信息算出密码hash值,与已经存储的hash值进行比较,如果相同,则验证成功。

Salt方法

Salt是一个近乎随机的字符串,相同的密码使用不同的salt hash散列后, 会得到不同的结果,正确的使用这个方法,可以防止一系列的攻击,包括:

1.通过弱口令(如123456)就知道你的hash类型。

2.使用已经算好的hash值去做比对,如cmd5.com。

3.能够准确知道两个用户(或者一个用户的两个帐号)的密码是否是一样的。

Salt通常和密码hash值储存在一起,它并不是保密的。具体案例可参考Ucenter

算法强度要提升

一旦密码hash值泄漏 ,攻击者必然会采取暴力破解,一般的hash算法,如md5, sha1等,都是为了保证速度,而非为密码加密准备的,这样势必为攻击者缩短暴力破解提供了可能。因此,采取一个略微复杂点的hash算法,能够降低损失。假想下,如果你的每个密码生成时间家长0.2ms,用户不会有任何不好的体验,但对攻击者来说,这意味着什么?他要多付出几个月甚至几年的时间去破解你的密码!

关于phpass

Phpass是基于php的简单易用的密码hash算法框架。它提供三种hash方法,包括两种基于函数crypt()的—-CRYPT_BLOWFISH 和 CRYPT_EXT_DES,一种phpass自己的类md5的算法,前者只有php5.30以上的版本支持,后者这是全版本皆可。虽然,所有的算法都使用了salt及算法强度提升的方法,但考虑到效果,我们推荐使用前两种。在使用时,用户可以自定义hash迭代的次数。

在使用的时候,phpass能够自动生成salt和对进行算法拓展,你不需要为生成这些而费神。另外,phpass支持windows系统。

安全的接入数据库

SQL注入

所谓SQL注入,就是通过把SQL命令(特殊字符串,如单引号等)插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令的行为,比如先前的很多会员网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击.

如何防止SQL注入

  1.永远不要信任用户的输入。对用户的输入进行转码校验,可以通过正则表达式,或限制长度;对单引号等特殊字符进行转换,如对数据进行url_encode\ stripslashes等。

  2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。

  3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。(下面有详细说明)

  4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。

  5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装。

在接下来的例子中 ,如上几点将得以体现。

组建数据库预备语句

目前,php提供三种连接mysql的接口,一种是自带的,被广泛应用的mysql扩展,另外一种是mysqli扩展, 还有一个PDO(PHP Data Objects)接口,只有mysqli和PDO支持MySQL的预备语句,而且都需要php5+的支持。本文使用mysqli的方式。

预备语句的使用使数据和代码分离,虽然这并不是最完美的防止sql注入的方法,以为从头到尾,所有的数据都使用相同的socket连接传输,但比传统的语句过滤使用起来更加简单,并且不容易出错。

对数据库采用最小权限原则

除了要预防SQL注入,我们还要预防其它各方面潜在的威胁。好的做法是使用最低权限的数据库帐号,也就是说,不要使用管理员权限的数据库链接,而是为每个应用使用单独的权限的数据库连接。这样,即使你的php代码并不是很“完美”,也可以把网站被攻破而付出最小的代价。

(待续)

本站内容受著作权法保护。个人 blog 转载时请遵循 “署名-非商业用途-保持一致” 的创作共用协议;商业网站或未授权媒体不得复制本站内容。
Categories: 感悟 Tags: , , , ,

Comments (0) Trackbacks (1) 本篇共有 1 篇评论↓
  1. No comments yet.
  1. 六月 17th, 2010 at 14:32 | #1