每一个网站、APP都几乎必然有其管理后台,其中管理的内容则是公司的核心技术财产。而登陆模块则是这扇大门,其安全的重要性可想而知。咱们知道,功能越多,安全性就会越低,因此咱们有必要从新审视一下,管理后台的登陆界面到底须要些什么功能。html
一、基本的帐号密码登陆。这个无可避免是必然须要的了。前端
二、图片验证码。验证码的目的是为了阻止机器人暴力撞库,做为管理后台颇有必要,并且是要每次登陆请求都需从新验证。jquery
三、填完用户名或密码时,Ajax实时验证。这个功能常见于一些自动管理后台的注册模块,用于验证用户名是否已被占用。但此功能一般会致使不需通过验证码验证,从而使得暴力撞库有隙可乘。ajax
四、记住我选项。这是一个使用cookie记住登陆用户的功能,使用户下次再来时能够不须要再登陆便可经过验证。但cookie必然须要记录 用户ID或用户名 相关的信息,存在浏览器中,有必定的CSRF攻击风险和信息泄漏风险。数据库
五、找回密码功能。这是一个高危功能,不管是逻辑疏漏仍是安全不严谨,都会致使帐号的失窃。参考1月份支付宝找回密码的危机。因此建议作法是,公司文档保存相关的帐号密码信息,如遇实在没法登陆,则找技术人员进入数据库修改密码(加密后)。后端
六、注册功能。这个不要作在外面,在后台的功能里加一个添加用户会安全不少。浏览器
七、第三方登陆。如QQ登陆、微信登陆?不须要,你们都知道QQ很容易被盗号,不宜做为安全性要求高的系统的登陆入口。微信则须要拿手机出来扫码,不如直接输入密码来得方便,另外它还须要申请微信公众号以及500块每一年的公众号认证费用。安全
综上,得出一个够用、安全的管理后台的登陆界面微信
一、验证码安全。以AJAX提交为例,每次尝试登陆后,不管是否登陆成功,后端都要注销当前验证码SESSION,前端JS刷新验证码。后台要注销SESSION是以避免黑客屏蔽JS致使验证码只需一写次,从而致使爆库。cookie
二、网络传输安全。最好使用https加密,以避免网络传输过程泄露帐号密码,如在咖啡店等他人WIFI环境。若是没有使用HTTPS,则应该在前端JS加密登陆名和密码,后端再解密。由于JS是明文的,因此要使用非对称性加密(如RSA),JS使用公钥加密,服务端使用私钥解密。甚至对JS文件自己也能够做一些加密压缩。为何登陆名也要加密呢?仍是避免信息泄露,以避免别人根据登陆名猜出密码。
三、登陆成功时从新生成SESSION_ID。主要是为了防止固定会话ID的CSRF攻击。
知己知彼,战斗才能胜利。上面这些功能和安全,都是一些通用的防守攻击套路。但敌人在暗我在明,敌人何时派出过特务,何时发出过攻击,发起了什么样的攻击?仅经过上面的功能,咱们无从得知。因此,咱们还须要一个监控器--登陆日志。
而后这个登陆日志,咱们须要记录些什么东西呢? 登陆名、是否成功、IP地址、时间。可是,这还不够,这样咱们只能分析到了是谁有攻击咱们,可是分析不到他是经过什么方式来攻击。那还要记录什么呢?URL地址(含GET数据)、POST数据。但须要注意的是,咱们登陆时的密码也在POST数据里,切不可将密码存储在登陆日志里,即便是RSA加密过的也不行,应以***星号代替,不然这和明文存储密码没什么差异。
前端代码的要点是登陆时RSA加密帐号密码,使用的是 jsencrypt.js 库,Ajax提交表单用的是 jquery.form.js 。核心代码以下,须要注意的是,ajaxForm接受的这两个回调函数,参数名是固定的没法修改,修改表单数据用的是formData,提交成功回调的结果名是responseText。标紫色的两个变量是后台输出的模板变量。
//AJAX提交登陆表单 $(function(){ var formSubOpt = { beforeSubmit: encodeForm, success: formRes }; $("#loginform").ajaxForm( formSubOpt ); }); //提交成功 function formRes(responseText){ //参数名要为这个 // console.log(responseText); ajaxAlerts(responseText); //提示 if(responseText.code<0){ changeVer(); $("input[name=ver]").val(""); } if(responseText && responseText.code==0){ setTimeout(function(){ location.href = "{$toURL}"; },750); } } //RSA加密帐号密码 var RSApubKey = "{$RSApubKey}"; //console.log(RSApubKey); function encodeForm(formData){ // console.log(formData); //这是要提交的参数 var crypt = new JSEncrypt(); crypt.setKey( RSApubKey ); var USER = crypt.encrypt( $("input[name=name]").val() ); var PW = crypt.encrypt( $("input[name=psw]").val() ); // console.log( PW ); formData[0].value = USER; formData[1].value = PW; }
略。按前面的分析思路来写便可