Flutter密码强度评估插件flutter_password_scoring的使用

Flutter密码强度评估插件flutter_password_scoring的使用

描述

该插件的主要目标是支持在Flutter中使用的dart_zxcvbn。此插件提供了两种类型的密码评分处理程序。默认的PasswordScoringHandler不使用隔离(Isolates),因此所有操作都在主线程上运行。这使得它在Web平台上友好(因为在Web平台上Flutter不支持Isolates),但可能会阻塞主线程很长时间。作为替代方案,还有一个基于隔离的处理程序,可以在移动平台或原生平台上使用。

使用

使用PasswordScoringBuilder构建UI。如果您想根据Locale自定义字典和其他选项,请查看示例代码。

/// 请注意,当使用基于隔离的处理程序时,必须将其声明为`final`状态,以确保在每次调用[build]时不被重新创建。
final handler = kIsWeb
    ? PasswordScoringHandler()
    : PasswordScoringIsolateHandler();

PasswordScoringBuilder(
  handler: handler,
  loadingPlaceholder: const Center(
    child: CircularProgressIndicator(),
  ),
  builder: (
    BuildContext context,
    Result? data,
    PasswordScoringHandler handler,
  ) {
  /// 每次用户输入密码更改时调用[handler.update]
  return Placeholder();
  },
);

相关包

包名 详情
dart_zxcvbn README
dart_zxcvbn_language_common README
dart_zxcvbn_language_en README
dart_zxcvbn_language_pl README
flutter_password_scoring README

许可证


示例代码

import 'dart:isolate';

import 'package:dart_zxcvbn/dart_zxcvbn.dart';
import 'package:dart_zxcvbn_language_common/dart_zxcvbn_language_common.dart';
import 'package:dart_zxcvbn_language_en/dart_zxcvbn_language_en.dart';
import 'package:dart_zxcvbn_language_pl/dart_zxcvbn_language_pl.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_password_scoring/flutter_password_scoring.dart';

import 'results_table.dart';

// 这个示例将使用所有当前可用的语言包
final langCommon = LanguageCommon();
final langEn = LanguageEn();
final langPl = LanguagePl();

const List<Locale> supportedLocales = [
  Locale('en'),
  Locale('pl'),
];

/// 此函数将根据提供的[Locale]返回[Options]。
Options getLocaleOptions([Locale? locale]) => Options(
      dictionary: Dictionary.merge([
        langCommon.dictionary,
        if (locale?.languageCode == 'en') langEn.dictionary,
        if (locale?.languageCode == 'pl') langPl.dictionary,
      ]),
      graphs: locale?.languageCode == 'en'
          ? langEn.adjacencyGraphs
          : locale?.languageCode == 'pl'
              ? langPl.adjacencyGraphs
              : langCommon.adjacencyGraphs,
      translations: locale?.languageCode == 'en'
          ? langEn.translations
          : locale?.languageCode == 'pl'
              ? langPl.translations
              : langCommon.translations,
    );

/// 此实现是[Iso]处理程序,它会根据提供的[Locale]更新[dart_zxcvbn]选项。
///
/// 有关更多信息,请参阅[PasswordScoringIsolateHandler]默认实现[defaultIsolateHandler]。
Future<void> localeAwareHandler(SendPort sendPort) async {
  ReceivePort receivePort = ReceivePort();
  sendPort.send(receivePort.sendPort);

  zxcvbn.setOptions(getLocaleOptions());

  // 用于刷新上次密码响应,当locale变化时
  ScoringRequest? lastRequest;

  await for (var message in receivePort) {
    if (message is Locale) {
      zxcvbn.setOptions(getLocaleOptions(message));
    } else if (message is ScoringRequest) {
      lastRequest = message;
    }

    if (lastRequest != null) {
      final Result result = zxcvbn(
        lastRequest.password,
        options: lastRequest.options,
        userInputs: lastRequest.userInputs,
      );
      sendPort.send(result);
    }
  }
}

