高校教务系统登录页面JS分析——华南农业大学

news2025/2/21 19:45:07

高校教务系统密码加密逻辑及JS逆向

本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文,你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。

本文仅供交流学习,勿用于非法用途。

一、密码加密基本概念

密码加密是一种保护信息安全的技术手段,它通过将明文(原始信息)转换为密文(加密后的信息),以防止未经授权的访问和篡改。常见的密码加密算法有MD5、SHA-1、SHA-256等。

1.1 加密过程

加密过程通常包括以下步骤:

  1. 密钥扩展:将密钥扩展为多个轮值,每个轮值都与明文的一部分有关。
  2. 初始轮值生成:将扩展后的密钥与轮常数进行某种运算,生成第一轮加密的密文。
  3. 多轮迭代:对密文进行多轮迭代操作,每轮操作都包括非线性函数、模运算和轮常数的变换。
  4. 最终密文:经过多轮迭代后,得到最终的密文。

1.2 解密过程

解密过程与加密过程相反,通过反向操作来恢复原始明文。通常需要知道加密时使用的密钥和算法。

二、高校教务系统密码加密逻辑分析

2.1 抓包

我们首先打开教务系统的登录页面,我们可以看到,只有学号和密码,有的高校会有验证码,或者有的高校是错误一次密码,会验证验证码。

我们打开开发者工具,尝试登录抓包,网页会返回这样的数据接口。

2.2 分析加密参数

我们接下来,就是来分析这个密码是怎么加密的。我们全局搜索password。定位到加密的位置。

我们搜索之后,会发现找不到,我们重新刷新一下网页,我们先不用登录,为什么搜不到,因为网页结构发生了变化。

我们搜索password,发现上面有一行字符串,我们仔细一看,就是加密方法。接下来,就是扣代码了。

三、JS逆向分析方法

逆向分析是指从已知的加密文本或程序中还原出原始信息的过程。在本例中,我们将使用JavaScript编写一个简单的逆向分析工具,用于逆向高校教务系统的密码。

环境使用

  • python 3.9
  • pycharm
  • node

我们全局搜索encryptedString,我们接下来就是扣这个函数吗,看缺什么补什么。这个就比较简单了,直接扣下来就可以了。

代码实现

我们先把这些代码扣下来,运行看看缺什么补什么。


var biRadixBits = 16;
var bitsPerDigit = biRadixBits;
var biRadix = 1 << 16; // = 2^16 = 65536
var biHalfRadix = biRadix >>> 1;
var biRadixSquared = biRadix * biRadix;
var maxDigitVal = biRadix - 1;

var maxDigits;
var ZERO_ARRAY;
var bigZero, bigOne;

function setMaxDigits(value)
{
	maxDigits = value;
	ZERO_ARRAY = new Array(maxDigits);
	for (var iza = 0; iza < ZERO_ARRAY.length; iza++) ZERO_ARRAY[iza] = 0;
	bigZero = new BigInt();
	bigOne = new BigInt();
	bigOne.digits[0] = 1;
}

setMaxDigits(20);

var dpl10 = 15;
// lr10 = 10 ^ dpl10
var lr10 = biFromNumber(1000000000000000);

function BigInt(flag)
{
	if (typeof flag == "boolean" && flag == true) {
		this.digits = null;
	}
	else {
		this.digits = ZERO_ARRAY.slice(0);
	}
	this.isNeg = false;
}


function biCopy(bi)
{
	var result = new BigInt(true);
	result.digits = bi.digits.slice(0);
	result.isNeg = bi.isNeg;
	return result;
}

function biFromNumber(i)
{
	var result = new BigInt();
	result.isNeg = i < 0;
	i = Math.abs(i);
	var j = 0;
	while (i > 0) {
		result.digits[j++] = i & maxDigitVal;
		i = Math.floor(i / biRadix);
	}
	return result;
}

function reverseStr(s)
{
	var result = "";
	for (var i = s.length - 1; i > -1; --i) {
		result += s.charAt(i);
	}
	return result;
}

