webpack实战:最新QQ音乐sign参数加密分析

news2024/11/17 23:55:04

文章目录

  • 1. 写在前面
  • 2. 接口抓包分析
  • 3. 扣webpack代码
  • 4. 补浏览器环境
  • 5. 验证加密结果

1. 写在前面

  现在!很多的网站使用Webpack加载和处理JS文件。所以对于使用了Webpack加载的JS代码,一旦它们被打包并在浏览器中执行,通常是难以直接阅读和理解的,因为Webpack会将其压缩、混淆和优化

本文将分享最新的QQ音乐sign参数加密分析。QQ音乐的sign加密目前主要是由webpack生成并通过加载器导出!感兴趣的也可以看看我之前发布的一些关于webpack分析文章


分析目标

aHR0cHM6Ly95LnFxLmNvbS9uL3J5cXEvc2VhcmNoP3c9JUU3JTlDJTlGJUU3JTlBJTg0JUU3JTg4JUIxJUU0JUJEJUEw


在这里插入图片描述

2. 接口抓包分析

  可以看到如下请求提交了两个参数,一个时间戳一个就是加密的sign。先全局搜索一下sign,如下出现两个结果:

在这里插入图片描述
在这里插入图片描述

3. 扣webpack代码

  点击JS文件进去,找到sign的位置(可以继续在JS内搜索分析)打上断点。断点之后我们重新提交搜索请求,根据断点调试来到下图,可以看到i出来后就是sign。它是经过o函数就变为了加密内容。o()就是加密方法。而这里o又等于n(350).default

在这里插入图片描述

o = n(350).default是webpack的调用形式,n是加载器,鼠标移到n点击跳转将webpack的代码先整个扣下来:

在这里插入图片描述

上面我们找到了加载器的webpack代码,还有一个就是加载器的具体方法。这个我们也需要扣出来放到加载器中导入:

在这里插入图片描述

加载器的webpack代码一共是300多行,而需要加载的具体方法vendor.chunk的文件代码很庞大!至于有多大家可以看下图(2W+行代码),这里我把它扣下来存为qq.js,等待后续加载器的导入使用:

在这里插入图片描述

4. 补浏览器环境

  加载器跟加载方法的所有JS代码我们拿到本地编辑器。可以看到这个JS代码直接扣下来是不能用起来的,分析代码可以看到(window、location、navigator)这些都是缺失的!测试的时候自己发现缺什么就补~

在这里插入图片描述
在这里插入图片描述

上图按照浏览器的环境把location、navigator补上,另外一定自己要看代码分析,f它是加载器,这里也是用全局变量接收的,最终加载器扣下来完善后的最终代码如下所示(require(‘./qq’)这一行代码就是加载方法的所有代码):

// 补环境
window = global;
location = { 
    "ancestorOrigins": {}, 
    "href": "https://y.qq.com/n/ryqq/search?w=%E7%9C%9F%E7%9A%84%E7%88%B1%E4%BD%A0&t=song&remoteplace=txt.yqq.top",
    "origin": "https://y.qq.com",
    "protocol": "https:",
    "host": "y.qq.com",
    "hostname": "y.qq.com",
    "port": "", 
    "pathname": "/n/ryqq/search",
    "search": "?w=%E7%9C%9F%E7%9A%84%E7%88%B1%E4%BD%A0&t=song&remoteplace=txt.yqq.top",
    "hash": ""
}
navigator = { 
    appCodeName: "Mozilla",
    appName: "Netscape",
    appVersion: "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",}
