@elf-express/admin-net-mcp 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/index.js +83 -88
  2. package/knowledge/Furion_Teaching_Manual/04-1-/351/205/215/347/275/256.md +442 -0
  3. package/knowledge/Furion_Teaching_Manual/04-2-/351/201/270/351/240/205.md +363 -0
  4. package/knowledge/Furion_Teaching_Manual/05-1-/345/213/225/346/205/213WebAPI.md +825 -0
  5. package/knowledge/Furion_Teaching_Manual/05-2-HttpContext.md +217 -0
  6. package/knowledge/Furion_Teaching_Manual/05-3-/347/257/251/351/201/270/345/231/250/346/224/224/346/210/252/345/231/250AOP.md +581 -0
  7. package/knowledge/Furion_Teaching_Manual/05-4-/350/253/213/346/261/202/347/250/275/346/240/270/346/227/245/350/252/214.md +129 -0
  8. package/knowledge/Furion_Teaching_Manual/05-5-/344/270/255/344/273/213/350/273/237/351/253/224Middleware.md +328 -0
  9. package/knowledge/Furion_Teaching_Manual/05-6-Vue-React-Angular/344/273/213/351/235/242/344/273/243/347/220/206.md +317 -0
  10. package/knowledge/Furion_Teaching_Manual/06-1/350/246/217/347/257/204/345/214/226/346/216/245/345/217/243.md +1458 -0
  11. package/knowledge/Furion_Teaching_Manual/06-2/347/254/254/344/270/211/346/226/271API_Scalar.md +91 -0
  12. package/knowledge/Furion_Teaching_Manual/07-/345/217/213/345/245/275/344/276/213/345/244/226/350/231/225/347/220/206.md +511 -0
  13. package/knowledge/Furion_Teaching_Manual/08-1-/350/263/207/346/226/231/351/251/227/350/255/211/345/237/272/347/244/216/344/275/277/347/224/250.md +587 -0
  14. package/knowledge/Furion_Teaching_Manual/10-1-SqlSugar/346/225/264/345/220/210.md +336 -0
  15. package/knowledge/Furion_Teaching_Manual/11-SaaS /345/244/232/347/247/237/346/210/266/347/255/206/350/250/230.md" +271 -0
  16. package/knowledge/Furion_Teaching_Manual/12-furion-dependency-injection.md +408 -0
  17. package/knowledge/Furion_Teaching_Manual/13-/347/211/251/344/273/266/350/263/207/346/226/231/346/230/240/345/260/204/357/274/210Mapster/357/274/211.md +162 -0
  18. package/knowledge/Furion_Teaching_Manual/14-/345/210/206/345/270/203/345/274/217/347/274/223/345/255/230.md +311 -0
  19. package/knowledge/Furion_Teaching_Manual/15-/345/256/211/345/205/250/351/211/264/346/235/203.md +832 -0
  20. package/knowledge/Furion_Teaching_Manual/17-/346/252/242/350/246/226/347/257/204/346/234/254/345/274/225/346/223/216.md +327 -0
  21. package/knowledge/Furion_Teaching_Manual/18-/346/227/245/350/252/214/350/250/230/351/214/204.md +639 -0
  22. package/knowledge/Furion_Teaching_Manual/19-1-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/345/237/272/347/244/216/344/275/277/347/224/250.md +621 -0
  23. package/knowledge/Furion_Teaching_Manual/19-2-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/351/200/262/351/232/216/346/214/207/345/215/227.md +928 -0
  24. package/knowledge/Furion_Teaching_Manual/19-3-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/345/270/270/350/246/213/345/225/217/351/241/214.md +362 -0
  25. package/knowledge/Furion_Teaching_Manual/20-/350/263/207/346/226/231/345/212/240/350/247/243/345/257/206.md +286 -0
  26. package/knowledge/Furion_Teaching_Manual/20-/351/231/204/351/214/204-KSort/350/263/207/346/226/231/347/260/275/345/220/215/345/256/214/346/225/264/345/216/237/345/247/213/347/242/274.md +305 -0
  27. package/knowledge/Furion_Teaching_Manual/21-/345/205/250/347/220/203/345/214/226/345/222/214/346/234/254/345/234/260/345/214/226.md +342 -0
  28. package/knowledge/Furion_Teaching_Manual/22-/344/272/213/344/273/266/345/214/257/346/265/201/346/216/222EventBus.md +448 -0
  29. package/knowledge/Furion_Teaching_Manual/23-JSON/345/272/217/345/210/227/345/214/226.md +340 -0
  30. package/knowledge/Furion_Teaching_Manual/24-/345/215/263/346/231/202/351/200/232/350/250/212SignalR.md +247 -0
  31. package/knowledge/Furion_Teaching_Manual/25-/350/274/224/345/212/251/350/247/222/350/211/262/346/234/215/345/213/231WorkerService.md +295 -0
  32. package/knowledge/Furion_Teaching_Manual/26-1-/346/216/222/347/250/213/344/275/234/346/245/255/345/256/232/346/231/202/344/273/273/345/213/231.md +631 -0
  33. package/knowledge/Furion_Teaching_Manual/26-2-Cron/350/241/250/351/201/224/345/274/217.md +203 -0
  34. package/knowledge/Furion_Teaching_Manual/26-3-/344/273/273/345/213/231/344/275/207/345/210/227TaskQueue.md +215 -0
  35. package/knowledge/Furion_Teaching_Manual/27-/345/210/206/346/225/243/345/274/217ID/347/224/237/346/210/220.md +86 -0
  36. package/knowledge/Furion_Teaching_Manual/28-/346/250/241/347/265/204/345/214/226/351/226/213/347/231/274.md +68 -0
  37. package/knowledge/Furion_Teaching_Manual/29-/346/265/201/350/256/212/347/211/251/344/273/266Clay.md +313 -0
  38. package/knowledge/Furion_Teaching_Manual/30-/350/204/253/346/225/217/350/231/225/347/220/206/357/274/210Sensitive Detection).md" +168 -0
  39. package/knowledge/Furion_Teaching_Manual/32-/346/234/203/350/251/261/345/222/214/347/213/200/346/205/213/347/256/241/347/220/206.md +147 -0
  40. package/knowledge/Furion_Teaching_Manual/33-IPC/347/250/213/345/272/217/351/200/232/350/250/212.md +98 -0
  41. package/knowledge/Furion_Teaching_Manual/34-2-Docker/351/203/250/347/275/262.md +313 -0
  42. package/knowledge/Furion_Teaching_Manual/34-3-Nginx/351/203/250/347/275/262.md +157 -0
  43. package/knowledge/Furion_Teaching_Manual/34-8-WindowsService/351/203/250/347/275/262.md +112 -0
  44. package/knowledge/Furion_Teaching_Manual/35-1-Docker/347/222/260/345/242/203/346/214/201/347/272/214/351/203/250/347/275/262Jenkins.md +169 -0
  45. package/knowledge/Furion_Teaching_Manual/36-1-/345/226/256/345/205/203/346/270/254/350/251/246/346/225/264/345/220/210/346/270/254/350/251/246.md +275 -0
  46. package/knowledge/Furion_Teaching_Manual/36-3-/345/237/272/346/272/226/346/270/254/350/251/246Benchmarking.md +80 -0
  47. package/knowledge/attributes.md +153 -0
  48. package/knowledge/config.md +147 -0
  49. package/knowledge/entity.md +115 -0
  50. package/knowledge/event.md +124 -0
  51. package/knowledge/plugin.md +136 -0
  52. package/knowledge/service.md +146 -0
  53. package/knowledge/sqlsugar.md +172 -0
  54. package/knowledge/vue-typescript.md +338 -0
  55. package/package.json +3 -2
