2 Revize cb51615392 ... 01111f9e5c

Autor SHA1 Zpráva Datum
  gjh 01111f9e5c 增加webview用的进度条 před 2 týdny
  gjh 456375e08e 增加RSA加密解密方法,增加国康RAS公钥配置信息 před 2 týdny

+ 91 - 0
lib/funcs.dart

@@ -26,6 +26,9 @@ import 'package:network_info_plus/network_info_plus.dart';
26 26
 import 'package:package_info_plus/package_info_plus.dart';
27 27
 import 'package:path_provider/path_provider.dart';
28 28
 import 'package:permission_handler/permission_handler.dart';
29
+import 'package:pointycastle/asymmetric/pkcs1.dart';
30
+import 'package:pointycastle/asymmetric/rsa.dart';
31
+import 'package:pointycastle/pointycastle.dart';
29 32
 
30 33
 import 'global.dart';
31 34
 
@@ -532,6 +535,94 @@ String aesDecrypt(String str) {
532 535
   return _encrypter.decrypt(encrptyed, iv: _iv);
533 536
 }
534 537
 
538
+///合并字节数组
539
+Uint8List concatenateBytes(List<Uint8List> byteList) {
540
+  int totalLength = byteList.fold(0, (sum, bytes) => sum + bytes.length);
541
+  Uint8List result = Uint8List(totalLength);
542
+  int offset = 0;
543
+
544
+  for (var bytes in byteList) {
545
+    result.setRange(offset, offset + bytes.length, bytes);
546
+    offset += bytes.length;
547
+  }
548
+
549
+  return result;
550
+}
551
+
552
+///RSA加密,返回BASE64字符串,仅支持PKCS1编码
553
+///
554
+/// [keyBitLength] 密钥长度,应为512,1024,2048,4096中的一个,默认512
555
+String rsaEncrypt(String pubKey, String content, {int keyBitLength = 512}) {
556
+  try {
557
+    final cipher = PKCS1Encoding(RSAEngine())
558
+      ..init(
559
+          true,
560
+          PublicKeyParameter<RSAPublicKey>(
561
+              encrpyt.RSAKeyParser().parse(pubKey) as RSAPublicKey));
562
+
563
+    final utf8Bytes = Uint8List.fromList(utf8.encode(content));
564
+    final inputLen = utf8Bytes.length;
565
+    int offLen = 0;
566
+    int i = 0;
567
+    List<Uint8List> bops = [];
568
+
569
+    int size = (keyBitLength / 8 - 11).toInt();
570
+    while (inputLen - offLen > 0) {
571
+      final chunkSize = (inputLen - offLen > size) ? size : inputLen - offLen;
572
+      final cache = cipher.process(
573
+          Uint8List.sublistView(utf8Bytes, offLen, offLen + chunkSize));
574
+      bops.add(cache);
575
+      i++;
576
+      offLen = size * i;
577
+    }
578
+
579
+    final encryptedData = concatenateBytes(bops);
580
+    final base64Encoded = base64Encode(encryptedData);
581
+
582
+    return base64Encoded;
583
+  } catch (e) {
584
+    loge("RSA加密异常", error: e);
585
+    return "";
586
+  }
587
+}
588
+
589
+///RSA解密,输入BASE64,仅支持PKCS1编码
590
+///
591
+/// [keyBitLength] 密钥长度,应为512,1024,2048,4096中的一个,默认512
592
+String rsaDecrypt(String priKey, String content, {int keyBitLength = 512}) {
593
+  try {
594
+    final cipher = PKCS1Encoding(RSAEngine());
595
+    cipher.init(
596
+        false,
597
+        PrivateKeyParameter<RSAPrivateKey>(
598
+            encrpyt.RSAKeyParser().parse(priKey) as RSAPrivateKey));
599
+
600
+    final encryptedBytes = base64Decode(content);
601
+    final inputLen = encryptedBytes.length;
602
+    int offLen = 0;
603
+    int i = 0;
604
+
605
+    List<Uint8List> byteList = [];
606
+
607
+    int size = keyBitLength ~/ 8;
608
+    while (inputLen - offLen > 0) {
609
+      final int chunkSize =
610
+          (inputLen - offLen > size) ? size : inputLen - offLen;
611
+      final cache = cipher.process(
612
+          Uint8List.sublistView(encryptedBytes, offLen, offLen + chunkSize));
613
+      byteList.add(cache);
614
+      i++;
615
+      offLen = size * i;
616
+    }
617
+
618
+    final byteArray = concatenateBytes(byteList);
619
+    return utf8.decode(byteArray);
620
+  } catch (e) {
621
+    loge("RSA解密异常", error: e);
622
+    return '';
623
+  }
624
+}
625
+
535 626
 ///检查新版本
