Flutter自动登录插件autologin_web的使用

Flutter自动登录插件autologin_web的使用

autologin_webautologin 包在 Web 平台上的实现。此包已被推荐为受支持的插件,因此你可以在项目中直接使用 autologin,而无需手动将其添加到 pubspec.yaml 文件中。

使用说明

如果你只是想使用 autologin 包的功能,那么你可以直接导入并使用它。但是,如果你想直接使用 autologin_web 包中的某些 API,则需要将其添加到 pubspec.yaml 文件中。

以下是一个完整的示例,展示了如何在 Flutter 应用程序中使用 autologin_web 插件来实现自动登录功能。

import 'dart:async';

import 'package:autologin/autologin.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

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

/// 这个框架只是为了确保 DemoPage 可以显示一个 Snackbar
class DemoFrame extends StatelessWidget {
  const DemoFrame({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Autologin-Plugin 示例应用'),
        ),
        body: const SingleChildScrollView(
          padding: EdgeInsets.symmetric(vertical: 8, horizontal: 24),
          child: Align(
            child: SizedBox(
              width: 400,
              child: DemoPage(),
            ),
          ),
        ),
      ),
    );
  }
}

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

  @override
  State<DemoPage> createState() => _DemoPageState();
}

/// 大多数这些状态字段只是为了调试正在发生的事情
class _DemoPageState extends State<DemoPage> {
  bool? isPlatformSupported;
  String? usernameNote;
  String? passwordNote;
  bool obscurePassword = true;
  final usernameController = TextEditingController();
  final passwordController = TextEditingController();
  String loginToken = 'Loading...';

  @override
  void initState() {
    super.initState();
    unawaited(initPlatformState());
    usernameController.addListener(resetUsernameNote);
    passwordController.addListener(resetPasswordNote);
    AutologinPlugin.setup(
      domain: 'rekire.github.io',
      appId: 'eu.rekisoft.flutter.autologin',
      appName: 'Autologin Demo',
    );
    AutologinPlugin.requestLoginToken().then((value) async {
      if (value != null) {
        setState(() => loginToken = value);
      } else {
        final hasZeroTouchSupport = (await AutologinPlugin.performCompatibilityChecks()).hasZeroTouchSupport;
        setState(() => loginToken = hasZeroTouchSupport ? '这是首次应用启动' : '平台不受支持');
        if (hasZeroTouchSupport) {
          await AutologinPlugin.saveLoginToken('首次启动 ${DateTime.now()}');
        }
      }
    }).onError((error, stackTrace) {
      setState(() => loginToken = error.toString());
    });
  }

  @override
  void dispose() {
    super.dispose();
    usernameController.removeListener(resetUsernameNote);
    passwordController.removeListener(resetPasswordNote);
  }

  // 平台消息是异步的,所以我们初始化在一个异步方法中。
  Future<void> initPlatformState() async {
    final isSupported = await AutologinPlugin.isPlatformSupported;
    setState(() => isPlatformSupported = isSupported);
  }

  void resetUsernameNote() {
    setState(() => usernameNote = null);
  }

  void resetPasswordNote() {
    setState(() => passwordNote = null);
  }

  Future<void> requestCredentials() async {
    final credentials = await AutologinPlugin.requestCredentials();

    if (mounted) {
      setState(() {
        if (credentials?.username != null) {
          usernameController.text = credentials!.username!;
          usernameNote = null;
        } else {
          usernameController.text = '';
          usernameNote = 'API 没有提供用户名';
        }
        if (credentials?.password != null) {
          passwordController.text = credentials!.password!;
          passwordNote = null;
        } else {
          passwordController.text = '';
          passwordNote = 'API 没有提供密码';
        }
      });
    }
  }

  Future<void> saveCredentials() async {
    final success = await AutologinPlugin.saveCredentials(
      Credential(username: usernameController.text, password: passwordController.text, domain: 'rekire.github.io'),
    );

    if (!success && mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('保存凭证失败!'),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        if (isPlatformSupported != true)
          const Padding(
            padding: EdgeInsets.only(bottom: 16),
            child: Text('⚠️ 此浏览器或平台不受支持 ⚠️'),
          ),
        TextFormField(
          controller: usernameController,
          textInputAction: TextInputAction.next,
          autofillHints: const [AutofillHints.username],
          decoration: InputDecoration(
            border: const OutlineInputBorder(),
            labelText: '用户名',
            helperText: usernameNote,
          ),
          onFieldSubmitted: (_) => saveCredentials(),
        ),
        const SizedBox(height: 16),
        TextFormField(
          controller: passwordController,
          obscureText: obscurePassword,
          textInputAction: TextInputAction.send,
          keyboardType: TextInputType.visiblePassword,
          autofillHints: const [AutofillHints.password],
          decoration: InputDecoration(
            border: const OutlineInputBorder(),
            labelText: '密码',
            helperText: passwordNote,
            suffixIcon: IconButton(
              icon: Icon(obscurePassword ? Icons.visibility : Icons.visibility_off),
              onPressed: () {
                setState(() => obscurePassword = !obscurePassword);
              },
              tooltip: obscurePassword ? '显示密码' : '隐藏密码',
            ),
          ),
          onFieldSubmitted: (_) => saveCredentials(),
        ),
        const SizedBox(height: 16),
        FilledButton(
          onPressed: isPlatformSupported == true ? saveCredentials : null,
          child: const Text('保存凭证'),
        ),
        const SizedBox(height: 8),
        OutlinedButton(
          onPressed: () {
            usernameController.text = 'Some-Username';
            passwordController.text = r'Example-P@§$w0rd!';
          },
          child: const Text('输入示例数据'),
        ),
        const SizedBox(height: 8),
        OutlinedButton(
          onPressed: isPlatformSupported == true ? requestCredentials : null,
          child: const Text('请求登录数据'),
        ),
        const SizedBox(height: 8),
        Text('登录令牌: $loginToken'),
      ],
    );
  }
}

