flutter 项目签名验证原理、签 名验证算法 时间差问题

 

1. Flutter Md5 加密

// 引入所需的库: utf8 用于编码, crypto 用于md5加密
import 'dart:convert';
import 'package:crypto/crypto.dart';

main() {
  // 对"Hello"字符串进行md5加密并打印结果
  print(md5.convert(utf8.encode("Hello")));
}

2. 为什么要签名验证

// 为保证http请求的安全性,需要进行签名验证,以下列出了进行签名验证的几个主要原因:
// 1. 验证请求来源是否合法
// 2. 检查请求参数是否被篡改
// 3. 确保请求的唯一性,防止请求被复制
// 对于需要用户登录后访问的信息,尤其需要进行签名验证来确保数据的安全性。

3. 签名验证实现原理

// 用户登录成功后,服务器会返回包含用户信息及salt的数据
// salt 是在用户注册时随机生成并经md5加密得到的,每个用户的salt都是独一无二的
// 当请求API时,需要在接口中加入sign签名以确保数据的安全性。

// 例如,传统的请求方式是这样的:
传统请求方式

// 而带有签名验证的请求方式则变为:
带签名验证的请求方式

// 签名的生成算法如下:
import 'dart:convert';
import 'package:crypto/crypto.dart';

getSign() {
  Map json = {
    "aid": 1,
    "name": 'zhangsan',
    "age": 20,
    "sex": '男',
    "salt": "xxxewrewqrqrwqrwqrwqr"
  };

  List jsonKeys = json.keys.toList();
  // 对key进行排序
  jsonKeys.sort();

  var str = '';
  // 将排序后的key-value对拼接成字符串
  for (var i = 0; i < jsonKeys.length; i++) {
    str += "${jsonKeys[i]}${json[jsonKeys[i]]}";
  }

  // 将拼接的字符串进行md5加密并打印
  print(md5.convert(utf8.encode(str)));
}

4. 请求接口传入 sign

// 在实际请求接口时,我们需要将生成的sign参数添加到URL中,如:
请求接口带sign

5. 服务器端生成签名验证

// 服务器端需要进行以下步骤来验证客户端传来的sign:
// 1. 获取客户端传来的sign和其他参数
// 2. 使用uid查询数据库,获取当前用户的salt(32位)
// 3. 将URL中的数据和查询到的salt组合成json, 使用同样的算法生成签名
// 4. 比较服务器生成的签名和客户端传来的签名,如果相同则数据未被篡改

6. 请求的唯一性解决方案

// 为了防止请求参数被重复使用,我们需要确保每次的请求都是唯一的。
// 一种常见的做法是在请求参数中加入时间戳,并将其作为请求参数之一,加入到sign的生成算法中。
// 服务器会比较客户端的时间戳和服务器的当前时间,如果两者之间的时间差过大,则请求会被判定为无效。

// 如何解决时间差问题:
// 1. 启动应用时,获取本地时间,然后请求服务器获取其当前时间
// 2. 计算时间差并保存到本地存储
// 3. 每次请求接口时,将本地时间和时间差相加,得到一个更接近服务器时间的时间戳

posted on 2020-03-02 16:00  完美前端  阅读(1059)  评论(0)    收藏  举报

导航