当前位置: 首页 > news >正文

多次握手登录

社会险恶啊,现在做系统做个简单的用户密码判断然后登录已经不好使了。安保的搞个爬虫抓包登录请求就可以让爬虫用登录持有会话然后爬行网站。然后就各种提,我这用个Cache库,都是对象存储的,如果被抓到一个表报错是SQL就提你系统有SQL注入漏洞,真是有理说不清。先不说我这是Cache对象存储。就是关系库我用SQL参数了啊。被你抓个SQL日志就SQL注入风险了,真是无语。

安保的得力工具是爬虫。拿个爬虫去现场,一个什么不懂的小白都能提一堆你不得不改的问题来。爬虫爬行整个网站还得抓一下登录的包,然后用登录提交的东西模拟登录保持会话爬行。所以首先把门得守住,让爬虫不能轻易抓取登录时候请求模拟登录,简单的一次性提交登录肯定是不行了。理论上把登录的口子守住了系统起码安全一半。

所以改进登录为多次握手登录,大概以下步骤。
1.js提交验证用户密码时候顺带生成一个时间戳和他的哈希值提交给后台,并且提交用RSA加密(服务端给JS加密数据用一对秘钥,JS给服务端加密数据用一对秘钥)。
2.服务端收到数据后用服务端持有的RSA秘钥界面JS数据。然后哈希校验时间戳。对非法时间戳直接拉黑IP一天访问。
3.服务端如果校验时间戳通过且验证用户密码通过。那么把JS提交时间戳加上服务器时间形成累计的时间戳,再哈希得到验证值。然后把服务端组装的新时间戳串用JS提交的时间戳哈希值当做密码DES加密。再把加密数据用服务端RSA秘钥加密返回给JS端。
4.JS端登录时候需要把服务端返回的时间戳和登录新构造的时间戳提交到后台。
5.后台解密服务端时间戳,先验证里面第一次验证用户密码时候的时间戳合法性。然后再验证服务端时间戳整体合法性。然后再计算当前时间和服务端时间戳时间差不能大于三分钟。
6.然后再验证JS第二次时间戳和第一次时间戳之差不能大于3分钟。
7.验证登录后再登录构造会话,构造会话成功后马上把当前用户最后时间戳存入会话。如果登录提交的时间戳已经使用过就不给登录。防止爬虫跟随登录页抓包潜入进来(相同的服务端时间戳只让登录一次)。

通过上面多次握手和多种加密结合防止爬虫轻易抓包模拟登录。

JS得到时间戳方法,结合MD5和RSA加密:

//得到时间戳
function GetTimeSpan() {
    var myDate = new Date();
    var hours = myDate.getHours();
    if (hours < 10) {
        hours = "0" + hours;
    }
    var minutes = myDate.getMinutes();
    if (minutes < 10) {
        minutes = "0" + minutes;
    }
    var seconds = myDate.getSeconds();
    if (seconds < 10) {
        seconds = "0" + seconds;
    }
    var timeStr = GetCurentDate() + " " + hours + ":" + minutes + ":" + seconds;
    var random = Math.random();
    var transStr = hex_md5(timeStr + "_" + random).toUpperCase();
    return RsaEncrypt(timeStr + "_" + random+ "^" + transStr );
}

验证密码提交第一次时间戳
在这里插入图片描述

校验片段示例(实际会加拉黑操作):

 //时间戳
string TimeSpan = Helper.ValidParam(LIS.Core.MultiPlatform.LISContext.GetRequest(Request, "TimeSpan"), "");
//解密时间戳数据
TimeSpan = LIS.Core.Util.RsaUtil.RsaDecrypt(TimeSpan);
//验证时间戳
string[] timeSpanArr = TimeSpan.Split('^');
if (timeSpanArr.Length != 2)
{
    RetResultMsg errRet = new RetResultMsg();
    errRet.Code = -1;
    errRet.IsOk = false;
    errRet.Message = "非法的时间戳数据!";
    return Helper.Object2Json(errRet);
}
else
{
    string timeSource = timeSpanArr[0];
    timeSource = LIS.Util.Md5Util.getMd5Hash(timeSource);
    if (timeSpanArr[1] != timeSource)
    {
        RetResultMsg errRet = new RetResultMsg();
        errRet.Code = -1;
        errRet.IsOk = false;
        errRet.Message = "非法的时间戳数据!";
        return Helper.Object2Json(errRet);
    }
}
//拼接服务器时间做服务器时间戳
string RetTimeSpanStr = TimeSpan + "^" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
//得到时间戳验证哈希
string RetTimeSpanStrHash = LIS.Util.Md5Util.getMd5Hash(RetTimeSpanStr);
//返回的时间戳。用JS的时间戳哈希值当密码加密
string RetTimeSpan = LIS.Common.Login.DesUtilCommon.EncryptDES(RetTimeSpanStr + "@" + RetTimeSpanStrHash, timeSpanArr[1]);
//二次加密
RetTimeSpan = LIS.Common.Login.DesUtilCommon.EncryptDES(RetTimeSpan + "@" + timeSpanArr[1], "testzz");
RetResultMsg ret = LgService.CheckUser(userCode, password, Session);
//返回时间戳
ret.TimeSpan = RetTimeSpan;
//返回之前再RSA加密

