控制面板 - 帮助中心 - 付款方式 - 常用文档 - 软件下载 -   
服务中心
当前位置:首页 - 服务中心 - 网络学院

PHP管理系统对用户和密码的处理(一)

  现在很多大型网站,尤其是SNS社区,都有用户管理系统。这些系统均会涉及到密码认证问题。那么这些系统是如何储存用户名和密码的呢?直接存储密码明文吗?肯定不会。

  不错的做法是把密码算出一个哈希(hash)值予以存储。我们会发现好多文章教你怎么去计算密码的hash值,不过不是用来加密密码的,只是简单的散列,传统的文章推荐使用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代码并不是很“完美”,也可以把网站被攻破而付出最小的代价。 

更新时间:2010-8-11

7*24小时咨询热线:400-628-6536 0371-86013552 19937165195
传真:0371-86013552-6612 服务邮箱:web@3a88.com 代理邮箱:agent@3a88.com 备案邮箱:beian@3a88.com
运营商:郑州金飞科技有限公司 工商营业执照号:9141010567945717XL
公司地址:郑州高新技术产业开发区木兰里9号1号楼1单元14层310号 邮政编码:450000 豫ICP备12025635号-1 豫公网安备 41010502003077号