var hexatrigesimalToChar = new Array(
 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
 'u', 'v', 'w', 'x', 'y', 'z'
);

function biToString(x, radix)
	// 2 <= radix <= 36
{
	var b = new BigInt();
	b.digits[0] = radix;
	var qr = biDivideModulo(x, b);
	var result = hexatrigesimalToChar[qr[1].digits[0]];
	while (biCompare(qr[0], bigZero) == 1) {
		qr = biDivideModulo(qr[0], b);
		digit = qr[1].digits[0];
		result += hexatrigesimalToChar[qr[1].digits[0]];
	}
	return (x.isNeg ? "-" : "") + reverseStr(result);
}


var hexToChar = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                          'a', 'b', 'c', 'd', 'e', 'f');

function digitToHex(n)
{
	var mask = 0xf;
	var result = "";
	for (i = 0; i < 4; ++i) {
		result += hexToChar[n & mask];
		n >>>= 4;
	}
	return reverseStr(result);
}

function biToHex(x)
{
	var result = "";
	var n = biHighIndex(x);
	for (var i = biHighIndex(x); i > -1; --i) {
		result += digitToHex(x.digits[i]);
	}
	return result;
}

function charToHex(c)
{
	var ZERO = 48;
	var NINE = ZERO + 9;
	var littleA = 97;
	var littleZ = littleA + 25;
	var bigA = 65;
	var bigZ = 65 + 25;
	var result;

	if (c >= ZERO && c <= NINE) {
		result = c - ZERO;
	} else if (c >= bigA && c <= bigZ) {
		result = 10 + c - bigA;
	} else if (c >= littleA && c <= littleZ) {
		result = 10 + c - littleA;
	} else {
		result = 0;
	}
	return result;
}

function hexToDigit(s)
{
	var result = 0;
	var sl = Math.min(s.length, 4);
	for (var i = 0; i < sl; ++i) {
		result <<= 4;
		result |= charToHex(s.charCodeAt(i))
	}
	return result;
}

function biFromHex(s)
{
	var result = new BigInt();
	var sl = s.length;
	for (var i = sl, j = 0; i > 0; i -= 4, ++j) {
		result.digits[j] = hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4)));
	}
	return result;
}


function biAdd(x, y)
{
	var result;

	if (x.isNeg != y.isNeg) {
		y.isNeg = !y.isNeg;
		result = biSubtract(x, y);
		y.isNeg = !y.isNeg;
	}
	else {
		result = new BigInt();
		var c = 0;
		var n;
		for (var i = 0; i < x.digits.length; ++i) {
			n = x.digits[i] + y.digits[i] + c;
			result.digits[i] = n % biRadix;
			c = Number(n >= biRadix);
		}
		result.isNeg = x.isNeg;
	}
	return result;
}

function biSubtract(x, y)
{
	var result;
	if (x.isNeg != y.isNeg) {
		y.isNeg = !y.isNeg;
		result = biAdd(x, y);
		y.isNeg = !y.isNeg;
	} else {
		result = new BigInt();
		var n, c;
		c = 0;
		for (var i = 0; i < x.digits.length; ++i) {
			n = x.digits[i] - y.digits[i] + c;
			result.digits[i] = n % biRadix;
			// Stupid non-conforming modulus operation.
			if (result.digits[i] < 0) result.digits[i] += biRadix;
			c = 0 - Number(n < 0);
		}
		// Fix up the negative sign, if any.
		if (c == -1) {
			c = 0;
			for (var i = 0; i < x.digits.length; ++i) {
				n = 0 - result.digits[i] + c;
				result.digits[i] = n % biRadix;
				// Stupid non-conforming modulus operation.
				if (result.digits[i] < 0) result.digits[i] += biRadix;
				c = 0 - Number(n < 0);
			}
			// Result is opposite sign of arguments.
			result.isNeg = !x.isNeg;
		} else {
			// Result is same sign.
			result.isNeg = x.isNeg;
		}
	}
	return result;
}


function biHighIndex(x)
{
	var result = x.digits.length - 1;
	while (result > 0 && x.digits[result] == 0) --result;
	return result;
}

