我解开了掘金在文章链接中的参数加密👏

702 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

思路分析

几天前,我想统计一下掘金的热门文章都是哪些方面的,调试页面后定位到 请求的接口(这个接口会异步拉取20条文章数据再渲染到页面上),这个接口的参数如下

图片.png

其中,当前最重要的 2 个参数是 cursor 游标,可以理解为是当前请求的资源是第几页, limit 可以理解为当前请求返回多少个数据

上图的请求参数是首屏渲染时自动请求的参数,然后,我们手动下拉滚动条时,页面会自动用 fetch 去拉下一屏的数据

图片.png

图片.png

上面两个图片的参数,就是通过 fetch 自动去拉的文章时的参数,拿出多个加密后 cursor 摆出来,研究一下规律

eyJ2IjoiNzAyMzYyMzk2NDExMDg4MDc4MiIsImkiOjIwfQ==
eyJ2IjoiNzAyMzYyMzk2NDExMDg4MDc4MiIsImkiOjYwfQ==
eyJ2IjoiNzAyMzYyMzk2NDExMDg4MDc4MiIsImkiOjgwfQ==

图片.png

观察发现仅仅一位不同,怀疑刚好是页面的游标变化造成的


一般来说,我们对数据加密常规有2种方案,① 是使用 md5 加密,但是不可逆的,② 是使用 base64,这个加密后是可以解密的

抱着试一试的心态,将那一串数据扔在线网站测试一下

图片.png

图片.png

图片.png

图片.png

可以很明显的看到,i 对应的就是游标的功能,意思是表示当前查询的数据起点是多少,配合开始的 limit 完成分页的效果,甚至可以怀疑 mybaits 的写法就是 select xx from xx limit ${cursor}, ${limit}

总结起来就是,对参数确实进行了加密,但只加密了一点点

js 如何实现 base64 加解密

既然这样,我们可以自己生成这个加密后的 cursor,然后直接调接口就可以拉取到对应的数据,我们最后对数据做分析即可

分享一下 js 里如何对字符做 base64 加解密(仅限英文、数字和符号的组合)

let base64 = function() {
    // private property  
    _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    return {
        encode(input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            while (i < input.length) {
                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);
            }
            return output;

        },
        decode(input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
            while (i < input.length) {
                enc1 = _keyStr.indexOf(input.charAt(i++));
                enc2 = _keyStr.indexOf(input.charAt(i++));
                enc3 = _keyStr.indexOf(input.charAt(i++));
                enc4 = _keyStr.indexOf(input.charAt(i++));
                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }
            }
            return output;

        }
    }
}();