536 627
 ///
537 628
 /// 返回true表示有新版本,false没有新版本

+ 11 - 0
lib/global.dart

@@ -66,3 +66,14 @@ final MethodChannel videoChannel = const MethodChannel(_videoChannelName);
66 66
 
67 67
 ///文件channel
68 68
 final MethodChannel fileChannel = const MethodChannel(_fileChannelName);
69
+
70
+///国康RSA加密公钥
71
+final String gkRsaPublicKey = """
72
+-----BEGIN PUBLIC KEY-----
73
+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALltnyc4QcGMQ7/ZT+xmV6x/OXdJ2k5ftatsES9XlScM
74
+fPgs/mANKCixDwNFOIAFvTnKUvGgxVhBXpFL8Ma/J0cCAwEAAQ==
75
+-----END PUBLIC KEY-----
76
+    """;
77
+
78
+///国康RSA加密密钥长度
79
+final int gkRsaKeyBitLength = 512;

+ 43 - 29
lib/pages/web/webview_page.dart

@@ -1,6 +1,7 @@
1 1
 import 'package:auto_route/annotations.dart';
2 2
 import 'package:eitc_erm_dental_flutter/exts.dart';
3 3
 import 'package:eitc_erm_dental_flutter/funcs.dart';
4
+import 'package:eitc_erm_dental_flutter/widget/webview_progress_bar.dart';
4 5
 import 'package:flutter/foundation.dart';
5 6
 import 'package:flutter/material.dart';
6 7
 import 'package:flutter_inappwebview/flutter_inappwebview.dart';
@@ -34,6 +35,9 @@ class _WebviewPageState extends State<WebviewPage> {
34 35
       iframeAllowFullscreen: true,
35 36
       javaScriptEnabled: true);
36 37
 
38
+  final WebviewProgressBarController _progressBarController =
39
+      WebviewProgressBarController();
40
+
37 41
   @override