var loader;
require('./qq') // 加载方法代码,需要扣出来
!function(e) {
    function t(t) {
        for (var a, n, f = t[0], d = t[1], i = t[2], l = 0, u = []; l < f.length; l++)
            n = f[l],
            Object.prototype.hasOwnProperty.call(o, n) && o[n] && u.push(o[n][0]),
            o[n] = 0;
        for (a in d)
            Object.prototype.hasOwnProperty.call(d, a) && (e[a] = d[a]);
        for (b && b(t); u.length; )
            u.shift()();
        return c.push.apply(c, i || []),
        r()
    }
    function r() {
        for (var e, t = 0; t < c.length; t++) {
            for (var r = c[t], a = !0, n = 1; n < r.length; n++) {
                var d = r[n];
                0 !== o[d] && (a = !1)
            }
            a && (c.splice(t--, 1),
            e = f(f.s = r[0]))
        }
        return e
    }
    var a = {}
      , n = {
        20: 0
    }
      , o = {
        20: 0
    }
      , c = [];
    function f(t) {
        if (a[t])
            return a[t].exports;
        var r = a[t] = {
            i: t,
            l: !1,
            exports: {}
        };
        return e[t].call(r.exports, r, r.exports, f),
        r.l = !0,
        r.exports
    }
    f.e = function(e) {
        var t = [];
        n[e] ? t.push(n[e]) : 0 !== n[e] && {
            1: 1,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1
        }[e] && t.push(n[e] = new Promise((function(t, r) {
            for (var a = "css/" + ({
                1: "common",
                3: "album",
                4: "albumDetail",
                5: "album_mall",
                6: "category",
                7: "cmtpage",
                8: "index",
                9: "msg_center",
                10: "mv",
                11: "mvList",
                12: "mv_toplist",
                13: "notfound",
                14: "player",
                15: "player_radio",
                16: "playlist",
                17: "playlist_edit",
                18: "profile",
                19: "radio",
                21: "search",
                22: "singer",
                23: "singer_list",
                24: "songDetail",
                25: "toplist"
            }[e] || e) + "." + {
                1: "2e3d715e72682303d35b",
                3: "5cf0d69eaf29bcab23d2",
                4: "798353db5b0eb05d5358",
                5: "df4c243f917604263e58",
                6: "20d532d798099a44bc88",
                7: "e3bedf2b5810f8db0684",
                8: "ea0adb959fef9011fc25",
                9: "020422608fe8bfb1719a",
                10: "8bdb1df6c5436b790baa",
                11: "47ce9300786df1b70584",
                12: "4aee33230ba2d6b81dce",
                13: "e6f63b0cf57dd029fbd6",
                14: "1d2dbefbea113438324a",
                15: "d893492de07ce97d8048",
                16: "9484fde660fe93d9f9f0",
                17: "67fb85e7f96455763c83",
                18: "5e8c651e74b13244f7cf",
                19: "3befd83c10b19893ec66",
                21: "b2d11f89ea6a512a2302",
                22: "c7a38353c5f4ebb47491",
                23: "df0961952a2d3f022894",
                24: "4c080567e394fd45608b",
                25: "8edb142553f97482e00f"
            }[e] + ".chunk.css?max_age=2592000", o = f.p + a, c = document.getElementsByTagName("link"), d = 0; d < c.length; d++) {
                var i = (b = c[d]).getAttribute("data-href") || b.getAttribute("href");
                if ("stylesheet" === b.rel && (i === a || i === o))
                    return t()
            }
            var l = document.getElementsByTagName("style");
            for (d = 0; d < l.length; d++) {
                var b;
                if ((i = (b = l[d]).getAttribute("data-href")) === a || i === o)
                    return t()
            }
            var u = document.createElement("link");
            u.rel = "stylesheet",
            u.type = "text/css",
            u.onload = t,
            u.onerror = function(t) {
                var a = t && t.target && t.target.src || o
                  , c = new Error("Loading CSS chunk " + e + " failed.\n(" + a + ")");
                c.code = "CSS_CHUNK_LOAD_FAILED",
                c.request = a,
                delete n[e],
                u.parentNode.removeChild(u),
                r(c)
            }
            ,
            u.href = o,
            0 !== u.href.indexOf(window.location.origin + "/") && (u.crossOrigin = "anonymous"),
            document.getElementsByTagName("head")[0].appendChild(u)
        }
        )).then((function() {
            n[e] = 0
        }
        )));
        var r = o[e];
        if (0 !== r)
            if (r)
                t.push(r[2]);
            else {
                var a = new Promise((function(t, a) {
                    r = o[e] = [t, a]
                }
                ));
                t.push(r[2] = a);
                var c, d = document.createElement("script");
                d.charset = "utf-8",
                d.timeout = 120,
                f.nc && d.setAttribute("nonce", f.nc),
                d.src = function(e) {
                    return f.p + "js/" + ({
                        1: "common",
                        3: "album",
                        4: "albumDetail",
                        5: "album_mall",
                        6: "category",
                        7: "cmtpage",
                        8: "index",
                        9: "msg_center",
                        10: "mv",
                        11: "mvList",
                        12: "mv_toplist",
                        13: "notfound",
                        14: "player",
                        15: "player_radio",
                        16: "playlist",
                        17: "playlist_edit",
                        18: "profile",
                        19: "radio",
                        21: "search",
                        22: "singer",
                        23: "singer_list",
                        24: "songDetail",
                        25: "toplist"
                    }[e] || e) + ".chunk." + {
                        1: "aabe67026a2f3f407781",
                        3: "57adeab72a3ec5a6940c",
                        4: "fb9a0df49aac1081fd8b",
                        5: "ce88bd122dac655490ca",
                        6: "3c9e9ce78ed1a42f485f",
                        7: "ca787dcf6db83f6a4d11",
                        8: "306c7ad24389b8338e1f",
                        9: "b5cd5a77da26782764c2",
                        10: "b9b35726ef5f56f87151",
                        11: "c925c75c1a05b9bd0958",
                        12: "b2bfa82b42b9bec98cca",
                        13: "e8b9a6dad95b623cab82",
                        14: "16f4f61d208558a7c17c",
                        15: "7264ef7ff4b6052f4c01",
                        16: "039db3b85d472916677b",
                        17: "72dfb28846b85bcce963",
                        18: "7f8ac1ee0d0077c0d960",
                        19: "89e9600c87d40494d2a0",
                        21: "157aa8a8c67606f0d243",
                        22: "07c7b21c4be040114330",
                        23: "d0f42e091f31e2cd3a85",
                        24: "4e38573b87120e0a3b0a",
                        25: "08f75a75f2455ab4c49f"
                    }[e] + ".js?max_age=2592000"
                }(e),
                0 !== d.src.indexOf(window.location.origin + "/") && (d.crossOrigin = "anonymous");
                var i = new Error;
                c = function(t) {
                    d.onerror = d.onload = null,
                    clearTimeout(l);
                    var r = o[e];
                    if (0 !== r) {
                        if (r) {
                            var a = t && ("load" === t.type ? "missing" : t.type)
                              , n = t && t.target && t.target.src;
                            i.message = "Loading chunk " + e + " failed.\n(" + a + ": " + n + ")",
                            i.name = "ChunkLoadError",
                            i.type = a,
                            i.request = n,
                            r[1](i)
                        }
                        o[e] = void 0
                    }
                }
                ;
                var l = setTimeout((function() {
                    c({
                        type: "timeout",
                        target: d
                    })
                }
                ), 12e4);
                d.onerror = d.onload = c,
                document.head.appendChild(d)
            }
        return Promise.all(t)
    }
    ,
    f.m = e,
    f.c = a,
    f.d = function(e, t, r) {
        f.o(e, t) || Object.defineProperty(e, t, {
            enumerable: !0,
            get: r
        })
    }
    ,
    f.r = function(e) {
        "undefined" !== typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
            value: "Module"
        }),
        Object.defineProperty(e, "__esModule", {
            value: !0
        })
    }
    ,
    f.t = function(e, t) {
        if (1 & t && (e = f(e)),
        8 & t)
            return e;
        if (4 & t && "object" === typeof e && e && e.__esModule)
            return e;
        var r = Object.create(null);
        if (f.r(r),
        Object.defineProperty(r, "default", {
            enumerable: !0,
            value: e
        }),
        2 & t && "string" != typeof e)
            for (var a in e)
                f.d(r, a, function(t) {
                    return e[t]
                }
                .bind(null, a));
        return r
    }
    ,
    f.n = function(e) {
        var t = e && e.__esModule ? function() {
            return e.default
        }
        : function() {
            return e
        }
        ;
        return f.d(t, "a", t),
        t
    }
    ,
    f.o = function(e, t) {
        return Object.prototype.hasOwnProperty.call(e, t)
    }
    ,
    f.p = "/ryqq/",
    f.oe = function(e) {
        throw e
    }
    ;
    var d = window.webpackJsonp = window.webpackJsonp || []
      , i = d.push.bind(d);
    d.push = t,
    d = d.slice();
    for (var l = 0; l < d.length; l++)
        t(d[l]);
    var b = i;
    r()
    loader = f;
}([]);

