某小程序sign签名参数逆向分析
文章目录
- 1. 写在前面
- 2. 接口分析
- 3. 分析还原
【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1. 写在前面
做爬虫脑子一定要灵光~不然怎么当大佬!正所谓大路不通走水路,水路不通走山路!相信很多工程师在面对一个端采集遇到瓶颈的时候什么M端、APP端、小程序端、Web端都几乎会挑一个或多个去摸排分析一下。风控这个东西很奇妙也很玄学,有时候还真有那么一些低风控的接口或者端存在
小程序端这么说吧,体量大点的风控基本都拉的很强且有的跟某信有因果!除非真的没有其他端的数据源了,一般少有人去(总之非可选的主流战场)
分析目标:
5Lmd5YS/572R57uc
2. 接口分析
随便通过关键词在搜索接口看看发包情况,直接Curl重放是403无效的,会出现签名错误。这个如下所示:
也就是说上面的sign是动态实时生成的,另外还有一个token参数也是有时效性的,将请求参数拿出来看看,如下所示:
data = {"method": "serverless.function.runtime.invoke","params": "{\"functionTarget\":\"DCloud-clientDB\",\"functionArgs\":{\"command\":{\"$db\":[{\"$method\":\"collection\",\"$param\":[\"a_novels\"]},{\"$method\":\"where\",\"$param\":[{\"novels_name\":{\"$regexp\":{\"source\":\"玄幻\",\"flags\":\"\"}}}]},{\"$method\":\"get\",\"$param\":[]}]},\"clientInfo\":{\"PLATFORM\":\"mp-weixin\",\"OS\":\"mac\",\"APPID\":\"__UNI__1B787A1\",\"DEVICEID\":\"17356293548006764541\",\"scene\":1089,\"deviceId\":\"17356293548006764541\",\"appId\":\"__UNI__1B787A1\",\"appName\":\"\",\"appVersion\":\"2.0.1\",\"appVersionCode\":\"201\",\"appLanguage\":\"zh-Hans\",\"uniCompilerVersion\":\"4.36\",\"uniRuntimeVersion\":\"4.36\",\"uniPlatform\":\"mp-weixin\",\"deviceBrand\":\"apple\",\"deviceModel\":\"MacBookPro15,2\",\"deviceType\":\"pc\",\"osName\":\"mac\",\"osVersion\":\"OS\",\"hostVersion\":\"3.8.7\",\"hostName\":\"WeChat\",\"locale\":\"zh-Hans\",\"LOCALE\":\"zh-Hans\"},\"uniIdToken\":\"\"}}","spaceId": "mp-f510ce55-6e44-40b0-b249-d278726b813d","timestamp": 1735785506387,"token": "63bc0ed6-f8a1-40ab-bb07-d11bf678ab21"
}
初看大概是MD5标准加密,拼接一下路径、参数加个时间戳啥的
3. 分析还原
在开始分析JS之前,可以通过反编译小程序的方式去分析也可以使用大佬开源的调试工具来辅助分析,有些Web端分析比较多的使用这个辅助还是蛮不错的。如下所示:
这里在页面直接搜索的话有时候资源多会比较慢,可以直接通过堆栈或者编译好的JS文件简单的进行静态分析,如下所示:
可以看到Ae就是生成签名的调用方法,而clientSecret是一段密文,后续它将参与加密用到,如下所示:
直接跳转到Ae方法处,可以看到Object.keys(e).sort()获取e对象里面的所有键进行一个排序,存在的话则使用&拼接,然后去掉所拼接字符串开头多余的一个&确保格式正确,如下所示:
接下来需要分析P方法,也就是最终的加密算法实现,进入当前方法直接来到了如下所示:
_createHmacHelper: function(e) {return function(t, n) {return new d.HMAC.init(e,n).finalize(t)}
}
这里推测d.HMAC是个库框架中的HMAC实现,而init(e, n)与finalize(t)是该HMAC对象的初始化和最终处理方法,注意入口处的时候是使用了密钥的,所以要分析是什么算法难度是不大的,肯定不是一个单纯的MD5,对应JS代码如下所示:
var k = A((function(e, t) {var n;e.exports = n = n || function(e, t) {var n = Object.create || function() {function e() {}return function(t) {var n;return e.prototype = t,n = new e,e.prototype = null,n}}(), r = {}, o = r.lib = {}, i = o.Base = {extend: function(e) {var t = n(this);return e && t.mixIn(e),t.hasOwnProperty("init") && this.init !== t.init || (t.init = function() {t.$super.init.apply(this, arguments)}),t.init.prototype = t,t.$super = this,t},create: function() {var e = this.extend();return e.init.apply(e, arguments),e},init: function() {},mixIn: function(e) {for (var t in e)e.hasOwnProperty(t) && (this[t] = e[t]);e.hasOwnProperty("toString") && (this.toString = e.toString)},clone: function() {return this.init.prototype.extend(this)}}, a = o.WordArray = i.extend({init: function(e, t) {e = this.words = e || [],this.sigBytes = null != t ? t : 4 * e.length},toString: function(e) {return (e || c).stringify(this)},concat: function(e) {var t = this.words, n = e.words, r = this.sigBytes, o = e.sigBytes;if (this.clamp(),r % 4)for (var i = 0; i < o; i++) {var a = n[i >>> 2] >>> 24 - i % 4 * 8 & 255;t[r + i >>> 2] |= a << 24 - (r + i) % 4 * 8}elsefor (i = 0; i < o; i += 4)t[r + i >>> 2] = n[i >>> 2];return this.sigBytes += o,this},clamp: function() {var t = this.words, n = this.sigBytes;t[n >>> 2] &= 4294967295 << 32 - n % 4 * 8,t.length = e.ceil(n / 4)},clone: function() {var e = i.clone.call(this);return e.words = this.words.slice(0),e},random: function(t) {for (var n, r = [], o = function(t) {t = t;var n = 987654321, r = 4294967295;return function() {var o = ((n = 36969 * (65535 & n) + (n >> 16) & r) << 16) + (t = 18e3 * (65535 & t) + (t >> 16) & r) & r;return o /= 4294967296,(o += .5) * (e.random() > .5 ? 1 : -1)}}, i = 0; i < t; i += 4) {var u = o(4294967296 * (n || e.random()));n = 987654071 * u(),r.push(4294967296 * u() | 0)}return new a.init(r,t)}}), u = r.enc = {}, c = u.Hex = {stringify: function(e) {for (var t = e.words, n = e.sigBytes, r = [], o = 0; o < n; o++) {var i = t[o >>> 2] >>> 24 - o % 4 * 8 & 255;r.push((i >>> 4).toString(16)),r.push((15 & i).toString(16))}return r.join("")},parse: function(e) {for (var t = e.length, n = [], r = 0; r < t; r += 2)n[r >>> 3] |= parseInt(e.substr(r, 2), 16) << 24 - r % 8 * 4;return new a.init(n,t / 2)}}, s = u.Latin1 = {stringify: function(e) {for (var t = e.words, n = e.sigBytes, r = [], o = 0; o < n; o++) {var i = t[o >>> 2] >>> 24 - o % 4 * 8 & 255;r.push(String.fromCharCode(i))}return r.join("")},parse: function(e) {for (var t = e.length, n = [], r = 0; r < t; r++)n[r >>> 2] |= (255 & e.charCodeAt(r)) << 24 - r % 4 * 8;return new a.init(n,t)}}, l = u.Utf8 = {stringify: function(e) {try {return decodeURIComponent(escape(s.stringify(e)))} catch (e) {throw new Error("Malformed UTF-8 data")}},parse: function(e) {return s.parse(unescape(encodeURIComponent(e)))}}, f = o.BufferedBlockAlgorithm = i.extend({reset: function() {this._data = new a.init,this._nDataBytes = 0},_append: function(e) {"string" == typeof e && (e = l.parse(e)),this._data.concat(e),this._nDataBytes += e.sigBytes},_process: function(t) {var n = this._data, r = n.words, o = n.sigBytes, i = this.blockSize, u = o / (4 * i), c = (u = t ? e.ceil(u) : e.max((0 | u) - this._minBufferSize, 0)) * i, s = e.min(4 * c, o);if (c) {for (var l = 0; l < c; l += i)this._doProcessBlock(r, l);var f = r.splice(0, c);n.sigBytes -= s}return new a.init(f,s)},clone: function() {var e = i.clone.call(this);return e._data = this._data.clone(),e},_minBufferSize: 0});o.Hasher = f.extend({cfg: i.extend(),init: function(e) {this.cfg = this.cfg.extend(e),this.reset()},reset: function() {f.reset.call(this),this._doReset()},update: function(e) {return this._append(e),this._process(),this},finalize: function(e) {return e && this._append(e),this._doFinalize()},blockSize: 16,_createHelper: function(e) {return function(t, n) {return new e.init(n).finalize(t)}},_createHmacHelper: function(e) {return function(t, n) {return new d.HMAC.init(e,n).finalize(t)}}});var d = r.algo = {};return r}(Math)
}
)), P = (A((function(e, t) {var n;e.exports = (n = k,function(e) {var t = n, r = t.lib, o = r.WordArray, i = r.Hasher, a = t.algo, u = [];!function() {for (var t = 0; t < 64; t++)u[t] = 4294967296 * e.abs(e.sin(t + 1)) | 0}();var c = a.MD5 = i.extend({_doReset: function() {this._hash = new o.init([1732584193, 4023233417, 2562383102, 271733878])},_doProcessBlock: function(e, t) {for (var n = 0; n < 16; n++) {var r = t + n, o = e[r];e[r] = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8)}var i = this._hash.words, a = e[t + 0], c = e[t + 1], p = e[t + 2], h = e[t + 3], g = e[t + 4], v = e[t + 5], y = e[t + 6], m = e[t + 7], b = e[t + 8], w = e[t + 9], _ = e[t + 10], x = e[t + 11], S = e[t + 12], O = e[t + 13], A = e[t + 14], k = e[t + 15], P = i[0], T = i[1], j = i[2], E = i[3];P = s(P, T, j, E, a, 7, u[0]),E = s(E, P, T, j, c, 12, u[1]),j = s(j, E, P, T, p, 17, u[2]),T = s(T, j, E, P, h, 22, u[3]),P = s(P, T, j, E, g, 7, u[4]),E = s(E, P, T, j, v, 12, u[5]),j = s(j, E, P, T, y, 17, u[6]),T = s(T, j, E, P, m, 22, u[7]),P = s(P, T, j, E, b, 7, u[8]),E = s(E, P, T, j, w, 12, u[9]),j = s(j, E, P, T, _, 17, u[10]),T = s(T, j, E, P, x, 22, u[11]),P = s(P, T, j, E, S, 7, u[12]),E = s(E, P, T, j, O, 12, u[13]),j = s(j, E, P, T, A, 17, u[14]),P = l(P, T = s(T, j, E, P, k, 22, u[15]), j, E, c, 5, u[16]),E = l(E, P, T, j, y, 9, u[17]),j = l(j, E, P, T, x, 14, u[18]),T = l(T, j, E, P, a, 20, u[19]),P = l(P, T, j, E, v, 5, u[20]),E = l(E, P, T, j, _, 9, u[21]),j = l(j, E, P, T, k, 14, u[22]),T = l(T, j, E, P, g, 20, u[23]),P = l(P, T, j, E, w, 5, u[24]),E = l(E, P, T, j, A, 9, u[25]),j = l(j, E, P, T, h, 14, u[26]),T = l(T, j, E, P, b, 20, u[27]),P = l(P, T, j, E, O, 5, u[28]),E = l(E, P, T, j, p, 9, u[29]),j = l(j, E, P, T, m, 14, u[30]),P = f(P, T = l(T, j, E, P, S, 20, u[31]), j, E, v, 4, u[32]),E = f(E, P, T, j, b, 11, u[33]),j = f(j, E, P, T, x, 16, u[34]),T = f(T, j, E, P, A, 23, u[35]),P = f(P, T, j, E, c, 4, u[36]),E = f(E, P, T, j, g, 11, u[37]),j = f(j, E, P, T, m, 16, u[38]),T = f(T, j, E, P, _, 23, u[39]),P = f(P, T, j, E, O, 4, u[40]),E = f(E, P, T, j, a, 11, u[41]),j = f(j, E, P, T, h, 16, u[42]),T = f(T, j, E, P, y, 23, u[43]),P = f(P, T, j, E, w, 4, u[44]),E = f(E, P, T, j, S, 11, u[45]),j = f(j, E, P, T, k, 16, u[46]),P = d(P, T = f(T, j, E, P, p, 23, u[47]), j, E, a, 6, u[48]),E = d(E, P, T, j, m, 10, u[49]),j = d(j, E, P, T, A, 15, u[50]),T = d(T, j, E, P, v, 21, u[51]),P = d(P, T, j, E, S, 6, u[52]),E = d(E, P, T, j, h, 10, u[53]),j = d(j, E, P, T, _, 15, u[54]),T = d(T, j, E, P, c, 21, u[55]),P = d(P, T, j, E, b, 6, u[56]),E = d(E, P, T, j, k, 10, u[57]),j = d(j, E, P, T, y, 15, u[58]),T = d(T, j, E, P, O, 21, u[59]),P = d(P, T, j, E, g, 6, u[60]),E = d(E, P, T, j, x, 10, u[61]),j = d(j, E, P, T, p, 15, u[62]),T = d(T, j, E, P, w, 21, u[63]),i[0] = i[0] + P | 0,i[1] = i[1] + T | 0,i[2] = i[2] + j | 0,i[3] = i[3] + E | 0},_doFinalize: function() {var t = this._data, n = t.words, r = 8 * this._nDataBytes, o = 8 * t.sigBytes;n[o >>> 5] |= 128 << 24 - o % 32;var i = e.floor(r / 4294967296), a = r;n[15 + (o + 64 >>> 9 << 4)] = 16711935 & (i << 8 | i >>> 24) | 4278255360 & (i << 24 | i >>> 8),n[14 + (o + 64 >>> 9 << 4)] = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8),t.sigBytes = 4 * (n.length + 1),this._process();for (var u = this._hash, c = u.words, s = 0; s < 4; s++) {var l = c[s];c[s] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8)}return u},clone: function() {var e = i.clone.call(this);return e._hash = this._hash.clone(),e}});function s(e, t, n, r, o, i, a) {var u = e + (t & n | ~t & r) + o + a;return (u << i | u >>> 32 - i) + t}function l(e, t, n, r, o, i, a) {var u = e + (t & r | n & ~r) + o + a;return (u << i | u >>> 32 - i) + t}function f(e, t, n, r, o, i, a) {var u = e + (t ^ n ^ r) + o + a;return (u << i | u >>> 32 - i) + t}function d(e, t, n, r, o, i, a) {var u = e + (n ^ (t | ~r)) + o + a;return (u << i | u >>> 32 - i) + t}t.MD5 = i._createHelper(c),t.HmacMD5 = i._createHmacHelper(c)}(Math),n.MD5)
}
)),
A((function(e, t) {var n;e.exports = (n = k,void function() {var e = n, t = e.lib.Base, r = e.enc.Utf8;e.algo.HMAC = t.extend({init: function(e, t) {e = this._hasher = new e.init,"string" == typeof t && (t = r.parse(t));var n = e.blockSize, o = 4 * n;t.sigBytes > o && (t = e.finalize(t)),t.clamp();for (var i = this._oKey = t.clone(), a = this._iKey = t.clone(), u = i.words, c = a.words, s = 0; s < n; s++)u[s] ^= 1549556828,c[s] ^= 909522486;i.sigBytes = a.sigBytes = o,this.reset()},reset: function() {var e = this._hasher;e.reset(),e.update(this._iKey)},update: function(e) {return this._hasher.update(e),this},finalize: function(e) {var t = this._hasher, n = t.finalize(e);return t.reset(),t.finalize(this._oKey.clone().concat(n))}})}())
}
)),
A((function(e, t) {e.exports = k.HmacMD5
}
通过对上面的JS代码进行静态分析可发现最终使用的加密为HmacMD5,结合有密钥参与加密,可以直接Python进行算法还原测试验证即可,算法实现如下所示:
def sign(e, t):sorted_keys = sorted(e.keys())n = ""for key in sorted_keys:if e[key]:n += f"&{key}={e[key]}"n = n[1:]signature = hmac.new(t.encode('utf-8'), n.encode('utf-8'), hashlib.md5).hexdigest()return signature
HMAC-MD5是基于MD5哈希算法的消息认证码,HMAC是一种利用密钥的哈希算法,用于生成一个“签名”,并且常用于消息的完整性验证和认证(如API请求签名)
最终简单的编写一个搜索代码查看一下是否可以正常获取到相关的数据,如下所示:
案列比较简单,适合正在或想要学习逆向新手小伙伴练练手
相关文章:

某小程序sign签名参数逆向分析
文章目录 1. 写在前面2. 接口分析3. 分析还原 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…...

智能风控/数据分析 聚合 分组 连接
data。head()查看前几行 data.head() 是一个在Python的Pandas库中常用的方法,用于查看DataFrame对象的前几行数据。默认情况下,head() 方法会返回DataFrame的前5行数据,但是你也可以通过传递一个整数参数来指定返回的…...
Unity3D PBR光照计算公式推导详解
前言 在Unity3D中,PBR(Physically Based Rendering,基于物理的渲染)光照模型是一种高级光照模型,它模拟了真实世界中光的传播和反射过程,从而提供了更加逼真的渲染效果。PBR光照模型的计算公式涉及多个物理…...
行为树详解(6)——黑板模式
【动作节点数据共享】 行为树中需要的参数可以来自游戏中的各个模块,如果仅需从多个模块获取少量参数,那么可以直接在代码中调用其他模块的单例继而层层调用获取数据。 如果获取的参数量很大,从架构上看,我们需要通过加一个中间…...
Vue.js与其他框架有哪些兼容性?
Vue.js的兼容性主要体现在几个方面,包括浏览器支持、运行环境适应性、与其他库和框架的集成能力等。以下是更详细的解释: 浏览器兼容性 现代浏览器:Vue.js广泛支持所有主流的现代浏览器,如Google Chrome, Firefox, Safari, Edge…...
Java 8 Stream 介绍
Java 8 Stream 介绍 1. 什么是Stream? Stream(流)是Java 8引入的全新概念,它是一个支持串行和并行聚合操作的元素序列。Stream API提供了一种声明式的方式来处理数据集合,可以让我们以一种类似SQL查询的方式处理数据…...
Java NIO、AIO分析
好的,下面将对Java中的**NIO(Non-blocking IO)和AIO(Asynchronous IO)**进行更深入的分析,重点探讨它们的特点和具体的应用场景。 一、Java NIO(Non-blocking IO)深入分析 1. 主要…...
pip下载包出现SSLError
报错: ERROR: Could not install packages due to an OSError: HTTPSConnectionPool(host‘files.pythonhosted.org’, port443): Max retries exceeded with url: /packages/8a/c2/ae7227e4b089c6a8210920db9d5ac59186b0a84eb1e6d96b9218916cdaf1/taming_transform…...
零成本的互联网创业创意有哪些?
在互联网时代,创业的门槛大大降低,即使没有大量的资金投入,也有许多机会可以实现创业梦想。以下将为您介绍一些零成本的互联网创业创意,帮助您在互联网的海洋中找到属于自己的宝藏。 一、内容创作与自媒体 (一&#…...
linux ubantu重启桌面
在 Ubuntu 系统中,重启桌面环境通常有几种方法,具体取决于你所使用的桌面环境(如 GNOME、KDE 等)。下面是几种常用的重启桌面的方法: 重启 GNOME 桌面环境 如果你使用的是 GNOME 桌面环境(Ubuntu 默认桌面…...

DeepSeek重新定义“Open“AI
“面对颠覆性技术,闭源所创造的护城河是暂时的。即使是OpenAI的闭源方法也无法阻止他人赶超。” ——梁文锋,DeepSeek CEO DeepSeek V3 是一个拥有6710亿参数的开源AI模型,正在提升AI效率的新标准。它在相对有限的预算下进行训练,…...
iOS - 自旋锁
在 Objective-C 运行时中大量使用自旋锁,主要有以下几个原因: 1. 性能考虑 上下文切换成本 // 自旋锁实现 static ALWAYS_INLINE void OSSpinLockLock(volatile OSSpinLock *lock) {do {while (lock->value ! 0) {__asm__ volatile ("pause&q…...
web应用网站如何启用http2请求
要启用 HTTP/2 协议,您需要确保您的 Web 服务器软件支持 HTTP/2,并进行相应的配置。以下是一些常见的 Web 服务器软件及其启用 HTTP/2 的方法: 1. Nginx 对于 Nginx,您需要确保使用的是 1.9.5 或更高版本,因为这些版本…...

python进阶06:MySQL
课后大总结 Day1 一、数据库命令总结 1.连接数据库 连接数据库进入mysql安装目录打开bin文件夹,输入cmd(此命令后无分号)mysql.exe -u root -ppassword命令后输入密码:root 设置密码set passwordpassword("root123"); 查看所有数据库show databases; …...
mac 使用zip2john破解zip压缩包密码
一、下载: git clone https://github.com/magnumripper/JohnTheRipper.git cd JohnTheRipper/src ./configure sudo make -s clean && sudo make -sj4 cd ../run二、使用: zip2john提取提取 ZIP 文件的哈希: ./zip2john protecte…...

若依中Feign调用的具体使用(若依微服务版自身已集成openfeign依赖,并在此基础上定义了自己的注解)
若依中Feign调用具体使用 注意:以下所有步骤实现的前提是需要在启动类上加入注解 EnableRyFeignClients 主要是为开启feign接口扫描 1.创建服务提供者(provider) 导入依赖(我在分析依赖时发现若依本身已经引入openfeign依赖,并在此基础上自定义了自己的EnableRyF…...
【算法题系列】LeetCode 5.最长回文子串|JavaScript 5种思路实现
题目描述 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2: 输入: "cbbd" 输出: &q…...
基于ROS先验地图的机器人自主定位与导航SLAM
2021年学习,当时参加科大讯飞的智能车大赛, 【语音交互启动-teb算法路径规划A*算法自动避障路径最短优化yolo5目标检测视觉结果判断分类终点指定点位自动泊车语音播报。】 【讯飞学院】http://www.iflyros.com/home/ 一、全局路径规划中的地图 栅格地图&…...
nginx 1.6.3配置虚拟主机与rewrite-location匹配规则
1、 Nginx 虚拟主机配置(配置文件末尾以分号[;]结尾) (1) 准备测试目录站点 [rootWEB conf]# cd /application/nginx/conf/ [rootWEB conf]# mkdir extra (创建虚拟主机存放目录࿰…...

1130-host ... is not allowed to connect to this MySql serve
局域网内另外一台电脑使用navicat连接Mysql出现上述问题:不允许连接 解决方案: 1、输入命令:进入mysql mysql -u root -p 2、输入命令:展示所有数据库 show databases; 3、输入命令进入mysql数据库: use mysql; 4、…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...