/// 此[Iso]初始化回调实现根据提供的[Locale]更新[dart_zxcvbn]选项。
void localeAwareInit(Locale? locale) {
  zxcvbn.setOptions(
    getLocaleOptions(locale),
  );
}

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  [@override](/user/override)
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  Locale locale = supportedLocales.first;
  List<String> userInputs = [];

  late final PasswordScoringHandler handler;

  [@override](/user/override)
  void initState() {
    super.initState();

    handler = kIsWeb
        ? PasswordScoringHandler(onInit: localeAwareInit)
        : PasswordScoringIsolateHandler(handler: localeAwareHandler);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    const seedColor = Color.fromARGB(255, 130, 0, 169);

    final lightThemeData = ThemeData(
      useMaterial3: true,
      brightness: Brightness.light,
      colorSchemeSeed: seedColor,
    );
    final darkThemeData = ThemeData(
      useMaterial3: true,
      brightness: Brightness.dark,
      colorSchemeSeed: seedColor,
    );

    const fieldInsets = EdgeInsets.symmetric(
      horizontal: 0,
      vertical: 16,
    );

    return MaterialApp(
      darkTheme: darkThemeData,
      theme: lightThemeData,
      locale: locale,
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: supportedLocales,
      home: Scaffold(
        body: Padding(
          padding: const EdgeInsets.all(32.0),
          child: Center(
            child: ConstrainedBox(
              constraints: const BoxConstraints(maxWidth: 600),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Container(
                    padding: fieldInsets,
                    child: TextField(
                      onChanged: (String value) {
                        setState(() {
                          userInputs = value.split(',');
                        });
                      },
                      decoration: const InputDecoration(
                        labelText: 'User inputs',
                        helperText: 'Comma separated list of user inputs',
                        border: OutlineInputBorder(),
                      ),
                    ),
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    mainAxisSize: MainAxisSize.max,
                    children: [
                      Expanded(
                        child: DropdownMenu<Locale>(
                          initialSelection: locale,
                          label: const Text('Locale'),
                          expandedInsets: fieldInsets,
                          onSelected: (Locale? value) {
                            if (value == null) return;

                            setState(() {
                              locale = value;
                            });
                          },
                          dropdownMenuEntries: supportedLocales
                              .map((Locale value) => DropdownMenuEntry<Locale>(
                                  value: value, label: value.languageCode))
                              .toList(),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  PasswordScoringBuilder(
                    handler: handler,
                    loadingPlaceholder: const CircularProgressIndicator(),
                    builder: (
                      BuildContext context,
                      Result? data,
                      PasswordScoringHandler handler,
                    ) {
                      return Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          TextField(
                            onChanged: (String password) {
                              handler.update(
                                password,
                                userInputs: userInputs,
                              );
                            },
                            decoration: const InputDecoration(
                              labelText: 'Password',
                              border: OutlineInputBorder(),
                            ),
                          ),
                          const SizedBox(height: 32),
                          if (data != null) ResultTable(result: data),
                        ],
                      );
                    },
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter密码强度评估插件flutter_password_scoring的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter密码强度评估插件flutter_password_scoring的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_password_scoring 是一个用于评估密码强度的 Flutter 插件。它可以帮助你根据一定的规则(如长度、字符种类等)来评估用户输入的密码强度,并返回一个评分或提示。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 flutter_password_scoring 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_password_scoring: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装插件。

使用插件

在你的 Flutter 项目中,你可以使用 flutter_password_scoring 来评估密码强度。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:flutter_password_scoring/flutter_password_scoring.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PasswordStrengthScreen(),
    );
  }
}

class PasswordStrengthScreen extends StatefulWidget {
  [@override](/user/override)
  _PasswordStrengthScreenState createState() => _PasswordStrengthScreenState();
}

class _PasswordStrengthScreenState extends State<PasswordStrengthScreen> {
  String _password = '';
  PasswordStrength _strength = PasswordStrength.weak;

  void _onPasswordChanged(String password) {
    setState(() {
      _password = password;
      _strength = PasswordScoring.evaluateStrength(password);
    });
  }

  String _getStrengthText(PasswordStrength strength) {
    switch (strength) {
      case PasswordStrength.weak:
        return 'Weak';
      case PasswordStrength.fair:
        return 'Fair';
      case PasswordStrength.good:
        return 'Good';
      case PasswordStrength.strong:
        return 'Strong';
      default:
        return 'Weak';
    }
  }

  Color _getStrengthColor(PasswordStrength strength) {
    switch (strength) {
      case PasswordStrength.weak:
        return Colors.red;
      case PasswordStrength.fair:
        return Colors.orange;
      case PasswordStrength.good:
        return Colors.lightGreen;
      case PasswordStrength.strong:
        return Colors.green;
      default:
        return Colors.red;
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Password Strength Checker'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              obscureText: true,
              onChanged: _onPasswordChanged,
              decoration: InputDecoration(
                labelText: 'Password',
                border: OutlineInputBorder(),
              ),
            ),
            SizedBox(height: 20),
            Text(
              'Password Strength: ${_getStrengthText(_strength)}',
              style: TextStyle(
                color: _getStrengthColor(_strength),
                fontSize: 18,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部