随机程序的核心就是根据界面选项随机生成密码。

Random

基本上任何语言都会提供一个随机函数,Dart也不例外,在dart:math包中定义了Random类:

/// A generator of random bool, int, or double values.
///
/// The default implementation supplies a stream of pseudo-random bits that are
/// not suitable for cryptographic purposes.
///
/// Use the [Random.secure]() constructor for cryptographic purposes.
abstract class Random {
  /// Creates a random number generator.
  ///
  /// The optional parameter [seed] is used to initialize the
  /// internal state of the generator. The implementation of the
  /// random stream can change between releases of the library.
  external factory Random([int? seed]);

  /// Creates a cryptographically secure random number generator.
  ///
  /// If the program cannot provide a cryptographically secure
  /// source of random numbers, it throws an [UnsupportedError].
  external factory Random.secure();

  /// Generates a non-negative random integer uniformly distributed in the range
  /// from 0, inclusive, to [max], exclusive.
  ///
  /// Implementation note: The default implementation supports [max] values
  /// between 1 and (1<<32) inclusive.
  int nextInt(int max);

  /// Generates a non-negative random floating point value uniformly distributed
  /// in the range from 0.0, inclusive, to 1.0, exclusive.
  double nextDouble();

  /// Generates a random boolean value.
  bool nextBool();
}

有了Random就可以写出随机密码程序了。

_generatePassword

定义一个名叫_generatePassword的接口,随机密码有很多种方法,下面是我写的方法,核心思想就是:

  1. 根据需要引入的元素生成一个足够长的字符串,把这个字符串随机乱序。
  2. 再根据要生成的密码长度生成一个索引链表,把这个索引链表随机乱序。
  3. 遍历索引链表,根据索引取字符串中对应的字符

内容如下:

static const String LowerCase = 'abcdefghijklmnopqistuvwxyz';
static const String UpperCase = 'ABCDEFGHIJKLMNOPQISTUVWXYZ';
static const String ArabicNumeral = '01234567890123456789';
static const String SpeicalCharacter = '!@#%^&*()-+=|[]~<>.';

void _generatePassword() {
    int length = int.parse(_length);
    if (length <= 0 || (!_lowercase && !_uppercase && !_number && !_speical)) {
      return;
    }

    List<int> tmpPassword = [];
    List<int> tmpProp = [];
    List<int> propStr = [];

    Random random = Random(DateTime.now().millisecondsSinceEpoch);

    if (_lowercase) {
      propStr.addAll(LowerCase.runes.toList());
    }
    if (_uppercase) {
      propStr.addAll(UpperCase.runes.toList());
    }
    if (_number) {
      propStr.addAll(ArabicNumeral.runes.toList());
    }
    if (_speical) {
      propStr.addAll(SpeicalCharacter.runes.toList());
    }

    while (propStr.length < length * 2) {
      List<int> tmpList = List.from(propStr);
      propStr.addAll(tmpList);
    }

    propStr.shuffle(random);
    for (int i = 0; i < propStr.length; i++) {
      tmpProp.add(i);
    }
    tmpProp.shuffle(random);
    for (int item in tmpProp.getRange(0, length)) {
      tmpPassword.add(propStr[item]);
    }
    setState(() {
      _password = String.fromCharCodes(tmpPassword);
    });
  }

Random random = Random(DateTime.now().millisecondsSinceEpoch) 使用当前时间做为随机种子。

根据Switch开关的值,来引入对应的密码元素。

runes 是dart中表示utf-32格式字符的编码单元,可以把字符串变成List,有了List就可以使用自带的shuffle接口,shuffle可以把一个List随机打乱顺序。

while (propStr.length < length * 2) 是为了防止引入的元素少于密码生成长度引起的Bug,例如如果用户只引入小写字母来生成长度99的密码,小写字母只有26个长度,所以我们要把小写字母扩展到比99更长。

propStr.shuffle(random) 随机字符串。

tmpProp.shuffle(random) 随机索引。

tmpPassword.add(propStr[item]) 根据索引取字符串中的字符。

setState 把生成的密码放到_password中保存。

onPressed

修改_buttonGenerate接口中的onPressed,点击按钮时,调用_generatePassword接口:

onPressed: () {
  _generatePassword();
},

运行热加载,点击Generate按钮,就可以在文本框中看到生成的随机密码。

在下一切中,我们将学习如何使用剪贴板复制粘贴生成的密码?

0

本文为原创文章,转载请注明出处,欢迎访问作者网站(和而不同)

发表评论

error: Content is protected !!