Flutter 项目实战 网络请求MD5+时间戳+验证签名 十一
Posted xmiaoshen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 项目实战 网络请求MD5+时间戳+验证签名 十一相关的知识,希望对你有一定的参考价值。
/ MD5 ( Message-Digest Algorithm ) /
MD5消息摘要算法 , 由MD4、MD3、MD2 改进而来,主要增强算法复杂度和不可逆性 , 密码散列函数 。可以生成一个128位(16个字符(BYTES))的散列值(hash value), 128位的MD5散列被表示为32位十六进制数字 , 确保信息完整一致传输 。可以被破解 , 证实MD5算法无法防止碰撞攻击,因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。对于高度安全性的资料 可以使用 SHA-2 算法 。
/ MD5验证签名 /
密钥可以是任意字符串 , 为了增加破解难度 ,客户端和服务端协商的密钥字符串长度尽量要长 。密钥分别在客户端和服务端保存了一份 。客户端获取时间戳、签名和其他必备参数添加到Map集合中 , 然后对Map集合按Key的首字母顺序排列 , 最好遍历Map集合分别获取key和value循环拼接到赋值给一个字符串变量 。通过遍历集合拼接好的字符串末尾拼接协商的密钥 , 将这个拼接好的字符串通过Md5算法加密 。
/ 时间戳防止重复提交 /
Redis (REmote DIctionary Server) 是 key-value 存储系统,是跨平台的非关系型数据库。开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库 。Redis 通常被称为数据结构服务器,因为值(value)可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。
获取上次存储到redius的时间戳和客户端发起请求到时间戳进行对比 , 以此来校验时间戳是否重复 、session是否超时 。
/ Map集合按Key的首字母排序 /
排序算法
排序后
/ MD5加密 /
获取 android 平台密钥签名
打开 Flutter工程 下Android文件 配置密钥 到 gradle.properties (Project Properties)
build.gradle 下配置 flutterMd5Key (对应的别名 : FLUTTER_MD5_KEY)
Android Studio 菜单栏通过 build -> make project 编译项目后在BuildConfig文件下生成 静态的不可变的密钥 FLUTTER_MD5_KEY 。
Flutter 与 Android原生建立通信 ,获取密钥 (FLUTTER_MD5_KEY)
在main函数调用里面需要调用 函数 ensuerInitialized (
WidgetFlutterBinding
用于与 Flutter 引擎进行交互 ) , Flutter获取Android原生交换返回的密钥 FLUTTER_MD5_KEY 添加到 参与签名的Map集合中 , 最后遍历集合拼接签名参数进行Md5加密 。WidgetsFlutterBinding.ensureInitialized();
pubspec.yaml 文件下配置 common_utils 依赖库 (包含了md5加密的工具类)
import 'package:common_utils/common_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; void main() async ///时间戳 var _milSec = (DateTime.now().millisecondsSinceEpoch / 100).toStringAsFixed(0); /// Map 集合 Map<String, dynamic> encryMap = 'g_key': 'g_value', 'b_key': 'b_value', 'e_key': 'e_value', 'a_key': 'a_value', 'mil_sec':'$_milSec' ; /// Map 集合的键存储到 List 集合 List<String> keys = encryMap.keys.toList(); /// Map 集合按照 key 排序 keys.sort((a, b) List<int> al = a.codeUnits; List<int> bl = b.codeUnits; for (int i = 0; i < al.length; i++) if (bl.length <= i) return 1; if (al[i] > bl[i]) return 1; else if (al[i] < bl[i]) return -1; return 0; ); print('排序后的key $keys \\n'); var _signStr = ''; keys.asMap().forEach((k, v) encryMap.forEach((pk, pv) if (v == pk) print('键集合keys索引$k 集合encryMap键$pk 集合encryMap值$pv'); _signStr += pk + "=" + '$pv ?? ''' + "&"; ); ); WidgetsFlutterBinding.ensureInitialized(); var _flutterNativeKeyValue = await FlutterPlugins.senData('flutterSendNavData'); _signStr = _signStr.substring(0, _signStr.length - 1) + _flutterNativeKeyValue; ///拼接好的签名参数 print('拼接好的签名参数 $_signStr'); var _encMdeSignStr=EncryptUtil.encodeMd5(_signStr); print('Md5签名:$_encMdeSignStr'); class FlutterPlugins static const MethodChannel channel = const MethodChannel("com.flutter.native.key"); static Future<String> senData(String result) async return await channel.invokeMethod("flutterNativeKey", result);
MD5在线加密 对依赖库的签名算法进行验证
获取 ios 平台密钥签名
使用Xcode工具打开Flutter工程里面的IOS文件夹 , 找到 AppDelegate.swift 文件打开 , 配置密钥完成Flutter从IOS获取密钥的过程
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate var methodChannel:FlutterMethodChannel? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool GeneratedPluginRegistrant.register(with: self) ///Flutter和IOS通信的唯一标识符 com.flutter.native.key let vc = self.window.rootViewController as! FlutterViewController self.methodChannel = FlutterMethodChannel.init(name: "com.flutter.native.key", binaryMessenger: vc.binaryMessenger) self.methodChannel!.setMethodCallHandler (call , result) in ///Flutter调用的函数 if(call.method == "flutterNativeKey") ///密钥 result("qazwsxedcrfvtgbyhnujmikolp0987654321"); return super.application(application, didFinishLaunchingWithOptions: launchOptions)
xcode控制台输出的加密参数
/ 调用so文件 /
在当前工程目录下 用这个命令创建flutter工程 native_add
flutter create --platforms=android,ios --template=plugin native_add
在创建的natvie_add工程里面的 ios 文件夹下 Classes 文件夹里面创建 native_add.cpp 文件
native_add.cpp文件里面配置密钥
#include <stdint.h> #include <string.h> #define DART_API extern "C" __attribute__((visibility("default"))) __attribute__((used)) DART_API const char *greetString(const char *platform) char _platform[]="android"; if(strcmp(_platform,platform)==0) return "androidqazwsxedcrfvtgbyhnujmikolp0987654321"; return "iosdqazwsxedcrfvtgbyhnujmikolp0987654321";
在创建的natvie_add工程里面的 Android 文件夹下 创建 CMakeLists.txt 文件用来定义如何编译源文件 , 添加
externalNativeBuild
到android/build.gradle
native_add 工程 pubspec.yaml 文件下配置ffi依赖库 并完成依赖加载
native_add.dart 文件里面 导入ffi 依赖 , Android平台加载libnative_add.so库 ,工程编译后会生成.so库文件 (build/native_add/intermediates/cmake/debug/obj路径下)
运行工程查看从 native_add.cpp 获取到的密钥
以上是关于Flutter 项目实战 网络请求MD5+时间戳+验证签名 十一的主要内容,如果未能解决你的问题,请参考以下文章