38 42
   void initState() {
39 43
     super.initState();
@@ -42,6 +46,7 @@ class _WebviewPageState extends State<WebviewPage> {
42 46
   @override
43 47
   void dispose() {
44 48
     super.dispose();
49
+    _progressBarController.dispose();
45 50
   }
46 51
 
47 52
   void _load() async {
@@ -67,35 +72,44 @@ class _WebviewPageState extends State<WebviewPage> {
67 72
       ),
68 73
       //body: SafeArea(child: WebViewWidget(controller: _controller)),
69 74
       body: SafeArea(
70
-        child: InAppWebView(
71
-          key: _webViewKey,
72
-          initialSettings: _settings,
73
-          onWebViewCreated: (controller) {
74
-            _webViewController = controller;
75
-            _load();
76
-          },
77
-          onLoadStart: (controller, url) {
78
-            logd("onLoadStart,url=$url");
79
-          },
80
-          onPermissionRequest: (controller, request) async {
81
-            return PermissionResponse(
82
-                resources: request.resources,
83
-                action: PermissionResponseAction.GRANT);
84
-          },
85
-          onLoadStop: (controller, url) async {
86
-            logd("onLoadStop,url=$url");
87
-          },
88
-          onReceivedError: (controller, request, error) {
89
-            loge("onReceivedError", error: error);
90
-          },
91
-          onProgressChanged: (controller, progress) {
92
-            logd("onProgressChanged,progress=$progress");
93
-          },
94
-          onConsoleMessage: (controller, consoleMessage) {
95
-            if (kDebugMode) {
96
-              logd(consoleMessage);
97
-            }
98
-          },
75
+        child: Stack(
76
+          children: [
77
+            InAppWebView(
78
+              key: _webViewKey,
79
+              initialSettings: _settings,
80
+              onWebViewCreated: (controller) {
81
+                _webViewController = controller;
82
+                _load();
83
+              },
84
+              onLoadStart: (controller, url) {
85
+                logd("onLoadStart,url=$url");
86
+              },
87
+              onPermissionRequest: (controller, request) async {
88
+                return PermissionResponse(
89
+                    resources: request.resources,
90
+                    action: PermissionResponseAction.GRANT);
91
+              },
92
+              onLoadStop: (controller, url) async {
93
+                logd("onLoadStop,url=$url");
94
+              },
95
+              onReceivedError: (controller, request, error) {
96
+                loge("onReceivedError", error: error);
97
+              },
98
+              onProgressChanged: (controller, progress) {
99
+                logd("onProgressChanged,progress=$progress");
100
+                _progressBarController.setProgress(progress);
101
+              },
102
+              onConsoleMessage: (controller, consoleMessage) {
103
+                if (kDebugMode) {
104
+                  logd(consoleMessage);
105
+                }
106
+              },
107
+            ),
108
+            Align(
109
+              alignment: Alignment.topLeft,
110
+              child: WebviewProgressBar(controller: _progressBarController),
111
+            )
112
+          ],
99 113
         ),
100 114
       ),
101 115
     );

+ 73 - 0
lib/widget/webview_progress_bar.dart

@@ -0,0 +1,73 @@
1
+import 'package:flutter/material.dart';
2
+
3
+///Webview进度条
4
+class WebviewProgressBar extends StatefulWidget {
5
+  final WebviewProgressBarController controller;
6
+  final bool autoHide;
7
+  final Color? backgroundColor;
8
+  final Color? color;
9
+  final Animation<Color?>? valueColor;
10
+  final String? semanticsLabel;
11
+  final String? semanticsValue;
12
+  final BorderRadiusGeometry borderRadius;
13
+
14
+  const WebviewProgressBar(
15
+      {super.key,
16
+      required this.controller,
17
+      this.autoHide = true,
18
+      this.backgroundColor,
19
+      this.color,
20
+      this.valueColor,
21
+      this.semanticsLabel,
22
+      this.semanticsValue,
23
+      this.borderRadius = BorderRadius.zero});
24
+
25
+  @override
26
+  State<WebviewProgressBar> createState() => _WebviewProgressBarState();
27
+}
28
+
29
+class _WebviewProgressBarState extends State<WebviewProgressBar> {
30
+  @override
31
+  void initState() {
32
+    super.initState();
33
+    widget.controller.progress.addListener(() {
34
+      setState(() {});
35
+    });
36
+  }
37
+
38
+  @override
39
+  Widget build(BuildContext context) {
40
+    WebviewProgressBarController controller = widget.controller;
41
+    if (controller.progress.value >= 100 && widget.autoHide) {
42
+      return SizedBox();
43
+    }
44
+    return LinearProgressIndicator(
45
+      value: controller.progress.value / 100,
46
+      backgroundColor: widget.backgroundColor,
47
+      color: widget.color,
48
+      valueColor: widget.valueColor,
49
+      semanticsLabel: widget.semanticsLabel,
50
+      semanticsValue: widget.semanticsValue,
51
+      borderRadius: widget.borderRadius,
52
+    );
53
+  }
54
+}
55
+
56
+///Webview进度条控制器
57
+class WebviewProgressBarController {
58
+  ///进度
59
+  ValueNotifier<int>? _progress;
60
+
61
+  ///进度
62
+  ValueNotifier<int> get progress => _progress ??= ValueNotifier(0);
63
+
64
+  ///设置进度
65
+  void setProgress(int value) {
66
+    progress.value = value;
67
+  }
68
+
69
+  void dispose() {
70
+    _progress?.dispose();
71
+    _progress = null;
72
+  }
73
+}

+ 1 - 1
pubspec.lock

@@ -955,7 +955,7 @@ packages:
955 955
     source: hosted
956 956
     version: "2.1.8"
957 957
   pointycastle:
958
-    dependency: transitive
958
+    dependency: "direct main"
959 959
     description:
960 960
       name: pointycastle
961 961
       sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"

+ 1 - 0
pubspec.yaml

@@ -92,6 +92,7 @@ dependencies:
92 92
   image: ^4.2.0
93 93
 
94 94
   encrypt: ^5.0.3
95
+  pointycastle: ^3.9.1
95 96
 
96 97
   retrofit: ^4.4.1
97 98
   json_annotation: ^4.9.0