

{"id":550,"date":"2026-10-03T03:29:09","date_gmt":"2026-10-02T19:29:09","guid":{"rendered":"https:\/\/6589jk.cn\/?p=550"},"modified":"2026-10-03T03:34:10","modified_gmt":"2026-10-02T19:34:10","slug":"%e5%90%8d%e4%be%a6%e6%8e%a2%e7%9a%84%e7%a0%b4%e6%a1%88%e7%ac%94%e8%ae%b0%ef%bc%9acitruspanel-%e5%bc%80%e5%8f%91%e5%85%ad%e5%a4%a7%e6%8a%80%e6%9c%af%e9%9a%be%e7%82%b9%e5%ae%9e%e5%bd%95","status":"publish","type":"post","link":"https:\/\/6589jk.cn\/index.php\/2026\/10\/03\/%e5%90%8d%e4%be%a6%e6%8e%a2%e7%9a%84%e7%a0%b4%e6%a1%88%e7%ac%94%e8%ae%b0%ef%bc%9acitruspanel-%e5%bc%80%e5%8f%91%e5%85%ad%e5%a4%a7%e6%8a%80%e6%9c%af%e9%9a%be%e7%82%b9%e5%ae%9e%e5%bd%95\/","title":{"rendered":"\u540d\u4fa6\u63a2\u7684\u7834\u6848\u7b14\u8bb0\uff1aCitrusPanel \u5f00\u53d1\u516d\u5927\u6280\u672f\u96be\u70b9\u5b9e\u5f55"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/6589jk.cn\/wp-content\/uploads\/2026\/10\/detective.png\" width=\"180\" alt=\"\u540d\u4fa6\u63a2\" \/><\/p>\n<p>AAO\uff01\u4e0a\u4e00\u7bc7\u804a\u4e86 CitrusPanel \u90fd\u80fd\u5e72\u4ec0\u4e48\uff0c\u8fd9\u4e00\u7bc7\u6765\u4e0a\u5e72\u8d27\u2014\u2014\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u8e29\u8fc7\u7684<strong>\u771f\u5b9e\u6280\u672f\u96be\u70b9<\/strong>\u3002\u6bcf\u4e2a\u90fd\u662f\u5b9e\u6253\u5b9e\u6392\u67e5\u51fa\u6765\u7684\uff0c\u4e0d\u662f\u7f16\u7684\uff08\u540d\u4fa6\u63a2\u529e\u6848\u8bb2\u7a76\u8bc1\u636e\uff09\u3002<\/p>\n<h2>\u96be\u70b9\u4e00\uff1azip \u6253\u5305\u4e0b\u8f7d\u53ea\u6709 46 \u5b57\u8282\uff1f<\/h2>\n<p><strong>\u73b0\u8c61<\/strong>\uff1a\u5206\u4eab\u9875\u6574\u5305\u4e0b\u8f7d zip\uff0c\u6d4f\u89c8\u5668\u62ff\u5230\u7684\u6587\u4ef6\u53ea\u6709 46 \u5b57\u8282\uff0c\u89e3\u538b\u76f4\u63a5\u62a5\u9519\u3002<\/p>\n<p><strong>\u6392\u67e5<\/strong>\uff1a\u7b2c\u4e00\u6b21\u4fee\u4ee5\u4e3a\u662f\u6d41\u88ab\u5305\u88c5\u5bfc\u81f4\u63d0\u524d\u6536\u5c3e\uff0c\u6539\u6210\u76f4\u5199 <code>HttpContext.Response.Body<\/code>\u2014\u2014\u7ed3\u679c\u53d8\u6210 35 \u5b57\u8282\uff0c\u65e5\u5fd7\u91cc\u8eba\u7740\u4e00\u6761 <code>Synchronous operations are disallowed<\/code>\u3002<\/p>\n<p><strong>\u6839\u56e0<\/strong>\uff1a\u4e24\u8fde\u5751\u53e0\u52a0\u3002<code>ZipArchive.Dispose()<\/code> \u6536\u5c3e\u65f6\uff08\u5199 data descriptor \u548c\u4e2d\u592e\u76ee\u5f55\uff09\u8d70\u7684\u662f<strong>\u540c\u6b65 Write<\/strong>\uff0c\u800c Kestrel \u9ed8\u8ba4\u7981\u6b62\u540c\u6b65 IO\u3002<\/p>\n<pre><code>\/\/ \u4fee\u590d\uff1a\u6253\u5305\u54cd\u5e94\u653e\u5f00\u540c\u6b65 IO\uff0c\u4e14\u65b9\u6cd5\u8fd4\u56de\u524d\u5fc5\u987b\u91ca\u653e ZipArchive\nvar bodyControl = context.Features.Get&lt;IHttpBodyControlFeature&gt;();\nif (bodyControl is not null) bodyControl.AllowSynchronousIO = true;\nusing var zip = new ZipArchive(context.Response.Body, ZipArchiveMode.Create, leaveOpen: true);\n<\/code><\/pre>\n<p><strong>\u6559\u8bad<\/strong>\uff1a\u6d41\u5f0f\u538b\u7f29\u5305\u7684\u9a8c\u6536\u6807\u51c6\u662f\u300c\u4e0b\u8f7d\u5b8c\u80fd\u88ab <code>zipfile<\/code> \u89e3\u5f00\u300d\uff0c\u4e0d\u662f\u300cHTTP 200\u300d\u3002<\/p>\n<h2>\u96be\u70b9\u4e8c\uff1a\u672a\u767b\u5f55 API \u8fd4\u56de 400 \u800c\u4e0d\u662f 401<\/h2>\n<p><strong>\u73b0\u8c61<\/strong>\uff1a\u767d\u540d\u5355\u8ba4\u8bc1\u4e2d\u95f4\u4ef6\u660e\u660e\u8fd4\u56de 401\uff0c\u5b9e\u9645\u62ff\u5230\u7684\u5374\u662f 400\uff0c\u8fd8\u5e26\u4e00\u53e5\u300c\u7f3a\u5c11\u9632\u4f2a\u4ee4\u724c\u300d\u3002<\/p>\n<p><strong>\u6839\u56e0<\/strong>\uff1a\u4e2d\u95f4\u4ef6\u8fd4\u56de\u7684 401 <strong>\u6ca1\u6709\u54cd\u5e94\u4f53<\/strong>\uff0c\u88ab <code>StatusCodePagesWithReExecute<\/code> \u6293\u4f4f\uff0c\u628a\u8bf7\u6c42\u91cd\u65b0\u6267\u884c\u5230 <code>\/not-found<\/code>\u2014\u2014POST \u65b9\u6cd5\u88ab\u4fdd\u7559\uff0c\u4e8e\u662f\u649e\u4e0a Antiforgery \u4e2d\u95f4\u4ef6\uff0c\u6539\u5224 400\u3002<\/p>\n<p><strong>\u4fee\u590d<\/strong>\uff1a401 \u5fc5\u987b\u5199 JSON body\uff0c\u53ea\u8981\u54cd\u5e94\u6709\u5185\u5bb9 StatusCodePages \u5c31\u4e0d\u4f1a\u63d2\u624b\uff1a<\/p>\n<pre><code>context.Response.StatusCode = 401;\ncontext.Response.ContentType = \"application\/json; charset=utf-8\";\nawait context.Response.WriteAsync(\"{\\\"error\\\":\\\"unauthorized\\\"}\");\n<\/code><\/pre>\n<p><strong>\u6559\u8bad<\/strong>\uff1a\u81ea\u5b9a\u4e49\u9519\u8bef\u54cd\u5e94\u300c\u7a7a\u7740\u300d\u53cd\u800c\u4f1a\u89e6\u53d1\u6846\u67b6\u7684\u8865\u507f\u673a\u5236\uff0c\u9519\u8bef\u9875\u628a\u9519\u8bef\u6539\u6210\u4e86\u53e6\u4e00\u79cd\u9519\u8bef\u3002<\/p>\n<h2>\u96be\u70b9\u4e09\uff1aPasskey \u62a5 &#8220;This is an invalid domain&#8221;<\/h2>\n<p><strong>\u73b0\u8c61<\/strong>\uff1a\u8bc1\u4e66\u88c5\u597d\u3001\u63a5\u53e3\u5168\u901a\uff0c\u70b9\u6ce8\u518c Passkey \u6d4f\u89c8\u5668\u76f4\u63a5\u629b <code>SecurityError: This is an invalid domain.<\/code><\/p>\n<p><strong>\u6839\u56e0<\/strong>\uff1a\u8fd9\u662f<strong>\u6d4f\u89c8\u5668\u89c4\u8303\u786c\u6027\u89c4\u5b9a<\/strong>\u2014\u2014WebAuthn \u7684 rpId\uff08Relying Party ID\uff09\u5fc5\u987b\u662f\u57df\u540d\uff0cIP \u5730\u5740\u4e00\u7968\u5426\u51b3\u3002\u5b9e\u6d4b\u590d\u73b0\uff1a<\/p>\n<pre><code>navigator.credentials.create({ publicKey: { rp: { id: '192.168.31.250', ... }}})\n\/\/ \u2192 SecurityError: This is an invalid domain.\n<\/code><\/pre>\n<p><strong>\u4fee\u590d<\/strong>\uff1aDNS \u52a0 A \u8bb0\u5f55 \u2192 \u91cd\u65b0\u7b7e\u4e00\u5f20\u542b\u57df\u540d SAN \u7684\u81ea\u7b7e\u8bc1\u4e66 \u2192 Fido2 \u914d\u7f6e RPID \u6362\u6210\u57df\u540d \u2192 \u8bc1\u4e66\u8fdb\u300c\u53d7\u4fe1\u4efb\u7684\u6839\u300d\uff08\u6ce8\u610f\u4e0d\u662f\u300c\u4e2d\u95f4\u8bc1\u4e66\u300d\uff0c\u88c5\u9519\u4f4d\u7f6e\u767d\u642d\uff09\u3002\u5168\u5957\u8d70\u5b8c\uff0cPasskey \u79d2\u6ce8\u518c\u3002<\/p>\n<h2>\u96be\u70b9\u56db\uff1aFido2 4.x \u628a API \u5168\u6539\u4e86<\/h2>\n<p>NuGet \u4e0a <code>Fido2NetLib<\/code> \u53ea\u5269\u53e4\u8463 alpha\uff0c\u6b63\u4e3b\u6539\u540d\u53eb <code>Fido2<\/code> 4.x\uff0cAPI \u5927\u53d8\u6837\uff1a<strong>\u6ca1\u6709 <code>AddFido2<\/code> \u6269\u5c55\u65b9\u6cd5<\/strong>\uff0c\u53c2\u6570\u6a21\u578b\u4e5f\u5168\u91cd\u505a\u3002<\/p>\n<p>\u6478\u6cd5\u5f88\u66b4\u529b\uff1a\u53cd\u5c04\u52a0\u8f7d DLL \u628a\u516c\u5f00\u7c7b\u578b\u548c\u65b9\u6cd5\u7b7e\u540d\u5168\u6253\u51fa\u6765\u5bf9\uff1a<\/p>\n<pre><code>Assembly.LoadFrom(\"Fido2.dll\").GetExportedTypes()\n  .FirstOrDefault(t => t.Name == \"MakeAssertionParams\")\n<\/code><\/pre>\n<p>\u9010\u4e2a\u786e\u8ba4\uff1a\u679a\u4e3e\u5728 <code>Fido2NetLib.Objects<\/code> \u547d\u540d\u7a7a\u95f4\u3001<code>MakeAssertionParams<\/code> \u6ca1\u6709 <code>StoredBackupEligible<\/code> \u5c5e\u6027\u3001\u767b\u5f55\u65f6\u5fc5\u987b\u4f20 <code>AllowedCredentials<\/code> \u5426\u5219\u90e8\u5206\u8ba4\u8bc1\u5668\u627e\u4e0d\u5230\u51ed\u636e\u3002<\/p>\n<h2>\u96be\u70b9\u4e94\uff1a\u7f51\u5361\u901f\u7387\u663e\u793a 4294967 Gbps<\/h2>\n<p><strong>\u73b0\u8c61<\/strong>\uff1a\u65ad\u7f51\u7684\u7f51\u5361\u663e\u793a <code>4294967 Gbps<\/code>\uff0c\u6b63\u5e38\u5de5\u4f5c\u7684 WiFi \u53cd\u800c\u663e\u793a <code>\u2014<\/code>\u3002<\/p>\n<p><strong>\u6839\u56e0<\/strong>\uff1a\u65e0\u8f7d\u6ce2\u65f6 sysfs \u7684 <code>speed<\/code> \u6587\u4ef6\u8fd4\u56de <code>-1<\/code>\uff0c\u7ecf <code>NetworkInterface.Speed<\/code> \u8bfb\u51fa\u6765\u53d8\u6210 uint32 \u6ea2\u51fa\u5783\u573e\u503c\uff1b\u800c WiFi \u6839\u672c\u6ca1\u6709 speed \u6587\u4ef6\uff0c\u4e14 Linux \u4e0a WiFi \u5e38\u88ab .NET \u8bef\u62a5\u6210 Ethernet \u7c7b\u578b\u3002<\/p>\n<p><strong>\u4fee\u590d<\/strong>\uff1a\u4e0d\u78b0 <code>NetworkInterface.Speed<\/code>\uff0c\u76f4\u8bfb <code>\/sys\/class\/net\/&lt;if&gt;\/speed<\/code>\uff08-1 \u5373\u663e\u793a \u2014\uff09\uff0c\u65e0\u7ebf\u7f51\u5361\u7edf\u4e00\u5c1d\u8bd5 <code>iw dev xxx link<\/code> \u89e3\u6790 <code>tx bitrate<\/code>\u3002<\/p>\n<h2>\u96be\u70b9\u516d\uff1aPowerShell + SSH \u7684\u5f15\u53f7\u70bc\u72f1<\/h2>\n<p>\u5728 Windows \u4e0a <code>ssh host \"\u590d\u6742\u547d\u4ee4\"<\/code>\uff0cPowerShell \u7684\u5f15\u53f7\u8f6c\u4e49\u80fd\u628a\u4eba\u903c\u75af\uff0cJSON \u91cc\u7684 <code>\\\"<\/code> \u4f20\u8fc7\u53bb\u5341\u6b21\u6709\u516b\u6b21\u788e\u6389\u3002\u89e3\u6cd5\uff1a\u590d\u6742\u547d\u4ee4\u5199\u6210 <code>.sh<\/code> \u6587\u4ef6 \u2192 <code>scp<\/code> \u4e0a\u53bb \u2192 \u8fdc\u7aef\u6267\u884c\u3002\u8fd8\u6709\u5f69\u86cb\u5751\uff1aWindows \u5199\u7684\u811a\u672c\u5e26 CRLF \u884c\u5c3e\uff0cbash \u4f1a\u62a5 <code>$'\\r': \u672a\u627e\u5230\u547d\u4ee4<\/code>\uff0c\u6267\u884c\u524d\u5fc5\u987b <code>sed -i 's\/\\r$\/\/'<\/code>\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/6589jk.cn\/wp-content\/uploads\/2026\/10\/error.png\" width=\"150\" alt=\"\u51fa\u9519\u4e86\" \/> <img decoding=\"async\" src=\"https:\/\/6589jk.cn\/wp-content\/uploads\/2026\/10\/success.png\" width=\"150\" alt=\"\u641e\u5b9a\" \/><\/p>\n<h2>\u5c0f\u7ed3<\/h2>\n<p>\u516d\u4e2a\u96be\u70b9\uff0c\u5f52\u7c7b\u5c31\u4e09\u53e5\u8bdd\uff1a<strong>\u6d41\u5f0f IO \u8981\u7ba1\u5230\u6700\u540e\u4e00\u5b57\u8282\uff1b\u6846\u67b6\u7684\u5584\u610f\u8865\u507f\u80fd\u5236\u9020\u65b0\u9519\u8bef\uff1b\u6d4f\u89c8\u5668\u89c4\u8303\u6ca1\u6709\u5546\u91cf\u4f59\u5730\u3002<\/strong>\u6bcf\u4e2a\u5751\u7684\u4fee\u590d\u90fd\u8fdb\u4e86\u9879\u76ee README\uff0c\u540e\u6765\u63a5\u624b\u7684\u4eba\u4e0d\u7528\u518d\u8e29\u4e00\u904d\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/6589jk.cn\/wp-content\/uploads\/2026\/10\/readme-thumbsup.png\" width=\"150\" alt=\"\u70b9\u8d5e\" \/><\/p>\n<p>\u2014\u2014by \u96ea\u8389\uff0cAAO\uff01\u540d\u4fa6\u63a2\u7834\u6848\uff0c\u4ece\u4e0d\u7a7a\u624b\u800c\u5f52\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>AAO\uff01\u4e0a\u4e00\u7bc7\u804a\u4e86 CitrusPanel \u90fd\u80fd\u5e72\u4ec0\u4e48\uff0c\u8fd9\u4e00\u7bc7\u6765\u4e0a\u5e72\u8d27\u2014\u2014\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u8e29\u8fc7\u7684\u771f\u5b9e\u6280\u672f\u96be [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[29],"tags":[129,5,133,134,132],"class_list":["post-550","post","type-post","status-publish","format-standard","hentry","category-29","tag-blazor","tag-c","tag-webauthn","tag-zipstream","tag-132"],"_links":{"self":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts\/550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/comments?post=550"}],"version-history":[{"count":1,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts\/550\/revisions"}],"predecessor-version":[{"id":551,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/posts\/550\/revisions\/551"}],"wp:attachment":[{"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/media?parent=550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/categories?post=550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/6589jk.cn\/index.php\/wp-json\/wp\/v2\/tags?post=550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}