autoFillCredentials - jquery

自动填充表单账号密码

// ==UserScript==
// @name         autoFillCredentials - jquery
// @namespace    http://tampermonkey.net/
// @version      1.7.3
// @description  自动填充表单账号密码
// @author       ltond
// @license MIT
// @match        */dxdsapi/login.html
// @require      https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/3.3.2/jsencrypt.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
// @grant        GM_addStyle
// ==/UserScript==


(function ($, JSEncrypt) {
  'use strict';

  const autoFillCredentials = {
    datas: {
      accountList: [
        { account: 'developer_da', password: '1qaz@WSX', role: '普通' },
        { account: 'developer_da_2', password: '1qaz@WSX', role: '两票监护人一' },
        { account: 'developer_da_6', password: '1qaz@WSX', role: '两票监护人二' },
        { account: 'developer_da_3', password: '1qaz@WSX', role: '值班负责人' },
        { account: 'developer_da_4', password: '1qaz@WSX', role: '值长' },
        { account: 'developer_da_5', password: '1qaz@WSX', role: '监察人员' },
        { account: 'test_lp_gly', password: '1qaz@WSX', role: '两票管理员' },
        { account: 'developer', password: '1qaz@WSX' },
        { account: 'admin', password: 'NWH11qaz@WSX' },
        { account: 'developer_qianfar', password: '1qaz@WSX', label: '两票签发人' },
        { account: 'test_lp_pt', password: '1qaz@WSX', label: '(测试普通)' },
        { account: 'test_lp_jhr', password: '1qaz@WSX', label: '测试两票监护人' },
        { account: 'test_lp_zz', password: '1qaz@WSX', label: '测试两票值长' },
        { account: 'test_lp_jc', password: '1qaz@WSX', label: '测试两票监察' },
        { account: 'test_lp_zbfzr', password: '1qaz@WSX', label: '测试两票值班负责人' },

        { account: "LP-TEST01", password: "1qaz@WSX", label: "两票监护人" },
        { account: "LP-TEST02", password: "1qaz@WSX", label: "值班负责人" },
        { account: "LP-TEST03", password: "1qaz@WSX", label: "两票值长" },
        { account: "LP-TEST04", password: "1qaz@WSX", label: "两票监察" },
        { account: "test_lp_fzr", password: "1qaz@WSX", label: "测试负责人" },
        { account: "test_lp_qfr", password: "1qaz@WSX", label: "测试两票签发人" },
        { account: "test_lp_xkr", password: "1qaz@WSX", label: "测试两票许可人" },
        { account: "test_lp_yzqfr", password: "1qaz@WSX", label: "测试两票业主签发人" },

        { account: 'zyadmin', password: 'NWH11qaz@WSX' },

        { account: "fbh", password: "", label: "冯渤皓" },
        { account: "zhangcongyue", password: "", label: "张从粤" },
        { account: "Zqg12345", password: "", label: "曾琪洸" },
        { account: "chenlong", password: "", label: "陈龙" },
        { account: "developer01", password: "", label: "开发测试01" },
        { account: "developer02", password: "", label: "开发测试02" },
        { account: "luokai", password: "", label: "罗凯" },
        { account: "test01", password: "QAZwsx123", label: "建设单位测试员" },
        { account: "test_developer", password: "", label: "开发测试账号" },
        { account: "developer_da_6", password: "", label: "监护人二" },
        { account: "yjzces111", password: "", label: "测试删除" },
        { account: "testMing", password: "", label: "测试明" },
        { account: "testMing2", password: "", label: "测试明明" },
        { account: "testgong2", password: "", label: "龚" },
        { account: "testgong", password: "", label: "龚京旗" },

        { account: 'ZZGTest1', password: 'ZZGTest1' },
        { account: 'Lk123456', password: 'Lk123456' },
        { account: 'Test10', password: 'Test10' },
        { account: 'mr_test1', password: 'QAZwsx12345' },
        { account: 'zhangyue', password: 'QAZwsx12345' },
        { account: 'zhangcongyue', password: 'Zcy123456', label: '张从粤' },
        { account: 'ai_tingyan', password: 'QAZwsx12345' },
        { account: 'leitongda', password: 'ABCabc123456' },
        { account: 'li_xiaohu', password: 'Ctg111111' },
        { account: 'li_zhiliang', password: 'QAZwsx12345' },
        { account: 'long_tan', password: 'QAZwsx12345' },
        { account: 'ma_qiang', password: 'QAZwsx12345' },
        { account: 'wang_xiuwei', password: 'QAZwsx12345' },
        { account: 'xu_li', password: 'QAZwsx12345' },
        { account: 'yang_jicheng', password: 'QAZwsx12345' },
        { account: 'yao_pujie', password: 'QAZwsx12345' },
      ],
      pubKey: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeVp+B5QC2io6RJYx5NtMryiE02yIRVi0Ead2Oaklfo6cc/vBoSh35oxVDA2WSfgP5JwZ74DqRHFHt5LbXVnR//CebiHrvaFfcF31TNIriDtvitGqGaONbzRSYjI0t4OVHUtR1MGXtD+yCuXnLnZJE8Rnn+c5YHROG+AH3gV6t1wIDAQAB',
      username: '',
      password: '',

      encryptedAccount: '',
      encryptedPassword: '',

      ajaxPath: '/dxdsapi/dologin',
      currentRequests: {},

      vesion: 1,

      itemIndex: 0,
      maxLength: 0,
    },
    init() {
      if ($('form[action=dologin]').length !== 1) {
        $('body').empty();
        $('body').append(`
          <div>
            <h1>Whitelabel Error Page</h1>
            <form action="dologin" method="post">
              <div>
                <span>用户名:</span>
                <input id="j_username" name="j_username" type="text"></input>
              </div>
              <div>
                <span>密码:</span>
                <input id="pwd" name="j_password" type="password"></input>
              </div>

              <div>
                <button type="submit">登录</button>
              </div>
            </form>
          </div>
        `)
      }

      // 引入 Bootstrap CSS 样式
      this.loadBootstrapCSS();

      if ($('body').text().includes('Error occured while trying to proxy')) {
        return;
      }

      const { account, password } = this.datas.accountList[0];

      this.render();
      this.bindEvents();

      this.updateCredentials(account, password);

      this.configureAjax();
    },
    render() {
      this.$form = $('form').addClass('container form-container mt-5 mb-5 p-4 border-0 rounded  shadow');

      // 表单控件的样式
      this.$input_username = $('input[name="j_username"]').addClass('form-control mb-3');
      this.$input_password = $('input[name="j_password"]').addClass('form-control mb-3');
      $('span').addClass('form-label me-2');

      this.$submit = $('button[type="submit"]').addClass('btn btn-primary w-100');

      // 生成账号列表
      this.generateAccountList();
    },
    bindEvents() {
      const me = this;
      // // 将事件绑定到提交按钮,避免使用外部方法(如 $.proxy)
      // me.$submit.on('click', (e) => {
      //   e.preventDefault();  // 阻止表单默认提交
      //   me.handleSubmit();  // 执行表单提交逻辑
      // });

      $(document).on('keydown', this.handleNavigation.bind(this));
      this.$listContainer.on('click', '.list-group-item', this.handleAccountSelection.bind(this));

    },
    handleNavigation(e) {
      if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
        this.navigateList(1);
      } else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
        this.navigateList(-1);
      }
    },
    updateSelectedAccount() {
      const { accountList, itemIndex } = this.datas;
      const { account, password } = accountList[itemIndex];
      this.updateCredentials(account, password);

      // 更新界面显示
      this.$listContainer
        .find('.list-group-item')
        .removeClass('active')
        .eq(itemIndex)
        .addClass('active');
    },

    navigateList(step) {
      this.datas.itemIndex = (this.datas.itemIndex + step + this.datas.accountList.length) % this.datas.accountList.length;
      this.updateSelectedAccount();
    },
    handleAccountSelection(e) {
      const { account, password } = $(e.currentTarget).data('accountData');
      this.updateCredentials(account, password);
      this.datas.itemIndex = $(e.currentTarget).addClass('active').parent().index();
      $(e.currentTarget).addClass('active').parent().siblings().find('.list-group-item').removeClass('active');
    },
    configureAjax: function () {
      var me = this;

      // 设置Ajax请求的默认值
      $.ajaxSetup({
        url: me.datas.ajaxPath,
        dataType: 'json',
        beforeSend: function (xhr, settings) {
          me.datas.version += 1;
          settings.data = settings.data + `&k=${Math.random().toString(16).slice(2).toUpperCase()}&v=${me.datas.version}`
        },
        statusCode: {
          404: () => console.log(404),
          405: () => console.log(405),
          500: () => console.log(500),
          502: () => console.log(502),
        }
      });

      // 预过滤器
      $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
        console.log(options, originalOptions, jqXHR)
        // 自定义abortOnRetry选项被设置为true
        // 那么调用$.ajax()会自动中止请求相同的URL:
        if (options.abortOnRetry) {
          if (me.datas.currentRequests[options.url]) {
            me.datas.currentRequests[options.url].abort();
          }
          me.datas.currentRequests[options.url] = jqXHR;
        }

        // 代理服务器跨域请求
        // if (options.crossDomain) {
        //     options.url = 'http://localhost/test' + decodeURIComponent(options.url);
        //     options.crossDomain = false;
        // }
      });
    },
    handleSubmit() {
      const payload = {
        j_username: this.$input_username.val(),
        j_password: this.$input_password.val(),
      }
      console.log("🚀 ~ Form submitted with data:",);
      // 在这里可以做提交的处理逻辑

      $.ajax({
        // 同一域中强制跨域请求
        crossDomain: true,
        abortOnRetry: true,
        type: 'POST',
        dataType: 'json',
        // content: this,
        contentType: 'application/x-www-form-urlencoded',
        data: payload
      }).then(function (data, textStatus, jqXHR) {
        console.log("🚀 ~ handleSubmit ~ data, textStatus, jqXHR:", data, textStatus, jqXHR)

      }, function (jqXHR, textStatus, errorThrown) {
        console.log("🚀 ~ handleSubmit ~ jqXHR, textStatus, errorThrown:", jqXHR, textStatus, errorThrown)

      }).done(function (data, textStatus, jqXHR) {
        console.log("🚀 ~ handleSubmit ~ data:", data)
        console.log('Success...')
      }).fail(function (jqXHR, textStatus, errorThrown) {
        console.log('Error...')
      }).always(function (jqXHR, textStatus, errorThrown) {
        console.log('Complete...')
      })
    },
    loadBootstrapCSS() {
      // 提前加载 Bootstrap 样式,避免每次渲染时都重新加载
      if (!$('link[href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css"]').length) {
        $('<link>', {
          rel: 'stylesheet',
          href: 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css'
        }).appendTo('head');
      }
    },
    updateCredentials(account, password) {
      const encryptedAccount = encodeURIComponent(this.rsaEncrypt(account) || '');
      const encryptedPassword = encodeURIComponent(this.rsaEncrypt(password) || '');
      this.$input_username.val(encryptedAccount);
      this.$input_password.val(encryptedPassword);
      this.$submit.text(`登录 [${account}]`);
    },
    rsaEncrypt(value) {
      const encryptor = new JSEncrypt(10); // 创建加密对象实例
      encryptor.setPublicKey(this.datas.pubKey); // 设置公钥
      return encryptor.encrypt(value);
    },
    generateAccountList() {
      this.$listContainer = $('<div class="container mt-5 list-group  mb-3 p-0">').appendTo('body');
      const $accountList = $('<div class="row ">').appendTo(this.$listContainer); // 使用 row 来包裹两列
      this.datas.accountList.forEach((accountData, index) => {
        const $col = $('<div class="col-md-6 col-lg-4 col-xl-3 col-xxl-3 mb-2">'); // 每个列表项占一列
        $('<div>', {
          class: 'list-group-item border px-3 py-3 rounded-4',
          tabindex: index,
          text: `${accountData.label || accountData.account} ${accountData.role || ''}`,
          data: { accountData }
        }).appendTo($col);
        $col.appendTo($accountList);
      });

    },
  }

  autoFillCredentials.init()

  GM_addStyle(`
    body {
      font-family: Fira Code, Consolas !important;
    }

    .btn-primary {
      --bs-btn-bg: #FF5722;
      --bs-btn-border-color: #FF5722;
      --bs-btn-hover-bg: #FF5722;
      --bs-btn-hover-border-color: #FF5722;
      --bs-btn-active-bg: #FF5722;
      --bs-btn-active-border-color: #FF5722;
      --bs-btn-disabled-bg: #ff57224d;
      --bs-btn-disabled-border-color: #ff57224d;
    }

    .list-group-item {
      cursor: pointer;
      white-space: nowrap;
      font-family: Fira Code, Consolas;
      font-size: 14px;
      --bs-list-group-active-bg: #ff5722;
    }

    .list-group-item::before {
      content: "";
      display: inline-block;
      margin-right: 10px;
      width: 5px;
      height: 5px;
      border-radius: 50%;
      background-color: #000;
      vertical-align: 2px;
    }


    .list-group-item.active::before {
      background-color: #fff;
    }


    pre {
      white-space: normal;
      font-family: Fira Code, Consolas !important;
      font-size: 14px;
      font-weight: 300;
      line-height: 26px;
    }

    .form-container {
      box-shadow: 0 1px 2px -2px #00000029, 0 3px 6px #0000001f, 0 5px 12px 4px #00000017;
    }
  `);

})(jQuery, JSEncrypt);