油猴支持阿里云自动登陆插件

遇到的以下问题,都已在脚本中解决:

  1. 获取到的元素赋值在页面显示,但是底层的value并没有改写,导致请求就是获取不到数据
  2. 元素的加载时机不定,尤其是弱网情况下,只靠延迟还是有可能获取不到,且登陆不丝滑,通过元素发现机制,解决此问题并做到丝滑登陆
  3. 根据密钥计算校验码之前做过,本次引入了一个外部依赖默认的计算跟预期不一致,卡了10分钟

参考资料:入门篇 | 油猴开发指南

复制代码
// ==UserScript==
// @name         阿里云自动登录
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  自动填写阿里云登录表单
// @author       你
// @match        https://signin.aliyun.com/*.onaliyun.com/login.htm?callback=*


// @grant        GM_getResourceText
// @resource user_info_url file://D:/temp/csdn/userinfo.json


// ==/UserScript==

(function() {
    'use strict';

    // 注意:这里应该替换为你的实际用户名和密码
    var username = "帐号"; // 替换为你的用户名
    var password = "密码"; // 替换为你的密码
    var secretKey = "填入密钥"

    // 用户信息保存在本地
    let info_content = GM_getResourceText('user_info_url');

    let user_info_json = JSON.parse(info_content);
    var username = user_info_json['username']
    var password = user_info_json['password']
    // 用来计算双因子验证码 的密钥
    var secretKey = user_info_json['secretKey']




    // 定义一个辅助函数来等待某个选择器对应的元素出现
    function waitForElement(inputSelect,tag, callback) {
        const observer = new MutationObserver((mutations) => {
            var ele_input = document.querySelector(inputSelect);

            var but_next = document.querySelector('.next-btn.next-large.next-btn-primary')
           
            // 判断所有想到的元素都已加载完成,才进行数据改写
            if (ele_input && but_next.innerText == tag) {
                observer.disconnect();
                callback(ele_input,tag);
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    // 对元素进行赋值
    function freshReactValue(input){
        const evt = new Event("change");
        // 对其进行事件触发
        input.dispatchEvent(evt);
        // 获取元素的所有键名,并通过find函数进行查找
        // find函数会根据传入的函数进行判断,返回正确的值,
        // 而我们的函数是判断前缀是否是__reactEventHandlers
        const prop = Object.keys(input).find((p) => p.startsWith("__reactEventHandlers"));
        // 获取到对应键名的对象,得到该对象的onchange函数,并且传入event
        input[prop].onChange(evt);
    }


    window.addEventListener('load', () => {
        // 用户名登陆m,
        waitForElement('#loginName',"下一步", (loginInput,tag) => {
            loginInput.value = username;
            console.error(username)
            // 刷新
            freshReactValue(loginInput);
            // 点击下一步
            var but_pass = document.querySelector('.next-btn.next-large.next-btn-primary')
            but_pass.click();

        });

        // 密码登陆
        waitForElement('#loginPassword',"登录", (passInput,tag) => {
            passInput.value = password;
            // 刷新
            freshReactValue(passInput);
            // 点击下一步
            var but_pass = document.querySelector('.next-btn.next-large.next-btn-primary')
            but_pass.click();
        });


        // 双因子验证码
        waitForElement('.next-input.next-medium input[placeholder="请输入 6 位数字安全码"]',"提交验证", (secr_input,tag) => {
            // 计算验证码
            const secret = GenerateTOTP(secretKey);
            secr_input.value = secret;
            // 刷新
            freshReactValue(secr_input);
            // 点击下一步
            var but_pass = document.querySelector('.next-btn.next-large.next-btn-primary')
            but_pass.click();
        });
    });





    // 双因子计算原始库,也可以使用远程引用 ,但是想着使用的文件不大,就直接放进来 了

    "use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
    "undefined"!=typeof module&&module.exports&&(module.exports=sjcl);
    sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.g(a.slice(b/32),32-(b&31)).slice(1);return void 0===c?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(0===a.length||0===b.length)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return 32===d?a.concat(b):sjcl.bitArray.g(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;return 0===
        b?0:32*(b-1)+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(32*a.length<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b&=31;0<c&&b&&(a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return!1;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
        c},g:function(a,b,c,d){var e;e=0;for(void 0===d&&(d=[]);32<=b;b-=32)d.push(c),c=0;if(0===b)return d.concat(a);for(e=0;e<a.length;e++)d.push(c|a[e]>>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32<b+a?c:d.pop(),1));return d},j:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}};
    sjcl.codec.base32={e:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",fromBits:function(a,b){var c="",d,e=0,g=sjcl.codec.base32.e,f=0,k=sjcl.bitArray.bitLength(a);for(d=0;5*c.length<k;)c+=g.charAt((f^a[d]>>>e)>>>27),5>e?(f=a[d]<<5-e,e+=27,d++):(f<<=5,e-=5);for(;c.length&5&&!b;)c+="=";return c},toBits:function(a){a=a.replace(/\s|=/g,"").toUpperCase();var b=[],c,d=0,e=sjcl.codec.base32.e,g=0,f;for(c=0;c<a.length;c++){f=e.indexOf(a.charAt(c));if(0>f)throw new sjcl.exception.invalid("this isn't base32!");27<d?(d-=
27,b.push(g^f>>>d),g=f<<32-d):(d+=5,g^=f<<32-d)}d&56&&b.push(sjcl.bitArray.partial(d&56,g,1));return b}};sjcl.hash.sha1=function(a){a?(this.d=a.d.slice(0),this.b=a.b.slice(0),this.a=a.a):this.reset()};sjcl.hash.sha1.hash=function(a){return(new sjcl.hash.sha1).update(a).finalize()};
    sjcl.hash.sha1.prototype={blockSize:512,reset:function(){this.d=this.h.slice(0);this.b=[];this.a=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.b=sjcl.bitArray.concat(this.b,a);b=this.a;a=this.a=b+sjcl.bitArray.bitLength(a);for(b=this.blockSize+b&-this.blockSize;b<=a;b+=this.blockSize)n(this,c.splice(0,16));return this},finalize:function(){var a,b=this.b,c=this.d,b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);
b.push(Math.floor(this.a/0x100000000));for(b.push(this.a|0);b.length;)n(this,b.splice(0,16));this.reset();return c},h:[1732584193,4023233417,2562383102,271733878,3285377520],i:[1518500249,1859775393,2400959708,3395469782]};
    function n(a,b){var c,d,e,g,f,k,m,l=b.slice(0),h=a.d;e=h[0];g=h[1];f=h[2];k=h[3];m=h[4];for(c=0;79>=c;c++)16<=c&&(l[c]=(l[c-3]^l[c-8]^l[c-14]^l[c-16])<<1|(l[c-3]^l[c-8]^l[c-14]^l[c-16])>>>31),d=19>=c?g&f|~g&k:39>=c?g^f^k:59>=c?g&f|g&k|f&k:79>=c?g^f^k:void 0,d=(e<<5|e>>>27)+d+m+l[c]+a.i[Math.floor(c/20)]|0,m=k,k=f,f=g<<30|g>>>2,g=e,e=d;h[0]=h[0]+e|0;h[1]=h[1]+g|0;h[2]=h[2]+f|0;h[3]=h[3]+k|0;h[4]=h[4]+m|0}
    sjcl.misc.hmac=function(a,b){this.f=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.c=[new b,new b];a.length>e&&(a=b.hash(a));for(d=0;d<e;d++)c[0][d]=a[d]^909522486,c[1][d]=a[d]^1549556828;this.c[0].update(c[0]);this.c[1].update(c[1])};sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){a=(new this.f(this.c[0])).update(a).finalize();return(new this.f(this.c[1])).update(a).finalize()};



    function HOTP(K, C){
        var key = sjcl.codec.base32.toBits(K);

        // Count is 64 bits long.  Note that JavaScript bitwise operations make
        // the MSB effectively 0 in this case.
        var count = [((C & 0xffffffff00000000) >> 32), C & 0xffffffff];
        var otplength = 6;

        var hmacsha1 = new sjcl.misc.hmac(key, sjcl.hash.sha1);
        var code = hmacsha1.encrypt(count);

        var offset = sjcl.bitArray.extract(code, 152, 8) & 0x0f;
        var startBits = offset * 8;
        var endBits = startBits + 4 * 8;
        var slice = sjcl.bitArray.bitSlice(code, startBits, endBits);
        var dbc1 = slice[0];
        var dbc2 = dbc1 & 0x7fffffff;
        var otp = dbc2 % Math.pow(10, otplength);
        var result = otp.toString();
        while (result.length < otplength){
            result = '0' + result;
        }
        return result
    }

    // 计算双因子
    function GenerateTOTP(secret) {
        var ctime = Math.floor((new Date() - 0) / 30000);
        var code = HOTP(secret, ctime);
        return code;
    }


})();
相关推荐
₯㎕星空&繁华1 天前
阿里云服务器安装MySQL服务器
服务器·ubuntu·阿里云·云计算
云雾J视界2 天前
Flink Checkpoint与反压问题排查手册:从日志分析到根因定位
大数据·阿里云·flink·linq·checkpoint·反压
你的大佬9992 天前
阿里云百炼ai模型
人工智能·阿里云·云计算
一只栖枝2 天前
备考华为HCIA - 云计算,培训与自学到底该怎么选?
云计算·华为认证·hcia·考证·职业规划
数据与人工智能律师2 天前
AI的法治迷宫:技术层、模型层、应用层的法律痛点
大数据·网络·人工智能·云计算·区块链
荣光波比2 天前
Docker(三)—— Docker Compose 编排与 Harbor 私有仓库实战指南
运维·docker·容器·云计算
企鹅侠客3 天前
mysqldump导入备份数据到阿里云RDS会报错吗
阿里云·adb·云计算
iHero3 天前
【Jitsi Meet】阿里云Docker安装Jitsi Meet后的调整
阿里云·docker·云计算
荣光波比3 天前
Ansible(三)—— 使用Ansible自动化部署LNMP环境实战指南
运维·自动化·云计算·ansible
荣光波比3 天前
Docker(五)—— Docker Compose 一键搭建 LNMP 架构并部署 WordPress
运维·docker·容器·云计算