function biNumBits(x)
{
	var n = biHighIndex(x);
	var d = x.digits[n];
	var m = (n + 1) * bitsPerDigit;
	var result;
	for (result = m; result > m - bitsPerDigit; --result) {
		if ((d & 0x8000) != 0) break;
		d <<= 1;
	}
	return result;
}

function biMultiply(x, y)
{
	var result = new BigInt();
	var c;
	var n = biHighIndex(x);
	var t = biHighIndex(y);
	var u, uv, k;

	for (var i = 0; i <= t; ++i) {
		c = 0;
		k = i;
		for (j = 0; j <= n; ++j, ++k) {
			uv = result.digits[k] + x.digits[j] * y.digits[i] + c;
			result.digits[k] = uv & maxDigitVal;
			c = uv >>> biRadixBits;
			//c = Math.floor(uv / biRadix);
		}
		result.digits[i + n + 1] = c;
	}
	// Someone give me a logical xor, please.
	result.isNeg = x.isNeg != y.isNeg;
	return result;
}

function biMultiplyDigit(x, y)
{
	var n, c, uv;

	result = new BigInt();
	n = biHighIndex(x);
	c = 0;
	for (var j = 0; j <= n; ++j) {
		uv = result.digits[j] + x.digits[j] * y + c;
		result.digits[j] = uv & maxDigitVal;
		c = uv >>> biRadixBits;
		//c = Math.floor(uv / biRadix);
	}
	result.digits[1 + n] = c;
	return result;
}

function arrayCopy(src, srcStart, dest, destStart, n)
{
	var m = Math.min(srcStart + n, src.length);
	for (var i = srcStart, j = destStart; i < m; ++i, ++j) {
		dest[j] = src[i];
	}
}

var highBitMasks = new Array(0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
                             0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
                             0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF);

function biShiftLeft(x, n)
{
	var digitCount = Math.floor(n / bitsPerDigit);
	var result = new BigInt();
	arrayCopy(x.digits, 0, result.digits, digitCount,
	          result.digits.length - digitCount);
	var bits = n % bitsPerDigit;
	var rightBits = bitsPerDigit - bits;
	for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) {
		result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) |
		                   ((result.digits[i1] & highBitMasks[bits]) >>>
		                    (rightBits));
	}
	result.digits[0] = ((result.digits[i] << bits) & maxDigitVal);
	result.isNeg = x.isNeg;
	return result;
}
var lowBitMasks = new Array(0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
                            0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
                            0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF);

function biShiftRight(x, n)
{
	var digitCount = Math.floor(n / bitsPerDigit);
	var result = new BigInt();
	arrayCopy(x.digits, digitCount, result.digits, 0,
	          x.digits.length - digitCount);
	var bits = n % bitsPerDigit;
	var leftBits = bitsPerDigit - bits;
	for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) {
		result.digits[i] = (result.digits[i] >>> bits) |
		                   ((result.digits[i1] & lowBitMasks[bits]) << leftBits);
	}
	result.digits[result.digits.length - 1] >>>= bits;
	result.isNeg = x.isNeg;
	return result;
}

function biMultiplyByRadixPower(x, n)
{
	var result = new BigInt();
	arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n);
	return result;
}

function biDivideByRadixPower(x, n)
{
	var result = new BigInt();
	arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n);
	return result;
}

function biModuloByRadixPower(x, n)
{
	var result = new BigInt();
	arrayCopy(x.digits, 0, result.digits, 0, n);
	return result;
}

function biCompare(x, y)
{
	if (x.isNeg != y.isNeg) {
		return 1 - 2 * Number(x.isNeg);
	}
	for (var i = x.digits.length - 1; i >= 0; --i) {
		if (x.digits[i] != y.digits[i]) {
			if (x.isNeg) {
				return 1 - 2 * Number(x.digits[i] > y.digits[i]);
			} else {
				return 1 - 2 * Number(x.digits[i] < y.digits[i]);
			}
		}
	}
	return 0;
}

