最近在作一个小系统,须要用户登陆功能。虽然系统对安全性要求并不高,可是但愿借此机会增加下安全方面的知识,由于网络信息安全对于编程甚至对平常生活都很重要。因而就搜索一下网上关于登陆密码安全防御的一些网页,在这里进行一下整理和总结。因为我对安全方面的知识只有较粗浅的了解,所以这里给出了以为比较有参考价值的文章的连接,请想深刻了解的人仍是亲自参考下那些文章,或者延伸阅读更专业、详尽的书籍、资料。另外,我在查资料的过程当中曾经看过一个CSDN上的帖子,楼主说的内容大约是在询问有什么方法可以保证密码的安全,而底下的大多回复却在抨击这种想法,以为密码安全没法获得彻底解决,考虑这个问题太耗费开发精力,使用明文传输密码也没什么大不了反正新浪邮箱就用的明文云云。窃觉得这种想法不可取。我并不否定某些应用中并不须要太高的安全级别,过多考虑安全问题反而会消耗开发成本(其实我所开发的项目大约也是如此)。但毕竟并非全部应用都对安全要求不高,并非全部人都对安全不闻不问。能尽本身所能做多一点防御也没什么很差。多的就不说了,总之我仍是比较鼓励人不断探索。php
首先推荐一个很综合的讨论的连接:html
http://segmentfault.com/q/1010000000095307python
综合起来,密码的安全主要存在于三个方面:算法
数据库中存储密码的安全性
数据库
有一篇文章能够算是归纳了这一议题:编程
http://zhuoqiang.me/password-storage-and-python-example.htmlsegmentfault
简单的说,数据库中密码的安全性就是假若有黑客盗取了你的数据库的数据,你如何让黑客没法破解用户的密码信息。浏览器
最简单的方法,就是在数据库中使用明文来存储用户名密码(前一段时间CSDN的密码泄漏事件算是炸开了锅,更使人吃惊的是国内第一技术网站居然使用这种低级的方法)。这种方法很是容易破解,只要获得了用户数据,任何人直接就能得到密码信息。安全
第二种方法是对密码进行加密(如使用MD五、SHA算法)以后存储在数据库中。这种方法对于较复杂的密码来讲黑客一筹莫展,但对于较常见的密码黑客在获得了数据以后依然能有效破译。有一些好事者将用户经常使用的密码总结出来,再使用这些加密算法得出其加密后的值,称其为彩虹表。黑客只须要用彩虹表与加密后的密码比对,依然能获得用户的原始密码。网络
为了克服第二种方法的缺陷,使得常见密码也能获得保护,人们发明了第三种方法:使用salt来混淆加密后的值。大致方法是,每次写入用户的密码时(如注册或修改密码),随机生成一个salt值(多是一个随机字串或者大整数等等),并将salt与密码混合(能够是各类混合方式而不只限于将两个串链接在一块儿),再进行哈希。这样,即便黑客拥有了彩虹表,也不能当即猜想出哪些哈希值对应哪些常规的密码,由于即便用户输入了常规密码,混合了salt的哈希值已经与以前截然不同,而在salt值对于不一样用户各异的状况下(若是全部用户的salt值都同样且混淆方法已知那么黑客依然能够针对常见密码与salt混合生成一个具备针对性的彩虹表),也难以对全部用户生成一个彩虹表。但黑客依然能够针对某一个用户,使用暴力穷举的方式,来破译密码。若是用户的密码长度较短且全是数字的话,因为搜索空间较小且MD五、SHA等算法因为自己特性加密过程比较快,破译也并不难。
为了克服第三种方法的缺陷,第四种方法延长了加密算法的执行时间:或者使用“stretching”增长普通MD5等快速算法的迭代次数,或者使用bcrypt这样的执行时间可配置的加密算法,来迫使黑客在暴力破译的时候须要更长的时间。因为将加密算法控制在微秒级便可给黑客的破译带来灾难性打击而同时单个用户登陆时验证的耗时又不算太长,这种方法能够说有效的解决了黑客破译密码的危险。
salt与彩虹表的内容有一篇文章讲得比较详细:
http://www.libuchao.com/2013/07/05/password-salt
关于bcrypt算法可见
http://codahale.com/how-to-safely-store-a-password/
其论文见
https://www.usenix.org/legacy/events/usenix99/provos.html
这篇文章讲了php中一个通用的考虑了以上全部问题的登陆验证包phpass及其验证原理,还包括一些验证安全的通用议题,还讲到了如何使用输入过滤与prepared statement结合来防止SQL注入:
http://www.openwall.com/articles/PHP-Users-Passwords
不过笔者有一个小小的疑问,作了这么多都是为了防止黑客在得知了用户数据表以后如何防止其进一步得知用户的登陆密码。但再进一步说,既然黑客都获得了用户数据表了,那么是否是也能获得其余信息呢?黑客想登录到你的账户无非也是为了获取甚至更改你的数据(至少不少时候这样),那么数据库自己的安全是否是比用户密码存储方式的设计更重要呢。看来安全并非一个三言两语能讲完的议题,因为本文只关注密码在存储与传输过程当中的安全,因此这些内容就只能暂时忽略了。
密码在网络中传输的安全性
一篇归纳性讲解:
http://zhuoqiang.me/password-transport.html
传输过程当中的安全性可能比较数据库存储的安全性更重要,由于网络中的数据包极有可能被黑客截获。
最不可取的方法就是使用明文传输密码,黑客能够轻松截获http传输的数据并获知密码(且不谈黑客如何从海量数据中获取和分析与登陆密码相关的数据)。
进行加密传输后依然能被轻松攻击,黑客截获后,即便不分析出密文所对应的明文,只要构造相同的http请求使用所谓的“回放攻击”,就能轻松登陆用户的帐户。
解决这种传输中安全问题的终极方案是使用https协议加密传输。只要在客户端输入时密码不被窃取,且ssl协议的私钥安全,这种协议就是安全的。
值得一提的是,为了不回放攻击,可使用nonce来解决(参见http://doc.okbase.net/parry/archive/5619.html)。这种方式虽然应用在了http自带的认证中,普通的用户登陆认证也能够仿效。可是这种方法貌似仍是不如https来得安全。