登录时候把第二次JS时间戳和服务端时间戳抛给后台:
在这里插入图片描述

登录时候验证片段,从第一段哈希开始每段都得验证符合,并且在时间范围才放行(时间会加拉黑一天操作)。

//JS时间戳
string JSTimeSpan = Helper.ValidParam(LIS.Core.MultiPlatform.LISContext.GetRequest(Request, "JSTimeSpan"), "");
//解密时间戳数据
JSTimeSpan = LIS.Core.Util.RsaUtil.RsaDecrypt(JSTimeSpan);
//验证时间戳
string[] jsTimeSpanArr = JSTimeSpan.Split('^');
//JS第一次时间戳时间
string JSOneTime = "";
//JS第二次时间戳时间
string JSTowTime = "";
if (jsTimeSpanArr.Length != 2)
{
    RetResultMsg errRet = new RetResultMsg();
    errRet.Code = -1;
    errRet.IsOk = false;
    errRet.Message = "非法的时间戳数据!";
    return Helper.Object2Json(errRet);
}
else
{
    string timeSource = jsTimeSpanArr[0];
    timeSource = LIS.Util.Md5Util.getMd5Hash(timeSource);
    if (jsTimeSpanArr[1] != timeSource)
    {
        RetResultMsg errRet = new RetResultMsg();
        errRet.Code = -1;
        errRet.IsOk = false;
        errRet.Message = "非法的时间戳数据!";
        return Helper.Object2Json(errRet);
    }
    JSTowTime = jsTimeSpanArr[0].Split('_')[0];
}

string LISTimeSpan = Helper.ValidParam(LIS.Core.MultiPlatform.LISContext.GetRequest(Request, "LISTimeSpan"), "");
LISTimeSpan = LIS.Core.Util.RsaUtil.RsaDecrypt(LISTimeSpan);
//一次解密
LISTimeSpan = LIS.Common.Login.DesUtilCommon.DecryptDES(LISTimeSpan, "testzz");
string[] timeSpanArr = LISTimeSpan.Split('@');
//二次解密
LISTimeSpan = LIS.Common.Login.DesUtilCommon.DecryptDES(timeSpanArr[0], timeSpanArr[1]);
timeSpanArr = LISTimeSpan.Split('@');
if (timeSpanArr.Length != 2)
{
    RetResultMsg errRet = new RetResultMsg();
    errRet.Code = -1;
    errRet.IsOk = false;
    errRet.Message = "非法的时间戳数据!";
    return Helper.Object2Json(errRet);
}
else
{
    string timeSource = timeSpanArr[0];
    string timeSourceSpan = LIS.Util.Md5Util.getMd5Hash(timeSource);
    if (timeSpanArr[1] != timeSourceSpan)
    {
        RetResultMsg errRet = new RetResultMsg();
        errRet.Code = -1;
        errRet.IsOk = false;
        errRet.Message = "非法的时间戳数据!";
        return Helper.Object2Json(errRet);
    }
    string[] timeArr = timeSource.Split('^');
    if (timeArr.Length != 3)
    {
        RetResultMsg errRet = new RetResultMsg();
        errRet.Code = -1;
        errRet.IsOk = false;
        errRet.Message = "非法的服务时间戳数据!";
        return Helper.Object2Json(errRet);
    }
    else
    {
        string timeSourceSpanJS = LIS.Util.Md5Util.getMd5Hash(timeArr[0]);
        if (timeSourceSpanJS != timeArr[1])
        {
            RetResultMsg errRet = new RetResultMsg();
            errRet.Code = -1;
            errRet.IsOk = false;
            errRet.Message = "非法的JS时间戳数据!";
            return Helper.Object2Json(errRet);
        }
        JSOneTime = timeArr[0].Split('_')[0];
        string timeStr = timeArr[2];
        DateTime spanTime = Convert.ToDateTime(timeStr);
        if ((DateTime.Now - spanTime).TotalMinutes > 3)
        {
            RetResultMsg errRet = new RetResultMsg();
            errRet.Code = -1;
            errRet.IsOk = false;
            errRet.Message = "时间戳已过期,请重新校验!";
            return Helper.Object2Json(errRet);
        }
        //比较两次JS时间戳的时间差
        DateTime JSOneSpanTime = Convert.ToDateTime(JSOneTime);
        DateTime JSTowSpanTime = Convert.ToDateTime(JSTowTime);
        if ((JSTowSpanTime - JSOneSpanTime).TotalMinutes > 3)
        {
            RetResultMsg errRet = new RetResultMsg();
            errRet.Code = -1;
            errRet.IsOk = false;
            errRet.Message = "JS时间戳已过期,请重新校验!";
            return Helper.Object2Json(errRet);
        }
    }
}


