[一]关于12306---登录

一直想写个订票软件,一是学习学习抓包,分析报文,HTTP协议,二是锻炼一下码代码能力。我将实现订票软件分为了几步,第一步是实现登录功能,第二部是实现查询功能,第三部是下订单功能。其中第二步实现略简单抓个包分析分析就行了,第三步可能以后还会细分为几步。参考了几篇博文,完成了现在的登录功能。在此只和大家分享一下登录的思路。

1. 12306登录流程分析

作者采用fiddler进行抓包,fiddler的使用教程见http://www.cnblogs.com/TankXiao/archive/2012/02/06/2337728.html

1.1 初始化登录页面

执行GET请求,请求URL为https://kyfw.12306.cn/otn/login/init,响应正文为登录页面的html源码,将改源码记录,在1.4中会用到

1.2 获取验证码

执行GET请求,请求URL是https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&0.5699852106627077,参数写死,对于最后的那个0.5699852106627077我没有弄懂是什么意思,我也写死了,发现是可以的,有知道那个是什么意思的可以教我一下。请求之后得到的回应是一张验证码图片,刷新验证码重新执行该请求即可。

1.3 验证码检验

执行POST请求,请求URL为https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn

请求正文截图如下:


参数分析:

randCode:验证码参数,前些天12306对验证码进行了升级,升级之后分为八张图片供选择,该参数的几个值就是你点击点的横纵坐标,以左上角为(0,0),右下角为(300,300),一张图片的长宽是75。假如我点击的是第二张和第五张,那么该参数包含四个值ABCD,以英文逗号隔开,其中75<A<150,0<B<75,0<C<75,75<D<150。

rand:写死为"sjrand"即可。

验证码认证成功返回的消息体为:{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"result":"1","msg":"TRUE"},"messages":[],"validateMessages":{}}

1.4 登录信息提交

POST请求,请求URL为https://kyfw.12306.cn/otn/login/loginAysnSuggest

请求正文截图如下:


参数分析:

loginUserDTO.user_name:用户名

userDTO.password:密码

randCode:验证码参数

ODk2MzM2:这个等一下重点说明

myversion:写死为"undefined"即可

对于第四个参数,参数名和值都是动态生成的,生成思路是这样的:在1.1初始化登录页面得到的源码中,存在一个动态js,<script src="/otn/dynamicJs/lwvawai" type="text/javascript" xml:space="preserve"></script>,这个动态js的src是随机生成的,初始化一次登录页面生成一次,并且对其执行GET请求只能执行一次,我们需要的参数名就是其中的function gc()里的第一个变量值。value是这样通过encode32(bin216(Base32.encrypt(keyVlues[1], keyVlues[0])))得到的,其中通过阅读js代码得知keyVlues[0]为该参数名,keyVlues[1]是对抢票软件的检测,初始化为"",每次检测通过则+1,共四次检测,最后得到1111,也就是说keyVlues[1]写死为"1111"即可。将提取到的密码脚本保存在本地,代码如下:

function bin216(s){
        var i,l,o = "",n;
        s += "";
        b = "";
        for(i = 0,l = s.length;i < l;i ++ ){
            b = s.charCodeAt(i);
            n = b.toString(16);
            o += n.length < 2 ? "0" + n : n;
        }
        return o;
    };
    var Base32 = new function(){
        var delta = 0x9E3779B8;
        function longArrayToString(data,includeLength){
            var length = data.length;
            var n = (length - 1) << 2;
            if (includeLength){
                var m = data[length - 1];
                if((m < n - 3) || (m > n))return null;
                n = m;
            }
            for(var i = 0;i < length;i ++ ){
                data[i] = String.fromCharCode(data[i] & 0xff,data[i] >>> 8 & 0xff,data[i] >>> 16 & 0xff,data[i] >>> 24 & 0xff);
            }
            if (includeLength){
                return data.join('').substring(0, n);
            }
            else{
                return data.join('');
            }
        };
        function stringToLongArray(string, includeLength){
            var length = string.length;
            var result = [];
            for (var i = 0;i < length;i += 4){
                result[i >> 2] = string.charCodeAt(i) |                string.charCodeAt(i + 1) << 8     |                string.charCodeAt(i + 2) << 16    |                string.charCodeAt(i + 3) << 24;
            }
            if (includeLength){
                result[result.length] = length;
            }
            return result;
        };
        this.encrypt = function(string, key){
            if (string == ""){
                return "";
            }
            var v = stringToLongArray(string, true);
            var k = stringToLongArray(key, false);
            if (k.length < 4){
                k.length = 4;
            }
            var n = v.length - 1;
            var z = v[n], y = v[0];
            var mx, e, p, q = Math.floor(6 + 52 / (n + 1)), sum = 0;
            while (0 < q -- ){
                sum = sum + delta & 0xffffffff;
                e = sum >>> 2 & 3;
                for (p = 0;p < n;p ++ ){
                    y = v[p + 1];
                    mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
                    z = v[p] = v[p] + mx & 0xffffffff;
                }
                y = v[0];
                mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
                z = v[n] = v[n] + mx & 0xffffffff;
            }
            return longArrayToString(v, false);
        };
    };
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    function encode32(input){
        input = escape(input);
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;
        do{
            chr1 = input.charCodeAt(i ++ );
            chr2 = input.charCodeAt(i ++ );
            chr3 = input.charCodeAt(i ++ );
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)){
                enc3 = enc4 = 64;
            }
            else if (isNaN(chr3)){
                enc4 = 64;
            }
            output = output +             keyStr.charAt(enc1) +             keyStr.charAt(enc2) +             keyStr.charAt(enc3) +             keyStr.charAt(enc4);
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        }
        while (i < input.length);
        return output;
    };
然后调用密码脚本js计算得到value。如果前面步骤争取且该步骤参数正确,将得到回应:{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"loginCheck":"Y"},"messages":[],"validateMessages":{}}

1.5 用户登录

暂且称之为用户登录吧,因为是对https://kyfw.12306.cn/otn/login/userLogin进行一个GET请求,请求正文写死为:_json_att=

1.6 初始化用户首页

对https://kyfw.12306.cn/otn/index/initMy12306执行GET请求,即可得到登录之后的用户首页。


2.参考博文

(1) Fiddler教程

(2) 玩转12306之系统登录

(3) C# winForm中调用javascript文件中的方法

感谢这些博文的博主!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值