代码解释

  1. 导入依赖:

    import 'package:autologin/autologin.dart';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
  2. 主入口点:

    void main() {
      runApp(const DemoFrame());
    }
    
  3. DemoFrame:

    class DemoFrame extends StatelessWidget {
      const DemoFrame({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Autologin-Plugin 示例应用'),
            ),
            body: const SingleChildScrollView(
              padding: EdgeInsets.symmetric(vertical: 8, horizontal: 24),
              child: Align(
                child: SizedBox(
                  width: 400,
                  child: DemoPage(),
                ),
              ),
            ),
          ),
        );
      }
    }
    
  4. DemoPage:

    class DemoPage extends StatefulWidget {
      const DemoPage({super.key});
    
      @override
      State<DemoPage> createState() => _DemoPageState();
    }
    
    class _DemoPageState extends State<DemoPage> {
      // 状态字段
      bool? isPlatformSupported;
      String? usernameNote;
      String? passwordNote;
      bool obscurePassword = true;
      final usernameController = TextEditingController();
      final passwordController = TextEditingController();
      String loginToken = 'Loading...';
    
      @override
      void initState() {
        super.initState();
        unawaited(initPlatformState());
        usernameController.addListener(resetUsernameNote);
        passwordController.addListener(resetPasswordNote);
        AutologinPlugin.setup(
          domain: 'rekire.github.io',
          appId: 'eu.rekisoft.flutter.autologin',
          appName: 'Autologin Demo',
        );
        AutologinPlugin.requestLoginToken().then((value) async {
          if (value != null) {
            setState(() => loginToken = value);
          } else {
            final hasZeroTouchSupport = (await AutologinPlugin.performCompatibilityChecks()).hasZeroTouchSupport;
            setState(() => loginToken = hasZeroTouchSupport ? '这是首次应用启动' : '平台不受支持');
            if (hasZeroTouchSupport) {
              await AutologinPlugin.saveLoginToken('首次启动 ${DateTime.now()}');
            }
          }
        }).onError((error, stackTrace) {
          setState(() => loginToken = error.toString());
        });
      }
    
      @override
      void dispose() {
        super.dispose();
        usernameController.removeListener(resetUsernameNote);
        passwordController.removeListener(resetPasswordNote);
      }
    
      // 初始化平台状态
      Future<void> initPlatformState() async {
        final isSupported = await AutologinPlugin.isPlatformSupported;
        setState(() => isPlatformSupported = isSupported);
      }
    
      // 重置用户名备注
      void resetUsernameNote() {
        setState(() => usernameNote = null);
      }
    
      // 重置密码备注
      void resetPasswordNote() {
        setState(() => passwordNote = null);
      }
    
      // 请求凭证
      Future<void> requestCredentials() async {
        final credentials = await AutologinPlugin.requestCredentials();
    
        if (mounted) {
          setState(() {
            if (credentials?.username != null) {
              usernameController.text = credentials!.username!;
              usernameNote = null;
            } else {
              usernameController.text = '';
              usernameNote = 'API 没有提供用户名';
            }
            if (credentials?.password != null) {
              passwordController.text = credentials!.password!;
              passwordNote = null;
            } else {
              passwordController.text = '';
              passwordNote = 'API 没有提供密码';
            }
          });
        }
      }
    
      // 保存凭证
      Future<void> saveCredentials() async {
        final success = await AutologinPlugin.saveCredentials(
          Credential(username: usernameController.text, password: passwordController.text, domain: 'rekire.github.io'),
        );
    
        if (!success && mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('保存凭证失败!'),
            ),
          );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            // 显示平台支持信息
            if (isPlatformSupported != true)
              const Padding(
                padding: EdgeInsets.only(bottom: 16),
                child: Text('⚠️ 此浏览器或平台不受支持 ⚠️'),
              ),
            // 用户名输入框
            TextFormField(
              controller: usernameController,
              textInputAction: TextInputAction.next,
              autofillHints: const [AutofillHints.username],
              decoration: InputDecoration(
                border: const OutlineInputBorder(),
                labelText: '用户名',
                helperText: usernameNote,
              ),
              onFieldSubmitted: (_) => saveCredentials(),
            ),
            const SizedBox(height: 16),
            // 密码输入框
            TextFormField(
              controller: passwordController,
              obscureText: obscurePassword,
              textInputAction: TextInputAction.send,
              keyboardType: TextInputType.visiblePassword,
              autofillHints: const [AutofillHints.password],
              decoration: InputDecoration(
                border: const OutlineInputBorder(),
                labelText: '密码',
                helperText: passwordNote,
                suffixIcon: IconButton(
                  icon: Icon(obscurePassword ? Icons.visibility : Icons.visibility_off),
                  onPressed: () {
                    setState(() => obscurePassword = !obscurePassword);
                  },
                  tooltip: obscurePassword ? '显示密码' : '隐藏密码',
                ),
              ),
              onFieldSubmitted: (_) => saveCredentials(),
            ),
            const SizedBox(height: 16),
            // 保存凭证按钮
            FilledButton(
              onPressed: isPlatformSupported == true ? saveCredentials : null,
              child: const Text('保存凭证'),
            ),
            const SizedBox(height: 8),
            // 输入示例数据按钮
            OutlinedButton(
              onPressed: () {
                usernameController.text = 'Some-Username';
                passwordController.text = r'Example-P@§$w0rd!';
              },
              child: const Text('输入示例数据'),
            ),
            const SizedBox(height: 8),
            // 请求登录数据按钮
            OutlinedButton(
              onPressed: isPlatformSupported == true ? requestCredentials : null,
              child: const Text('请求登录数据'),
            ),
            const SizedBox(height: 8),
            // 显示登录令牌
            Text('登录令牌: $loginToken'),
          ],
        );
      }
    }
    