@@ -0,0 +1,362 @@
1
+ # 19.Ⅲ HTTP 遠端請求 — 常見問題
2
+
3
+ > **版本說明**:僅適用於 Furion 4.9.6+(HttpAgent),不支援 .NET8 以下版本。
4
+
5
+ ---
6
+
7
+ ## 19.28 常見問題
8
+
9
+ ### 19.28.1 忽略 SSL 憑證驗證
10
+
11
+ ```csharp
12
+ // HttpClientHandler
13
+ services.AddHttpClient(string.Empty)
14
+ .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
15
+ {
16
+ ServerCertificateCustomValidationCallback = HttpRemoteUtility.IgnoreSslErrors,
17
+ SslProtocols = HttpRemoteUtility.AllSslProtocols
18
+ });
19
+
20
+ // SocketsHttpHandler
21
+ services.AddHttpClient(string.Empty)
22
+ .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
23
+ {
24
+ SslOptions = new SslClientAuthenticationOptions
25
+ {
26
+ RemoteCertificateValidationCallback = HttpRemoteUtility.IgnoreSocketSslErrors,
27
+ EnabledSslProtocols = HttpRemoteUtility.AllSslProtocols
28
+ }
29
+ });
30
+
31
+ // 單次請求
32
+ HttpRequestBuilder.Get("https://furion.net/")
33
+ .SetHttpClientProvider(() => (new HttpClient(new HttpClientHandler
34
+ {
35
+ ServerCertificateCustomValidationCallback = HttpRemoteUtility.IgnoreSslErrors,
36
+ SslProtocols = HttpRemoteUtility.AllSslProtocols
37
+ }), client => client.Dispose()));
38
+ ```
39
+
40
+ ---
41
+
42
+ ### 19.28.2 強制 IPv4 或 IPv6 請求
43
+
44
+ ```csharp
45
+ // 強制 IPv4
46
+ services.AddHttpClient(string.Empty)
47
+ .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
48
+ {
49
+ ConnectCallback = HttpRemoteUtility.IPv4ConnectCallback
50
+ });
51
+
52
+ // 強制 IPv6
53
+ services.AddHttpClient(string.Empty)
54
+ .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
55
+ {
56
+ ConnectCallback = HttpRemoteUtility.IPv6ConnectCallback
57
+ });
58
+
59
+ // 自動選擇
60
+ services.AddHttpClient(string.Empty)
61
+ .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
62
+ {
63
+ ConnectCallback = HttpRemoteUtility.UnspecifiedConnectCallback
64
+ });
65
+
66
+ // 多網卡:指定本地出口 IPv4
67
+ ConnectCallback = (context, token) =>
68
+ HttpRemoteUtility.ConnectWithLocalIPv4(IPAddress.Parse("192.168.0.103"), context, token)
69
+
70
+ // 多網卡:指定本地出口 IPv6
71
+ ConnectCallback = (context, token) =>
72
+ HttpRemoteUtility.ConnectWithLocalIPv6(IPAddress.Parse("::1"), context, token)
73
+ ```
74
+
75
+ ---
76
+
77
+ ### 19.28.3 重新導向回應處理
78
+
79
+ **全域啟用/停用(HttpRemoteOptions):**
80
+
81
+ ```csharp
82
+ services.AddHttpRemote(builder => {})
83
+ .ConfigureOptions(options =>
84
+ {
85
+ options.AllowAutoRedirect = false; // 預設 true
86
+ options.MaximumAutomaticRedirections = 50; // 預設 50
87
+ });
88
+ ```
89
+
90
+ **全域啟用/停用(HttpClient):**
91
+
92
+ ```csharp
93
+ services.AddHttpClient(string.Empty)
94
+ .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
95
+ {
96
+ AllowAutoRedirect = true,
97
+ MaxAutomaticRedirections = 20
98
+ });
99
+ ```
100
+
101
+ > ⚠️ 完全停用自動重新導向需**同時**設定 `HttpRemoteOptions` 和 `HttpClient`。
102
+
103
+ **手動處理重新導向:**
104
+
105
+ ```csharp
106
+ var response = await httpRemoteService.GetAsync("https://furion.net/redirect");
107
+ var statusCode = response.StatusCode;
108
+
109
+ if (statusCode is HttpStatusCode.Ambiguous or HttpStatusCode.Moved or HttpStatusCode.Redirect
110
+ or HttpStatusCode.RedirectMethod or HttpStatusCode.RedirectKeepVerb || (int)statusCode == 308)
111
+ {
112
+ var redirectUrl = response.Headers.Location;
113
+ if (redirectUrl != null)
114
+ response = await httpRemoteService.GetAsync(redirectUrl);
115
+ }
116
+ ```
117
+
118
+ ---
119
+
120
+ ### 19.28.4 效能最佳化
121
+
122
+ ```csharp
123
+ // 全域
124
+ services.AddHttpClient(string.Empty, client => client.PerformanceOptimization());
125
+
126
+ // 單次
127
+ HttpRequestBuilder.Get("https://furion.net/").PerformanceOptimization();
128
+ ```
129
+
130
+ 啟用後自動添加:`Accept: */*`、`Accept-Encoding: gzip, deflate, br`、`Connection: keep-alive`。
131
+
132
+ > ⚠️ 需要回傳 `Stream` 或進行 `HttpContext` 網頁轉發時,**請勿啟用**此設定。
133
+
134
+ ---
135
+
136
+ ### 19.28.5 設定預設 User-Agent
137
+
138
+ 框架預設使用 Edge 135 的 User-Agent。自訂方式:
139
+
140
+ ```csharp
141
+ // 全域
142
+ services.AddHttpClient(string.Empty, client =>
143
+ client.DefaultRequestHeaders.Add("User-Agent", "你的 User-Agent"));
144
+
145
+ // 單次
146
+ HttpRequestBuilder.Post("https://furion.net/")
147
+ .WithHeader("User-Agent", "你的 User-Agent", replace: true);
148
+ ```
149
+
150
+ ---
151
+
152
+ ### 19.28.6 發送相對位址(內部)請求
153
+
154
+ **ASP.NET 應用:**
155
+
156
+ ```csharp
157
+ services.AddHttpRemote()
158
+ .ConfigureOptions((options, sp) =>
159
+ {
160
+ var addresses = sp.GetRequiredService<IServer>().Features.Get<IServerAddressesFeature>()!;
161
+ options.FallbackBaseAddress = new Uri(addresses.Addresses.FirstOrDefault());
162
+ });
163
+ ```
164
+
165
+ **Blazor WebAssembly:**
166
+
167
+ ```csharp
168
+ services.AddHttpRemote()
169
+ .ConfigureOptions((options, sp) =>
170
+ {
171
+ options.FallbackBaseAddress = new Uri(sp.GetRequiredService<NavigationManager>().BaseUri);
172
+ });
173
+ ```
174
+
175
+ 使用時直接發送相對路徑:
176
+
177
+ ```csharp
178
+ var content = await httpRemoteService.GetAsStringAsync("/user/1");
179
+ ```
180
+
181
+ > 若在 `BackgroundService` 中 `Addresses` 為空,可透過 `IConfiguration` 讀取 `Urls` 節點設定。
182
+
183
+ ---
184
+
185
+ ### 19.28.7 取得回應 Cookie
186
+
187
+ ```csharp
188
+ // 方式一:HttpRemoteResult<T>
189
+ var result = await httpRemoteService.GetAsync<string>("https://furion.net/");
190
+ var setCookies = result.SetCookies; // IList<SetCookieHeaderValue>
191
+ var rawSetCookies = result.RawSetCookies; // List<string>
192
+
193
+ // 方式二:HttpResponseMessage 擴充方法
194
+ var response = await httpRemoteService.GetAsync("https://furion.net/");
195
+ response.TryGetSetCookies(out var setCookies, out var rawSetCookies);
196
+ ```
197
+
198
+ ---
199
+
200
+ ### 19.28.8 設定 Windows 身分驗證
201
+
202
+ ```csharp
203
+ // 使用目前 Windows 登入使用者(推薦)
204
+ .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { UseDefaultCredentials = true });
205
+
206
+ // 手動輸入帳密
207
+ .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
208
+ {
209
+ Credentials = new NetworkCredential("使用者名稱", "密碼"),
210
+ PreAuthenticate = true
211
+ });
212
+ ```
213
+
214
+ ---
215
+
216
+ ### 19.28.9 設定 Kerberos / Active Directory 身分驗證
217
+
218
+ **同網域:** 同 19.28.8,設定 `UseDefaultCredentials = true`。
219
+
220
+ **跨網域(使用 `Microsoft.Identity.Client`):**
221
+
222
+ ```bash
223
+ dotnet add package Microsoft.Identity.Client
224
+ ```
225
+
226
+ ```csharp
227
+ var app = PublicClientApplicationBuilder.Create(clientId)
228
+ .WithAuthority($"https://login.microsoftonline.com/{tenantId}")
229
+ .Build();
230
+
231
+ var result = await app.AcquireTokenInteractive(new[] { "api://目標服務的作用域" }).ExecuteAsync();
232
+
233
+ httpRemoteService.SendAsync(HttpRequestBuilder.Post("https://furion.net/")
234
+ .AddJwtBearerAuthentication(result.AccessToken));
235
+ ```
236
+
237
+ ---
238
+
239
+ ### 19.28.10 回應內容解壓與亂碼處理
240
+
241
+ 框架預設**自動解壓** gzip、deflate、brotli。
242
+
243
+ **自訂自動解壓:**
244
+
245
+ ```csharp
246
+ services.AddHttpClient(string.Empty)
247
+ .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
248
+ {
249
+ AutomaticDecompression = DecompressionMethods.All
250
+ // 或 DecompressionMethods.GZip | DecompressionMethods.Deflate
251
+ });
252
+ ```
253
+
254
+ **手動解壓:**
255
+
256
+ ```csharp
257
+ // 先停用自動解壓
258
+ AutomaticDecompression = DecompressionMethods.None
259
+
260
+ // 手動處理
261
+ var response = await httpRemoteService.GetAsync("https://furion.com");
262
+ if (response.Content.Headers.ContentEncoding.Contains("gzip"))
263
+ {
264
+ using var stream = await response.Content.ReadAsStreamAsync();
265
+ using var gzip = new GZipStream(stream, CompressionMode.Decompress);
266
+ using var reader = new StreamReader(gzip);
267
+ var content = await reader.ReadToEndAsync();
268
+ }
269
+ ```
270
+
271
+ ---
272
+
273
+ ### 19.28.11 JSON 序列化設定
274
+
275
+ ```csharp
276
+ // 全域預設
277
+ services.AddHttpRemote(builder => {})
278
+ .ConfigureOptions(options =>
279
+ options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
280
+
281
+ // 客戶端級(優先級更高)
282
+ services.AddHttpClient("furion")
283
+ .ConfigureOptions(options =>
284
+ options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
285
+
286
+ // 使用特定客戶端
287
+ var model = await httpRemoteService.SendAsAsync<YourModel>(
288
+ HttpRequestBuilder.Get("https://furion.net/test-json").SetHttpClientName("furion"));
289
+
290
+ // 手動處理
291
+ var json = await httpRemoteService.GetAsStringAsync("https://furion.net/test-json");
292
+ var model = JsonSerializer.Deserialize<YourModel>(json, new JsonSerializerOptions());
293
+ ```
294
+
295
+ > 若需替換為 `Newtonsoft.Json`,請自訂 `IHttpContentProcessor` 實作(參見 19.6.3)。
296
+
297
+ ---
298
+
299
+ ### 19.28.12 停用分散式追蹤上下文(traceparent 標頭)
300
+
301
+ ```csharp
302
+ services.AddHttpClient(string.Empty)
303
+ .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
304
+ {
305
+ ActivityHeadersPropagator = null
306
+ });
307
+ ```
308
+
309
+ ---
310
+
311
+ ### 19.28.13 設定 Content-Type(MIME)
312
+
313
+ 推薦使用 `MediaTypeNames` 靜態類避免拼字錯誤:
314
+
315
+ ```csharp
316
+ HttpRequestBuilder.Get("...").SetContentType(MediaTypeNames.Text.Plain);
317
+ HttpRequestBuilder.Post("...").SetContentType(MediaTypeNames.Application.Json);
318
+ HttpRequestBuilder.Post("...").SetContentType(MediaTypeNames.Application.FormUrlEncoded);
319
+ ```
320
+
321
+ ---
322
+
323
+ ### 19.28.14 在非相依性注入環境中使用(Console / WinForms / WPF)
324
+
325
+ ```csharp
326
+ // 直接使用
327
+ var result = await HttpRemoteClient.Service.GetAsStringAsync("https://furion.net/");
328
+
329
+ // 自訂設定
330
+ HttpRemoteClient.Configure(services =>
331
+ {
332
+ services.AddHttpClient(string.Empty).AddProfilerDelegatingHandler();
333
+ });
334
+
335
+ // 釋放資源(呼叫後無法再次實例化)
336
+ HttpRemoteClient.Dispose();
337
+ ```
338
+
339
+ 或手動建立服務容器:
340
+
341
+ ```csharp
342
+ var services = new ServiceCollection();
343
+ services.AddHttpRemote();
344
+ using var provider = services.BuildServiceProvider();
345
+ var httpRemoteService = provider.GetRequiredService<IHttpRemoteService>();
346
+ ```
347
+
348
+ ---
349
+
350
+ ### 19.28.15 與舊版 Java API 對接
351
+
352
+ ```csharp
353
+ HttpRequestBuilder.Get("https://furion.net").AutoSetHostHeader();
354
+ ```
355
+
356
+ ---
357
+
358
+ ### 19.28.16 AddHttpRemote 二義性錯誤
359
+
360
+ ```csharp
361
+ services.AddHttpRemote(builder => {});
362
+ ```
@@ -0,0 +1,286 @@
1
+ # 20. 資料加解密
2
+
3
+ ---
4
+
5
+ ## 20.1 概述
6
+
7
+ 資料加解密是系統開發必要的環節,用於保護使用者密碼、Cookie 等敏感資訊。
8
+
9
+ ---
10
+
11
+ ## 20.2 內建加密演算法
12
+
13
+ | 演算法 | 說明 |
14
+ |--------|------|
15
+ | MD5 | 加密 / 比較 |
16
+ | DES | 加解密 |
17
+ | AES | 加解密(支援 IV 向量、Mode、Padding、檔案加解密) |
18
+ | JWT | 加解密(需安裝 `Furion.Extras.Authentication.JwtBearer`) |
19
+ | PBKDF2 | 加密 / 比較(**推薦用於密碼加密**)(4.9.3.7+) |
20
+ | RSA | 加解密(支援超長字元分段加解密) |
21
+ | SHA1 | 加密 / 比較(4.9.2.41+) |
22
+ | KSort | API 資料簽名(4.9.5.10+) |
23
+ | Gzip | 壓縮 / 解壓(4.9.7.26+) |
24
+
25
+ ---
26
+
27
+ ## 20.3 加解密使用
28
+
29
+ ### 20.3.1 MD5 加密
30
+
31
+ ```csharp
32
+ var md5Hash = MD5Encryption.Encrypt("百小僧"); // 加密
33
+ var isEqual = MD5Encryption.Compare("百小僧", md5Hash); // 比較
34
+
35
+ var md5Upper = MD5Encryption.Encrypt("百小僧", true); // 大寫
36
+ var md5_16 = MD5Encryption.Encrypt("百小僧", is16: true); // 16 位(4.2.6+)
37
+
38
+ // byte[] 支援(4.8.6.3+)
39
+ var bytes = File.ReadAllBytes("image.png");
40
+ var hash = MD5Encryption.Encrypt(bytes);
41
+ var eq = MD5Encryption.Compare(bytes, hash);
42
+ ```
43
+
44
+ ### 20.3.2 DES 加解密
45
+
46
+ ```csharp
47
+ var desHash = DESEncryption.Encrypt("百小僧", "Furion"); // 加密
48
+ var str = DESEncryption.Decrypt(desHash, "Furion"); // 解密
49
+ ```
50
+
51
+ > ⚠️ 4.9.2.41+ 命名調整:`DESCEncryption` → `DESEncryption`,`ToDESCEncrypt` → `ToDESEncrypt`,`ToDESCDecrypt` → `ToDESDecrypt`。
52
+
53
+ ### 20.3.3 AES 加解密
54
+
55
+ ```csharp
56
+ var key = Guid.NewGuid().ToString("N"); // 密鑰,長度必須為 16 / 24 / 32 位
57
+
58
+ var aesHash = AESEncryption.Encrypt("百小僧", key); // 加密
59
+ var str = AESEncryption.Decrypt(aesHash, key); // 解密
60
+ ```
61
+
62
+ **自訂 IV 向量、Mode、Padding(4.9.2.18+):**
63
+
64
+ ```csharp
65
+ var key = "bda66540c463dfdbe70666019f89e554"; // 32 位元密鑰
66
+ byte[] customIV = { 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f, 0x70, 0x81,
67
+ 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7, 0xf8, 0x09 };
68
+
69
+ var encrypted = AESEncryption.Encrypt(plainText, key, customIV, CipherMode.CBC, PaddingMode.PKCS7);
70
+ var decrypted = AESEncryption.Decrypt(encrypted, key, customIV, CipherMode.CBC, PaddingMode.PKCS7);
71
+ ```
72
+
73
+ > IV 向量必須為長度 16 的 `byte[]`。Base64 編碼的 IV 請用 `Convert.FromBase64String()` 轉換。
74
+ > 若密鑰為 Base64 字串,需設定 `isBase64: true`(4.9.7.41+)。
75
+
76
+ **檔案加解密(4.8.8.11+):**
77
+
78
+ ```csharp
79
+ // 加密
80
+ var originBytes = File.ReadAllBytes("xxx.rar");
81
+ var encryptBytes = AESEncryption.Encrypt(originBytes, "1234567890abcdef");
82
+
83
+ // 解密
84
+ var encryptBytes = File.ReadAllBytes("xxx.加密.rar");
85
+ var originBytes = AESEncryption.Decrypt(encryptBytes, "1234567890abcdef");
86
+ ```
87
+
88
+ ### 20.3.4 JWT 加解密
89
+
90
+ > ⚠️ 需安裝 `Furion.Extras.Authentication.JwtBearer` 套件。
91
+
92
+ ```csharp
93
+ var token = JWTEncryption.Encrypt(new Dictionary<string, object>
94
+ {
95
+ { "UserId", user.Id },
96
+ { "Account", user.Account }
97
+ });
98
+
99
+ var tokenData = JWTEncryption.ReadJwtToken("你的 token");
100
+ var (isValid, tokenData, validationResult) = JWTEncryption.Validate("你的 token");
101
+ ```
102
+
103
+ ### 20.3.5 PBKDF2 加密(4.9.3.7+)
104
+
105
+ ```csharp
106
+ var hash = PBKDF2Encryption.Encrypt("百小僧");
107
+ var isEqual = PBKDF2Encryption.Compare("百小僧", hash);
108
+ ```
109
+
110
+ ### 20.3.6 RSA 加解密
111
+
112
+ ```csharp
113
+ var (publicKey, privateKey) = RSAEncryption.GenerateSecretKey(2048);
114
+ // 密鑰大小:2048 ~ 16384,須為 8 的倍數
115
+
116
+ var encrypted = RSAEncryption.Encrypt("百小僧", publicKey);
117
+ var decrypted = RSAEncryption.Decrypt(encrypted, privateKey);
118
+ ```
119
+
120
+ > RSA 簽名和校驗功能未內建,可查閱開發者提交的程式碼。4.8.8.2+ 支援超長字元(>245 位)分段加解密。
121
+
122
+ ### 20.3.7 SHA1 加密(4.9.2.41+)
123
+
124
+ ```csharp
125
+ var hash = SHA1Encryption.Encrypt("百小僧");
126
+ var isEqual = SHA1Encryption.Compare("百小僧", hash);
127
+
128
+ var hashUpper = SHA1Encryption.Encrypt("百小僧", true); // 大寫
129
+
130
+ // byte[]
131
+ var bytes = File.ReadAllBytes("image.png");
132
+ var hash2 = SHA1Encryption.Encrypt(bytes);
133
+ var eq = SHA1Encryption.Compare(bytes, hash2);
134
+ ```
135
+
136
+ ### 20.3.8 KSort 資料簽名(API 簽名)(4.9.5.10+)
137
+
138
+ **C# 簽名:**
139
+
140
+ ```csharp
141
+ var appId = "ca36cb2858ce3517df772ec34ce92f21";
142
+ var appKey = "95e4a4f651c2d62679c4c150f2e39f4a";
143
+ var command = "add.user";
144
+ var data = JsonSerializer.Serialize(new { id = 1, name = "Furion" });
145
+
146
+ KSortSignature sData = KSortEncryption.Encrypt(appId, appKey, command, data);
147
+ ```
148
+
149
+ 產出格式:
150
+
151
+ ```json
152
+ {
153
+ "app_id": "ca36cb2858ce3517df772ec34ce92f21",
154
+ "app_key": "95e4a4f651c2d62679c4c150f2e39f4a",
155
+ "command": "add.user",
156
+ "data": "{\"id\":1,\"name\":\"Furion\"}",
157
+ "timestamp": 1726695114461,
158
+ "signature": "f6ead3f509c952249f3046ebc4e6e149"
159
+ }
160
+ ```
161
+
162
+ **C# 驗證:**
163
+
164
+ ```csharp
165
+ bool result = KSortEncryption.Compare(dataString); // JSON 字串或 KSortSignature 物件
166
+ ```
167
+
168
+ **TypeScript/JavaScript 簽名:**
169
+
170
+ ```bash
171
+ npm install crypto-js
172
+ ```
173
+
174
+ ```typescript
175
+ var sData = signatureByKSort(appId, appKey, "add.user", { id: 1, name: "furion" });
176
+ fetch("http://furion.net", sData).then(res => res.json()).then(data => {});
177
+ ```
178
+
179
+ > 客戶端的 `data-signature.ts` 可從 Furion 官方 Gitee 倉庫取得。
180
+
181
+ **最佳實踐:**
182
+
183
+ ```csharp
184
+ [HttpPost]
185
+ public async Task AddUser([Required] KSortSignature sData)
186
+ {
187
+ if (!KSortEncryption.Compare(sData))
188
+ throw new Exception("非法資料");
189
+
190
+ var data = JsonSerializer.Deserialize<原始資料型別>(sData.data);
191
+ }
192
+ ```
193
+
194
+ > `appId` 和 `appKey` 應從伺服器取得,切勿明文寫在客戶端程式碼中。可實作中介軟體統一驗證。
195
+
196
+ ### 20.3.9 Gzip 壓縮解壓(4.9.7.26+)
197
+
198
+ ```csharp
199
+ var bytes = GzipEncryption.Compress("Furion");
200
+ var text = GzipEncryption.Decompress(bytes);
201
+
202
+ // Base64
203
+ var base64 = GzipEncryption.CompressToBase64("Furion");
204
+ var text2 = GzipEncryption.DecompressFromBase64(base64);
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 20.4 字串擴充方式
210
+
211
+ ```csharp
212
+ using Furion.DataEncryption.Extensions;
213
+
214
+ // MD5
215
+ var s = "Furion".ToMD5Encrypt();
216
+ var b = "Furion".ToMD5Compare(s);
217
+
218
+ // AES
219
+ var s = "Furion".ToAESEncrypt(key);
220
+ var str = s.ToAESDecrypt(key);
221
+
222
+ // DES
223
+ var s = "Furion".ToDESEncrypt(key);
224
+ var str = s.ToDESDecrypt(key);
225
+
226
+ // PBKDF2
227
+ var s = "Furion".ToPBKDF2Encrypt();
228
+ var b = "Furion".ToPBKDF2Compare(s);
229
+
230
+ // RSA
231
+ var (pub, pri) = RSAEncryption.GenerateSecretKey(2048);
232
+ var s = "Furion".ToRSAEncrpyt(pub);
233
+ var str = s.ToRSADecrypt(pri);
234
+
235
+ // SHA1
236
+ var s = "Furion".ToSHA1Encrypt();
237
+ var b = "Furion".ToSHA1Compare(s);
238
+
239
+ // Gzip
240
+ var s = "Furion".ToGzipCompress();
241
+ var b = s.ToGzipDecompress();
242
+ var s1 = "Furion".ToGzipCompressToBase64();
243
+ var b1 = s1.ToGzipDecompressFromBase64();
244
+ ```
245
+
246
+ ---
247
+
248
+ ## 20.5 SM2、SM3、SM4 國密
249
+
250
+ 框架未內建國密演算法,可使用開源社群貢獻的實作:
251
+
252
+ ```csharp
253
+ // SM2
254
+ var b = SM2Utils.加密("123");
255
+ var b1 = SM2Utils.解密(b);
256
+
257
+ // SM3(常用於數位簽名)
258
+ var sm3 = new SM3Utils();
259
+ sm3.secretKey = "ASAFSDFDSGSDFSDFSDFSFSF";
260
+ var token = sm3.加密("123");
261
+
262
+ // SM4
263
+ var sm4 = new SM4Utils();
264
+ sm4.secretKey = "BDBDBDBDBDBDBDBDBDBDBDBDBDBDBD";
265
+ var a = sm4.加密(data);
266
+ var a1 = sm4.解密(a);
267
+ ```
268
+
269
+ ---
270
+
271
+ ## 更新日誌摘要
272
+
273
+ | 版本 | 日期 | 內容 |
274
+ |------|------|------|
275
+ | 4.9.7.71 | 2025.05.23 | 修復 AES ECB + PKCS7 加密結果不一致 |
276
+ | 4.9.7.42 | 2025.04.15 | 修復 AES 密鑰安全漏洞(強制 AES 規範長度) |
277
+ | 4.9.7.41 | 2025.04.14 | AES 解密支援 Base64 字串密鑰 |
278
+ | 4.9.7.27 | 2025.03.21 | 修復 AES iv 位元組不足 16 位問題 |
279
+ | 4.9.7.26 | 2025.03.20 | 新增 Gzip 壓縮解壓 |
280
+ | 4.9.7.7 | 2025.02.14 | 修復 ECB 模式下 AES IV 被截斷問題 |
281
+ | 4.9.5.10 | 2024.09.19 | 新增 KSort API 資料簽名 |
282
+ | 4.9.3.7 | 2024.05.21 | 新增 PBKDF2 加密 |
283
+ | 4.9.2.41 | 2024.05.08 | 新增 SHA1、DES 命名調整 |
284
+ | 4.9.2.18 | 2024.04.15 | AES 支援 IV / Mode / Padding |
285
+ | 4.8.8.11 | 2023.05.05 | AES 檔案加解密 |
286
+ | 4.8.8.2 | 2023.04.19 | RSA 超長字元分段加解密 |