Flutter 项目实战 网络请求MD5+时间戳+验证签名 十一

/ MD5 ( Message-Digest Algorithm ) /

        MD5消息摘要算法 , 由MD4、MD3、MD2 改进而来,主要增强算法复杂度和不可逆性 , 密码散列函数 。可以生成一个128位(16个字符(BYTES))的散列值(hash value), 128位的MD5散列被表示为32位十六进制数字 , 确保信息完整一致传输 。可以被破解 , 证实MD5算法无法防止碰撞攻击,因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。对于高度安全性的资料 可以使用 SHA-2 算法 。

MD5在线加密 / MD5免费解密 /  MD5付费解密

/  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的首字母排序 / 

DartPad

排序算法

排序后 

 / 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 获取到的密钥

下载案例

  • 165
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Flutter 中进行网络请求可以使用 `http` 或者 `dio` 等第三方库。 #### 使用 http 首先,在 `pubspec.yaml` 文件中添加依赖: ``` dependencies: http: ^0.13.3 ``` 然后,在需要进行网络请求的地方引入 `http` 库: ```dart import 'package:http/http.dart' as http; ``` 接下来,可以使用 `http.get` 或者 `http.post` 方法进行 GET 或者 POST 请求。例如,使用 GET 方法请求一个 JSON 数据: ```dart Future<void> fetchAlbum() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1')); if (response.statusCode == 200) { // 请求成功,处理响应数据 print(response.body); } else { // 请求失败,处理错误信息 print('请求失败,状态码为 ${response.statusCode}'); } } ``` #### 使用 dio 首先,在 `pubspec.yaml` 文件中添加依赖: ``` dependencies: dio: ^4.0.0 ``` 然后,在需要进行网络请求的地方引入 `dio` 库: ```dart import 'package:dio/dio.dart'; ``` 接下来,可以使用 `Dio` 实例进行 GET 或者 POST 请求。例如,使用 GET 方法请求一个 JSON 数据: ```dart Future<void> fetchAlbum() async { final dio = Dio(); final response = await dio.get('https://jsonplaceholder.typicode.com/albums/1'); if (response.statusCode == 200) { // 请求成功,处理响应数据 print(response.data); } else { // 请求失败,处理错误信息 print('请求失败,状态码为 ${response.statusCode}'); } } ``` 以上就是 Flutter 中进行网络请求的基本方法。需要注意的是,网络请求需要在异步环境下进行,因此需要使用 `async/await` 或者 `Future.then` 等方法处理异步操作。同时,还需要处理请求成功和请求失败的情况,以及错误信息的展示和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️ 邪神

你自己看着办,你喜欢打赏我就赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值