// 加密调用函数
function get_sign(data) {
    let o = loader(350).default;
    return o(data)

5. 验证加密结果

  将webpack的加载器JS代码跟加载方法JS代码全部扣下来后,基本上整个加密的流程就出来了,现在我们编写一下脚本来验证一下效果,脚本内容如下:

# -*- coding: utf-8 -*-

# 测试请换自己的cookie
cookies = {
    'sd_userid': '2391663752714217',
    'pgv_pvid': '5766421817',
    'pac_uid': '0_9a2e8dd1c0852',
    'RK': 'jiHhTPl9aT',
    'ptcz': '1e1eb706edac3e0c76ab95a69f550b99fcdec80366b7f8c358d56f0fc0979946',
    'fqm_pvqid': '40c52bcd-87c7-4c72-a26c-27e8707c872c',
    'fqm_sessionid': '8dd996ec-c839-42c8-9ca3-d6851c420d58',
    'pgv_info': 'ssid=s1216838840',
    'ts_uid': '1699674176',
    'qm_keyst': 'W_X_5NTcvfg7hswI_XeeT1UL6iqZLxWEjnqblAPOLhMHc19EhzmgRaHfQcyATA3BOkNjn7mBtZxDrgTg',
    'wxuin': '1152921504767067454',
    'psrf_qqunionid': '',
    'psrf_qqrefresh_token': '',
    'wxunionid': 'oqFLxsgm67UNDPWQJrsB5zAagvAs',
    'psrf_qqopenid': '',
    'qqmusic_key': 'W_X_5NTcvfg7hswI_XeeT1UL6iqZLxWEjnqblAPOLhMHc19EhzmgRaHfQcyATA3BOkNjn7mBtZxDrgTg',
    'wxopenid': 'opCFJwysEgSAIr0m0m1bcSARkUAg',
    'tmeLoginType': '1',
    'psrf_qqaccess_token': '',
    'wxrefresh_token': '72_LC_VaHu3AQw7rraX_0r5Kw16fCtvHWtO5Qpli1bdCJBtkNnDeAoX6fDYGBDEpalnPYAAs8U9HTsfrleIMkK3ES25lJ1KNYhYIsRpSMK_Fj8',
    'euin': 'oK6kowEAoK4z7eSs7ins7ivk7n**',
    'login_type': '2',
    'ts_last': 'y.qq.com/n/ryqq/search'
}

headers = {
    'authority': 'u.y.qq.com',
    'accept': 'application/json',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'no-cache',
    'content-type': 'application/x-www-form-urlencoded',
    'origin': 'https://y.qq.com',
    'pragma': 'no-cache',
    'referer': 'https://y.qq.com/',
    'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"macOS"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-site',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
}

# 直接浏览器拷出来
data = '{"comm":{"cv":4747474,"ct":24,"format":"json","inCharset":"utf-8","outCharset":"utf-8","notice":0,"platform":"yqq.json","needNewCode":1,"uin":"1152921504767067454","g_tk_new_20200303":451075320,"g_tk":451075320},"req_1":{"method":"DoSearchForQQMusicDesktop","module":"music.search.SearchCgiService","param":{"remoteplace":"txt.yqq.top","searchid":"65805105264064724","search_type":0,"query":"海阔天空","page_num":1,"num_per_page":10}}}'

# 获取sign加密参数
with open("./加载器.js") as f: # 上面加载器的JS文件
    js_code = f.read()

time_str = round(time.time() * 1000)
sign = execjs.compile(js_code).call("get_sign", data)
print(YELLOW % 'sign: {}'.format(sign))
params = {
    '_': time_str,
    'sign': sign,
}

response = requests.post('https://u.y.qq.com/cgi-bin/musics.fcg', params=params, cookies=cookies, headers=headers,
                         data=data.encode()).json()
print(response)

验证效果如下所示:

在这里插入图片描述

最后说一句,GPT出来后确实为我们开发者省去了很多曾经繁琐的工作,像上面的Python验证脚本就是让GPT帮我写的,真好~

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

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

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

相关文章

选择正确的开发框架:构建高效、可维护的应用程序

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 在现代软件开发中…

python如何打包成应用

前几天有学生问&#xff0c;开发好的python代码如何打包给对方使用&#xff1f;对方没有python的安装执行环境。 python是一个强大的编程开发工具&#xff0c;它不仅仅是做一些命令行或脚本运行工具&#xff0c;还可以开发桌面、web等应用。 本文就介绍使用pyinstall如何把py…

GIS前端编程-地理事件动态模拟

GIS前端编程-地理事件动态模拟 动画特效功能图形闪烁要素轨迹移动 动画特效功能 目前&#xff0c;GIS应用除了涉及地理位置信息&#xff0c;还要结合时间维度&#xff0c;这样才能更加真实地模拟现实世界的事物。因此在实际项目应用中&#xff0c;静态的&#xff08;位置固定不…

Redis混合模式持久化原理

前言 前面文章中我们也介绍过Redis的持久化方式有两种&#xff1a;rdb持久化和aof持久化&#xff0c;具体详情可查看之前文章redis持久化。rdb持久化还是aof持久化它们都有各自的缺点。 rdb和aof缺点 rdb持久化&#xff1a;由于是定期对内存数据快照进行持久化&#xff0c;因此…

【智能家居-大模型】行业专题报告:ChatGPT等大模型催化智能家居行业发展

&#xff08;报告出品方/作者&#xff1a;华安证券&#xff0c;马远方&#xff09; 1 智能家居&#xff1a;ChatGPT 等大模型为行业发展带来新机遇 1.1 现状&#xff1a;智能家居产品的用户体验&#xff08;交互能力、智能化水 平&#xff09;及安全性待提升 智能家居&#…

编程获取图像中的圆半径

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 即将推出EmguCV的教程&#xff0c;请大家还稍作等待。 之前网友咨询如何获得图像中圆形的半径&#xff0c;其中有两个十字作为标定…

如何实现一个简单的深度优先搜索(DFS)算法?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现深度优先搜索⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前…

Qt Quick 之 QML 与 C++ 混合编程详解

Qt Quick 之 QML 与 C 混合编程详解 一、Qt Quick 之 QML 与 C 混合编程详解在 QML 中使用 C 类和对象实现可以导出的 C 类Q_INVOKABLE 宏Q_ENUMSQ_PROPERTY注册一个 QML 中可用的类型注册 QML 类型在 QML 中导入 C 注册的类型完整的 colorMaker 实例导出一个 C 对象为 QML 的属…

伴随矩阵与可逆矩阵

目录 伴随矩阵的概念与公式 可逆矩阵的概念与定理 逆矩阵的运算性质 伴随矩阵的概念与公式 伴随矩阵是一个与给定矩阵相关的矩阵&#xff0c;它的元素是给定矩阵的代数余子式。 给定一个nn的方阵A&#xff0c;其元素为aij&#xff0c;则A的伴随矩阵adj(A)是一个nn的方阵&…

EDI 许可证申请对网站有哪些要求?

EDI 许可证申请对网站有哪些要求&#xff1f; 1、电商类平台&#xff1b; 2、二手交易类平台&#xff1b; 3、外卖类平台&#xff1b; 4、票务交易类平台&#xff1b; 5、智能数据处理平台。 ​网站如果是上述类型&#xff0c;那就要办理EDI许可证&#xff0c;但EDI许可证…

北航投资携核心医疗获2023年度十佳投资案例

近日&#xff0c;全球PE论坛联合财新数据发布了2022-2023年度中国PE/VC行业评选结果&#xff0c;北航投资携核心医疗荣获2022-2023年度中国PE/VC十佳投资案例大奖。 经过7年的发展&#xff0c;北航投资的各项业务正密集地进入收获期&#xff0c;业务增长飞轮持续加速&#xff0…

vue拖拽插件 - Sortable

官网地址&#xff1a;Sortable.js中文网 使用方法&#xff1a; 1. npm安装 npm install sortablejs --save 2. 在组件中引入插件 import Sortable from "sortablejs"; 3. 给要拖动的table加上id用来获取dom&#xff0c;记得加row-key&#xff0c;不然会有显示问题 …

苹果“FindMy”APP

“FindMy”是一项 Apple 服务&#xff0c;可以定位设备。在 iOS 13 之前&#xff0c;Apple将该服务拆分为单独的应用程序&#xff1a;“查找我的 iPhone”&#xff08;或 iPad 或 Mac&#xff09;和“查找我的朋友”。该服务适用于iPhone、iPad、Mac、Apple Watch、AirPods、Ai…

麒麟v10安装Redis(ARM架构)

下载Redis安装包 华为开源镜像站_软件开发服务_华为云 上面的选择一个下载 或者用命令下载 wget https://repo.huaweicloud.com/kunpeng/yum/el/7/aarch64/Packages/bigdata/redis-5.0.5-1.el7.aarch64.rpm 检查是否已经安装Redis rpm -qa | grep redis将包卸载掉 rpm -e -…

AGV小车、机械臂协同作业实战03-opentcs5.9 运行体验

openTCS的控制核心是kernel&#xff0c;其内部有三种算法&#xff0c;分别为Dispater、Router、Scheduler。 本文主要介绍如何利用openTCS的plant overview平台进行基本的操作&#xff0c;主要内容来源于该软件内自带的opentcs-users-guide手册。 启动客户端 openTCS-Kernel…

Python中RESTful API的常见问题

RESTful API&#xff08;Representational State Transfer&#xff09;是一种设计风格&#xff0c;用于构建可扩展的和易于维护的Web服务。Python作为一门流行的编程语言&#xff0c;提供了丰富的库和工具来构建和实现RESTful API。然而&#xff0c;在实践过程中&#xff0c;我…

Matlab 分析 rosbag

在机器人的开发中&#xff0c;通常会使用rosbag工具来分析机器人的一些性能指标是否符合要求&#xff0c;在Windows平台&#xff0c;使用matlab分析rosbag是一个不错的选择&#xff0c;这里给出简单的使用示例&#xff1a; 示例&#xff1a;读取rosbag中机器人的位置信息&…

模拟实现C语言--strcmp函数

模拟实现C语言–strcmp函数 文章目录 模拟实现C语言--strcmp函数一、strcmp函数是什么&#xff1f;二、使用示例三、模拟实现3.1 模拟实现方式一3.2 模拟实现方式二 一、strcmp函数是什么&#xff1f; 字符串比较函数&#xff1a;比较的是对应位置的ASCII值 int strcmp ( con…

saml协议中生成jks

JKS简介 JKS是Java Key Store的缩写&#xff0c;是 Java 语言开发的一种密钥库格式&#xff0c;它包含了证书和私钥&#xff0c;可以用来加密、认证和签署数字信息。 环境 $ uname -a Linux yanlp 3.10.0-1160.92.1.el7.x86_64 #1 SMP Tue Jun 20 11:48:01 UTC 2023 x86_64 …

基于Qt实现的可视化大屏监控

基于Qt实现的可视化大屏监控 先上图 基于Qt实现的可视化大屏监控 总有人质疑QWidget实现不了炫酷的界面&#xff0c;其实QWidget已经很强大了&#xff0c;虽然很多效果没有现成的框架&#xff0c;所以比不上html5或者安卓这种&#xff0c;但是也能实现很多不错的效果了&#…