Flutter(六)| 随机密码
随机程序的核心就是根据界面选项随机生成密码。
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的接口,随机密码有很多种方法,下面是我写的方法,核心思想就是:
- 根据需要引入的元素生成一个足够长的字符串,把这个字符串随机乱序。
- 再根据要生成的密码长度生成一个索引链表,把这个索引链表随机乱序。
- 遍历索引链表,根据索引取字符串中对应的字符
内容如下:
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