function biDivideModulo(x, y)
{
	var nb = biNumBits(x);
	var tb = biNumBits(y);
	var origYIsNeg = y.isNeg;
	var q, r;
	if (nb < tb) {
		// |x| < |y|
		if (x.isNeg) {
			q = biCopy(bigOne);
			q.isNeg = !y.isNeg;
			x.isNeg = false;
			y.isNeg = false;
			r = biSubtract(y, x);
			// Restore signs, 'cause they're references.
			x.isNeg = true;
			y.isNeg = origYIsNeg;
		} else {
			q = new BigInt();
			r = biCopy(x);
		}
		return new Array(q, r);
	}

	q = new BigInt();
	r = x;

	// Normalize Y.
	var t = Math.ceil(tb / bitsPerDigit) - 1;
	var lambda = 0;
	while (y.digits[t] < biHalfRadix) {
		y = biShiftLeft(y, 1);
		++lambda;
		++tb;
		t = Math.ceil(tb / bitsPerDigit) - 1;
	}
	// Shift r over to keep the quotient constant. We'll shift the
	// remainder back at the end.
	r = biShiftLeft(r, lambda);
	nb += lambda; // Update the bit count for x.
	var n = Math.ceil(nb / bitsPerDigit) - 1;

	var b = biMultiplyByRadixPower(y, n - t);
	while (biCompare(r, b) != -1) {
		++q.digits[n - t];
		r = biSubtract(r, b);
	}
	for (var i = n; i > t; --i) {
    var ri = (i >= r.digits.length) ? 0 : r.digits[i];
    var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1];
    var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2];
    var yt = (t >= y.digits.length) ? 0 : y.digits[t];
    var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1];
		if (ri == yt) {
			q.digits[i - t - 1] = maxDigitVal;
		} else {
			q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt);
		}

		var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1);
		var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2);
		while (c1 > c2) {
			--q.digits[i - t - 1];
			c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1);
			c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2);
		}

		b = biMultiplyByRadixPower(y, i - t - 1);
		r = biSubtract(r, biMultiplyDigit(b, q.digits[i - t - 1]));
		if (r.isNeg) {
			r = biAdd(r, b);
			--q.digits[i - t - 1];
		}
	}
	r = biShiftRight(r, lambda);
	// Fiddle with the signs and stuff to make sure that 0 <= r < y.
	q.isNeg = x.isNeg != origYIsNeg;
	if (x.isNeg) {
		if (origYIsNeg) {
			q = biAdd(q, bigOne);
		} else {
			q = biSubtract(q, bigOne);
		}
		y = biShiftRight(y, lambda);
		r = biSubtract(y, r);
	}
	// Check for the unbelievably stupid degenerate case of r == -0.
	if (r.digits[0] == 0 && biHighIndex(r) == 0) r.isNeg = false;

	return new Array(q, r);
}

function biDivide(x, y)
{
	return biDivideModulo(x, y)[0];
}



function RSAKeyPair(encryptionExponent, decryptionExponent, modulus)
{
	this.e = biFromHex(encryptionExponent);
	this.d = biFromHex(decryptionExponent);
	this.m = biFromHex(modulus);
	// We can do two bytes per digit, so
	// chunkSize = 2 * (number of digits in modulus - 1).
	// Since biHighIndex returns the high index, not the number of digits, 1 has
	// already been subtracted.
	this.chunkSize = 2 * biHighIndex(this.m);
	this.radix = 16;
	this.barrett = new BarrettMu(this.m);
}

function twoDigit(n)
{
	return (n < 10 ? "0" : "") + String(n);
}