//上一个时间戳
string PreLISTimeSpan = LIS.Core.MultiPlatform.LISContext.GetSession<string>(Session, "TimeSpan_" + UserLogin.UserDR);
//防止爬虫跟随进来
if (PreLISTimeSpan == LISTimeSpan)
{
    return Helper.Error("爬虫恶意的跟随登录!");
}
RetResultMsg ret = LgService.UserLogin(UserLogin.SysID, UserLogin, Session);
//登录成功
if (ret.IsOk)
{
    LIS.Core.MultiPlatform.LISContext.SetSession<string>(Session, "TimeSpan_" + UserLogin.UserDR, LISTimeSpan);
}

通过多次交互,来回累计哈希和加密解密来防止爬虫简单抓包登录。这样爬虫得把每步交互搞清除,并且实现所有JS交互部分逻辑才能爬行登录。并且错误尝试还会受到拉黑一天的处理。从而包含网站不被轻易爬取。

反正就是一条,交互越复杂越好,频繁的累计哈希戳,任意一步构造数据不符合验证就拉黑。

交互示例:
验证密码提交
在这里插入图片描述
验证密码返回
在这里插入图片描述
登录提交,一个服务时间戳只让登进去一个会话
在这里插入图片描述
一样的串跟随提交是不会给他构造会话的
在这里插入图片描述

想靠抓包重复使用登录连接也是不可以的,有时效
在这里插入图片描述

伪造提交串也是有严格流程格式限制的
在这里插入图片描述

相关文章:

  • gdb调试 常用命令
  • 华为云上安装mysql-5.7.38-极其详细的安装教程
  • vue父子组件传值:父传子、子传父
  • 使用花生壳做内网穿透
  • 基于SSM的学生宿舍管理系统
  • 第二章第六节 ST图与迭代优化
  • Kotlin(九)类、属性、构造函数
  • Java 八股文能不背吗?Java 面试都只是背答案吗?
  • [CC2642R1][VSCODE+Embedded IDE+IAR Build+Cortex-Debug] TI CC2642R1基于VsCode的开发环境
  • JS垃圾回收与内存泄漏
  • MySQL数据库笔记
  • 基于SSM的高校餐厅防疫管理系统
  • y118.第七章 服务网格与治理-Istio从入门到精通 -- Istio流量治理快速入门(四)
  • Linux | 性能问题排查
  • 【微服务容器化】第二章-Docker常用命令
  • [LeetCode] Wiggle Sort
  • css选择器
  • ES6 学习笔记(一)let,const和解构赋值
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Java小白进阶笔记(3)-初级面向对象
  • Js基础知识(四) - js运行原理与机制
  • PAT A1050
  • 初识 webpack
  • 从零开始在ubuntu上搭建node开发环境
  • 基于HAProxy的高性能缓存服务器nuster
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 前嗅ForeSpider采集配置界面介绍
  • 使用 Xcode 的 Target 区分开发和生产环境
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #pragam once 和 #ifndef 预编译头
  • (04)odoo视图操作
  • (1)(1.13) SiK无线电高级配置(五)
  • (BFS)hdoj2377-Bus Pass
  • (pojstep1.1.2)2654(直叙式模拟)
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (WSI分类)WSI分类文献小综述 2024
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)fock函数详解
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)我也是一只IT小小鸟
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .Family_物联网
  • .net mvc 获取url中controller和action
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET值类型变量“活”在哪?
  • .py文件应该怎样打开?
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [2015][note]基于薄向列液晶层的可调谐THz fishnet超材料快速开关——
  • [AHOI2009]中国象棋 DP,递推,组合数