更多关于Flutter自动登录插件autologin_web的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自动登录插件autologin_web的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用autologin_web插件来实现自动登录功能的示例代码。autologin_web插件通常用于在Web平台上通过URL参数自动填充登录表单。

首先,确保你已经在pubspec.yaml文件中添加了autologin_web依赖:

dependencies:
  flutter:
    sdk: flutter
  autologin_web: ^最新版本号  # 请替换为实际最新版本号

然后运行flutter pub get来安装依赖。

接下来,让我们编写一个示例应用,展示如何使用autologin_web插件。

main.dart

import 'package:flutter/material.dart';
import 'package:autologin_web/autologin_web.dart';
import 'dart:html' as html;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter AutoLogin Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AutoLoginPage(),
    );
  }
}

class AutoLoginPage extends StatefulWidget {
  @override
  _AutoLoginPageState createState() => _AutoLoginPageState();
}

class _AutoLoginPageState extends State<AutoLoginPage> {
  String _username = '';
  String _password = '';

  @override
  void initState() {
    super.initState();
    _listenForAutoLogin();
  }

  void _listenForAutoLogin() {
    AutoLoginWeb().listen((data) {
      setState(() {
        _username = data?.username ?? '';
        _password = data?.password ?? '';
      });
      print('Auto login data received: ${data?.toString()}');
      // 在这里你可以添加自动登录的逻辑,比如调用登录API
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Auto Login Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextField(
              decoration: InputDecoration(labelText: 'Username'),
              controller: TextEditingController(text: _username),
            ),
            SizedBox(height: 16),
            TextField(
              obscureText: true,
              decoration: InputDecoration(labelText: 'Password'),
              controller: TextEditingController(text: _password),
            ),
            SizedBox(height: 24),
            ElevatedButton(
              onPressed: () {
                // 在这里添加实际的登录逻辑
                print('Logging in with username: $_username, password: $_password');
              },
              child: Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}

说明

  1. 依赖添加:在pubspec.yaml中添加autologin_web依赖。
  2. 监听自动登录数据:在_AutoLoginPageStateinitState方法中,通过AutoLoginWeb().listen来监听URL参数中的自动登录数据。一旦接收到数据,更新UI中的用户名和密码字段。
  3. UI显示:使用TextField来显示和编辑用户名和密码。初始时,这些字段会被自动登录数据填充(如果有的话)。
  4. 登录按钮:点击登录按钮时,可以在控制台打印出用户名和密码,实际项目中应替换为调用登录API的逻辑。

注意事项

  • 确保你的应用运行在Web平台上,因为autologin_web插件只支持Web。
  • 自动登录数据通常通过URL参数传递,例如https://yourapp.com/?username=test&password=1234
  • 出于安全考虑,自动登录功能应谨慎使用,尤其是在生产环境中,避免敏感信息泄露。

希望这个示例代码能帮助你理解如何在Flutter项目中使用autologin_web插件实现自动登录功能。

回到顶部