function encryptedString(key, s)
	// Altered by Rob Saunders (rob@robsaunders.net). New routine pads the
	// string after it has been converted to an array. This fixes an
	// incompatibility with Flash MX's ActionScript.
{
	var a = new Array();
	var sl = s.length;
	var i = 0;
	while (i < sl) {
		a[i] = s.charCodeAt(i);
		i++;
	}

	while (a.length % key.chunkSize != 0) {
		a[i++] = 0;
	}

	var al = a.length;
	var result = "";
	var j, k, block;
	for (i = 0; i < al; i += key.chunkSize) {
		block = new BigInt();
		j = 0;
		for (k = i; k < i + key.chunkSize; ++j) {
			block.digits[j] = a[k++];
			block.digits[j] += a[k++] << 8;
		}
		var crypt = key.barrett.powMod(block, key.e);
		var text = key.radix == 16 ? biToHex(crypt) : biToString(crypt, key.radix);
		result += text + " ";
	}
	return result.substring(0, result.length - 1); // Remove last space.
}



function BarrettMu(m)
{
	this.modulus = biCopy(m);
	this.k = biHighIndex(this.modulus) + 1;
	var b2k = new BigInt();
	b2k.digits[2 * this.k] = 1; // b2k = b^(2k)
	this.mu = biDivide(b2k, this.modulus);
	this.bkplus1 = new BigInt();
	this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1)
	this.modulo = BarrettMu_modulo;
	this.multiplyMod = BarrettMu_multiplyMod;
	this.powMod = BarrettMu_powMod;
}

function BarrettMu_modulo(x)
{
	var q1 = biDivideByRadixPower(x, this.k - 1);
	var q2 = biMultiply(q1, this.mu);
	var q3 = biDivideByRadixPower(q2, this.k + 1);
	var r1 = biModuloByRadixPower(x, this.k + 1);
	var r2term = biMultiply(q3, this.modulus);
	var r2 = biModuloByRadixPower(r2term, this.k + 1);
	var r = biSubtract(r1, r2);
	if (r.isNeg) {
		r = biAdd(r, this.bkplus1);
	}
	var rgtem = biCompare(r, this.modulus) >= 0;
	while (rgtem) {
		r = biSubtract(r, this.modulus);
		rgtem = biCompare(r, this.modulus) >= 0;
	}
	return r;
}

function BarrettMu_multiplyMod(x, y)
{
	/*
	x = this.modulo(x);
	y = this.modulo(y);
	*/
	var xy = biMultiply(x, y);
	return this.modulo(xy);
}

function BarrettMu_powMod(x, y)
{
	var result = new BigInt();
	result.digits[0] = 1;
	var a = x;
	var k = y;
	while (true) {
		if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a);
		k = biShiftRight(k, 1);
		if (k.digits[0] == 0 && biHighIndex(k) == 0) break;
		a = this.multiplyMod(a, a);
	}
	return result;
}



var thisPwd = '1234';
setMaxDigits(131);
var key = new RSAKeyPair("010001", '', "008e9fdac2a933c27a8262eb0ab8004aa74571e1e7c27beb436ce17c37df778d8861a9a2afddc04a6e80da995e34754e1e002864f2480f0471257880b55359e8232601244593333eb9f0f99b894fe13538a80bfd14aeb94bb8108959140231195a9e9f488f7d5cc72a112d6a19576cb05eaf629435538907ccc9b008d64595646d");
var result = encryptedString(key, encodeURIComponent(thisPwd));
console.log(result)

 我这里直接把代码给大家,大家感兴趣可以先尝试直接去写,可以和我写的做比较。

实现效果

7e38cbd93d9b7a12c7c5149b4020c8438db9f1f6d2abe4228c68408249e8dadc0e3c5d71351e10943bac59144533fe5e23efd9f1ddd32b1c61afc48462ecc0dd8060ab2d2ee6a5bfeb5a3e382cda98a700d5416303d1adc3770d3494c20c4836dba733daae0b3c6f5dc2a558ed8e300be83af7a5f91156a0854376ad48d9be9d

我们可以发现,这个结果和网页的结果一样的,说明我们逆向成功了,这里的加密稍微有点复杂,一个函数去扣就可以了。 

四、总结

本文介绍了高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的方法。通过学习这些知识,你可以更好地理解密码加密技术的原理,并掌握一定的逆向分析技巧。请注意,逆向分析可能涉及到法律问题,请在合法范围内进行研究和实践。

五、累计更新

