// ==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);