争取到到底早日更新30所高校,大家可以在评论区留言。前期更的可能会多一点,有的学校教务系统都没有加密,我这里就不写了,还有,部分学校的教务系统已经和我之前写的是一样的,我也不重复赘述了。

往期作品可以查看专栏👇👇👇

全国高校教务系统登录页面JS分析_爱吃饼干的小白鼠的博客-CSDN博客

6adf31c8c5dd4e6a83314f4805b30bc1.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115259.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[TCP1P 2023] 部分crypto,pwn,reverse

Crypto Final Consensus 这是个AES爆破密钥的题&#xff0c;加密方法是先后用两个密钥加密。远程先给出加密后的flag&#xff0c;然后允许输入值并进行加密。 from Crypto.Cipher import AES import random from Crypto.Util.Padding import pada b"" b b"&…

软件外包开发代码质量评测

软件开发代码质量的评测方法有很多种&#xff0c;它们可以帮助开发团队识别和改进潜在的问题&#xff0c;提高代码的可维护性、性能和安全性。以下是一些常见的代码质量评测方法和工具&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发…

C语言实现希尔排序

void ShellSort(int arr[], int n) {//希尔排序--升序int i 0;int j 0;int d n / 2;for (d n / 2;d > 1;d / 2) {for (i d;i < n;i) {int tmp arr[i];for (j i;j > 0;j - d) {if (tmp < arr[j - d]) {arr[j] arr[j - d];}else {arr[j] tmp;break;}}}} }in…

3DCAT实时云渲染赋能聚好看科技,打造3D沉浸式互动视频云平台

随着5G、云计算、XR等技术的发展&#xff0c;3D沉浸式互动视频已经成为了新一代的数字媒体形式&#xff0c;为各行各业带来了新的创新机遇和价值。然而&#xff0c;要实现高效、高质、高效率的3D沉浸式互动视频生产和传播&#xff0c;还需要强大的技术支撑和平台服务。 作为海…

SpringCloud:自定义skywalking链路追踪

一、添加依赖&#xff1a; <dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version>8.7.0</version></dependency><dependency><groupId>org.apache.sk…

蓝桥每日一题(day 3: 蓝桥587.约数个数)--数学--easy

题目 解题核心&#xff1a; 分解质因数&#xff0c;每个质因数的次方1的累乘积就是anscode #include <iostream> #include<algorithm> #include<unordered_map> //# #include<> typedef long long LL; const int N 110, MOD 1e9 7;using namespac…

【cmake】cmake生成Visual Studio工程后的INSTALL项目使用

很多开源项目使用CMake生成Visual Studio工程后会有INSTALL项目。 这个INSTALL项目是为安装编译产物&#xff0c;作用类似于make install。其使用与其他工程并不相同。 想安装编译产物&#xff0c;需右键INSTALL工程&#xff0c;在弹出的菜单中&#xff0c;选择“仅用于项目”…

搜维尔科技:Varjo-探讨汽车工业使用虚拟现实/XR的可能性

新的 奇亚EV9 被定位为起亚有史以来最豪华的车型。在一次活动中,起亚通过向芬兰媒体、利益相关者和经销商网络推出新的汽车车型(起亚EV9&#xff0c;EV9是一款高度超过5米的全电动车,拥有100千瓦的电池、快速充电能力、2500公斤的拖曳能力和7公斤的座位--这在市场上是一个独特的…

ABAP程序不报错却出错---解决

ALV字段名不显示 自建的透明表 REPORT ZTXYY_1123. DATA: gr_alv TYPE REF TO cl_salv_table,gr_columns TYPE REF TO cl_salv_columns_table. DATA: ZPL_LIST TYPE TABLE OF ZPL_EINVOICE_LOG. CALL METHOD cl_salv_table>factory IMPORTINGr_salv_table gr_alv CHAN…

14-bean创建流程5-初始化和循环依赖

文章目录 1.初始化和循环依赖1.1 初始化步骤1.2 循环依赖问题的产生1.3 如何解决循环依赖问题1.4 解决循环依赖二级缓存即可完成,为什么需要三级缓存1.5循环依赖有时报错1.初始化和循环依赖 1.1 初始化步骤 填充属性执行Aware执行BeanPostProcessor的postProcessBeforeInitia…

白水三佳电脑ERP部署

安装宝塔面板&#xff0c;有这个方便很多&#xff0c;可以省下3天的环境部署时间。 移动端&#xff0c; 先取移动版的压缩包&#xff0c;上传至服务器/www/wwwroot/目录下面&#xff0c;直接解压到当前目录后会生成/www/wwwroot/m/的目录&#xff0c;移动版就在这里面了。以下…

分频流水灯

在开发板中&#xff0c;有一个内置的时钟周期&#xff0c;为100MHZ&#xff0c;我们需要使用这样一个时钟信号来设计一个1HZ的流水灯&#xff08;使用8个led灯&#xff09;&#xff0c;也就是一秒钟有一个灯是亮起的&#xff0c;依次从左到右。 另外还有一个低有效的复位使能端…

(原创)实现左侧TextView宽度自适应并且可以显示右侧TextView的布局

效果展示 先来看看上面的效果 左侧的文字宽度是自适应的&#xff0c;但是右侧又有一个TextView 左侧的文字被限制不能把右侧的挤出屏幕外面 所以如果左侧文字超过指定宽度后多余部分就用省略号表示 实际开发中这种情况在一些列表的item中用的比较多 但实际实现的时候会发现 左侧…

RabbitMQ运行机制和通讯过程介绍

文章目录 1.RabbitMQ 环境搭建2.RabbitMQ简介3.RabbitMQ的优势&#xff1a;4. rabbitmq服务介绍4.1 rabbitmq关键词说明4.2 消息队列运行机制4.3 exchange类型 5.wireshark抓包查看RabbitMQ通讯过程 1.RabbitMQ 环境搭建 参考我的另一篇&#xff1a;RabbitMQ安装及使用教程&am…

2023备考软考中级-软件设计师资料

2023备考软考中级-软件设计师资料 一、资源目录介绍 1. 资源目录 2. 2004-2023年真题及答案解析 3. 03-第五版教材、大纲、笔记、精讲精练等 二、资源下载 2023备考软考中级-软件设计师 https://www.aliyundrive.com/s/7MPqUUuaY4K 点击链接保存&#xff0c;或者复制本段内容…

Java每日笔试题错题分析(7)

Java每日笔试题错题分析&#xff08;7&#xff09; 一、错题知识点前瞻第1题第2题第3题第4题第5题 二、错题展示及其解析第1题第2题第3题第4题第5题 一、错题知识点前瞻 第1题 非静态变量不能被静态方法引用 第2题 start()方法与run()方法 start()方法是启动一个线程&#xff…

KMP 算法 + 运用前后缀信息 + 案例分析 + 实战力扣题

一、理解KMP算法如何运用后缀和前缀的信息 文本串text:abcxabcdabxabcdabcdabcy模式串pattern:abcdabcy 当发现不匹配的点&#xff0c;我们的目标不是在这个串中进行回溯操作。因此我们要检查的是 d 的前面的子串&#xff08;abc&#xff09;&#xff0c;在这个子串&#xff08…

2000-2021年全国30省市水土流失治理面积、水库数量、水库总容量、除涝面积数据

2000-2021年全国30省市水土流失治理面积、水库数量、水库总容量、除涝面积数据 1、时间&#xff1a;1995-2020年 2、指标&#xff1a;水土流失治理面积、水库数量、水库总容量、除涝面积 3、范围:30省市不含上海 4、来源&#xff1a;国家统计J、各省NJ 5、指标解释&#x…

优秀数据库模式迁移工具的发展历程

数据库模式迁移可能是应用程序开发中风险最大的领域——因为这是一个困难的、有风险的和痛苦的过程。数据库模式迁移工具的存在是为了减轻这种痛苦&#xff0c;并且已经取得了长足的进步&#xff1a;从基本的CLI工具到GUI工具&#xff0c;从简单的SQL GUI客户端到一体化协作数据…