Flutter OAuth2客户端认证插件flutter_oauth2_client的使用

Flutter OAuth2 客户端认证插件 flutter_oauth2_client 的使用

简介

flutter_oauth2_client 是一个用于处理 OAuth2 认证流程的 Flutter 插件项目。

开始使用

示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_oauth2_client 进行 OAuth2 认证和登出操作。

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('OAuth2 Client Example')),
        body: Center(
          child: OAuth2ClientExample(),
        ),
      ),
    );
  }
}

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

class _OAuth2ClientExampleState extends State<OAuth2ClientExample> {
  String _idTokenString = '';

  Future<void> authenticate() async {
    try {
      var tokenResponse = await FlutterOAuth2Client.authenticate(
        uri: Uri.parse('http://localhost:8080/auth/realms/aether-passport'),
        clientId: 'aether-billing',
        scopes: ['email', 'profile'],
      );

      setState(() {
        _idTokenString = tokenResponse.idTokenString;
      });
    } catch (e) {
      print('Error during authentication: $e');
    }
  }

  Future<void> logout() async {
    try {
      Uri baseUri = Uri(
        scheme: Uri.base.scheme,
        host: Uri.base.host,
        port: Uri.base.port,
      );

      await FlutterOAuth2Client.logout(
        uri: Uri.parse('http://localhost:8080/auth/realms/aether-passport'),
        idTokenString: _idTokenString, // mobile only
        redirectString: baseUri.toString(), // web only
      );
    } catch (e) {
      print('Error during logout: $e');
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
          onPressed: authenticate,
          child: Text('Authenticate'),
        ),
        SizedBox(height: 20),
        ElevatedButton(
          onPressed: logout,
          child: Text('Logout'),
        ),
        SizedBox(height: 20),
        Text(_idTokenString.isEmpty ? '' : 'ID Token: $_idTokenString'),
      ],
    );
  }
}

说明

  1. 导入依赖:

    • 首先确保在你的 pubspec.yaml 文件中添加了 flutter_oauth2_client 依赖。
    dependencies:
      flutter:
        sdk: flutter
      flutter_oauth2_client: ^x.x.x # 替换为最新版本号
    
  2. 初始化应用:

    • main 函数中启动应用,并设置初始路由。
    void main() {
      runApp(MyApp());
    }
    
  3. 创建主界面:

    • 创建一个 MaterialApp,并设置初始页面为包含认证和登出按钮的 Scaffold
    class MyApp extends StatelessWidget {
      [@override](/user/override)
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: Text('OAuth2 Client Example')),
            body: Center(
              child: OAuth2ClientExample(),
            ),
          ),
        );
      }
    }
    
  4. 实现认证逻辑:

    • 使用 FlutterOAuth2Client.authenticate 方法进行 OAuth2 认证。该方法返回一个 tokenResponse 对象,其中包含了 ID Token 字符串。
    Future<void> authenticate() async {
      try {
        var tokenResponse = await FlutterOAuth2Client.authenticate(
          uri: Uri.parse('http://localhost:8080/auth/realms/aether-passport'),
          clientId: 'aether-billing',
          scopes: ['email', 'profile'],
        );
    
        setState(() {
          _idTokenString = tokenResponse.idTokenString;
        });
      } catch (e) {
        print('Error during authentication: $e');
      }
    }
    
  5. 实现登出逻辑:

    • 使用 FlutterOAuth2Client.logout 方法进行登出操作。该方法需要传入 ID Token 字符串(移动设备)或重定向字符串(Web 平台)。
    Future<void> logout() async {
      try {
        Uri baseUri = Uri(
          scheme: Uri.base.scheme,
          host: Uri.base.host,
          port: Uri.base.port,
        );
    
        await FlutterOAuth2Client.logout(
          uri: Uri.parse('http://localhost:8080/auth/realms/aether-passport'),
          idTokenString: _idTokenString, // mobile only
          redirectString: baseUri.toString(), // web only
        );
      } catch (e) {
        print('Error during logout: $e');
      }
    }
    
  6. UI 组件:

    • 创建两个按钮,分别用于触发认证和登出操作。
    [@override](/user/override)
    Widget build(BuildContext context) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: authenticate,
            child: Text('Authenticate'),
          ),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: logout,
            child: Text('Logout'),
          ),
          SizedBox(height: 20),
          Text(_idTokenString.isEmpty ? '' : 'ID Token: $_idTokenString'),
        ],
      );
    }
    

更多关于Flutter OAuth2客户端认证插件flutter_oauth2_client的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter OAuth2客户端认证插件flutter_oauth2_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_oauth2_client 是一个用于在 Flutter 应用中实现 OAuth2 客户端认证的插件。它简化了与 OAuth2 提供者的交互,帮助你轻松获取访问令牌并进行 API 调用。

以下是如何使用 flutter_oauth2_client 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 flutter_oauth2_client 依赖:

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

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

2. 导入库

在需要使用 OAuth2 客户端认证的文件中导入库:

import 'package:flutter_oauth2_client/flutter_oauth2_client.dart';

3. 创建 OAuth2Client 实例

创建一个 OAuth2Client 实例,配置 OAuth2 提供者的详细信息:

final oauth2Client = OAuth2Client(
  authorizeUrl: 'https://your-oauth-provider.com/authorize', // 授权 URL
  tokenUrl: 'https://your-oauth-provider.com/token',         // 令牌 URL
  redirectUri: 'com.example.app://oauth2redirect',           // 重定向 URI
  clientId: 'your-client-id',                                // 客户端 ID
  clientSecret: 'your-client-secret',                        // 客户端密钥
  customUriScheme: 'com.example.app',                        // 自定义 URI 方案
);

4. 发起授权请求

使用 oauth2Client 实例发起授权请求:

Future<void> authenticate() async {
  try {
    final tokenResponse = await oauth2Client.getTokenWithAuthCodeFlow();
    print('Access Token: ${tokenResponse.accessToken}');
    print('Refresh Token: ${tokenResponse.refreshToken}');
    print('Expires In: ${tokenResponse.expiresIn}');
  } catch (e) {
    print('Error during authentication: $e');
  }
}

5. 使用访问令牌调用 API

获取访问令牌后,你可以使用它来调用受保护的 API:

Future<void> fetchData(String accessToken) async {
  final response = await http.get(
    Uri.parse('https://api.example.com/data'),
    headers: {
      'Authorization': 'Bearer $accessToken',
    },
  );

  if (response.statusCode == 200) {
    print('Data: ${response.body}');
  } else {
    print('Failed to load data: ${response.statusCode}');
  }
}

6. 处理重定向

确保你的应用能够处理 OAuth2 重定向。在 AndroidManifest.xmlInfo.plist 中配置相应的意图过滤器。

Android:

android/app/src/main/AndroidManifest.xml 中添加以下内容:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="com.example.app" />
</intent-filter>

iOS:

ios/Runner/Info.plist 中添加以下内容:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>com.example.app</string>
        </array>
    </dict>
</array>

7. 刷新令牌

如果需要刷新令牌,可以使用 refreshToken 方法:

Future<void> refreshToken() async {
  try {
    final tokenResponse = await oauth2Client.refreshToken(refreshToken);
    print('New Access Token: ${tokenResponse.accessToken}');
    print('New Refresh Token: ${tokenResponse.refreshToken}');
    print('New Expires In: ${tokenResponse.expiresIn}');
  } catch (e) {
    print('Error during token refresh: $e');
  }
}

8. 处理错误

在实际应用中,务必处理各种可能的错误,例如网络错误、令牌过期等。

完整示例

以下是一个完整的示例,展示了如何使用 flutter_oauth2_client 进行 OAuth2 客户端认证:

import 'package:flutter/material.dart';
import 'package:flutter_oauth2_client/flutter_oauth2_client.dart';
import 'package:http/http.dart' as http;

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

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

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

class _OAuth2DemoState extends State<OAuth2Demo> {
  final oauth2Client = OAuth2Client(
    authorizeUrl: 'https://your-oauth-provider.com/authorize',
    tokenUrl: 'https://your-oauth-provider.com/token',
    redirectUri: 'com.example.app://oauth2redirect',
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    customUriScheme: 'com.example.app',
  );

  String _accessToken = '';

  Future<void> authenticate() async {
    try {
      final tokenResponse = await oauth2Client.getTokenWithAuthCodeFlow();
      setState(() {
        _accessToken = tokenResponse.accessToken;
      });
      print('Access Token: $_accessToken');
    } catch (e) {
      print('Error during authentication: $e');
    }
  }

  Future<void> fetchData() async {
    if (_accessToken.isEmpty) {
      print('No access token available.');
      return;
    }

    final response = await http.get(
      Uri.parse('https://api.example.com/data'),
      headers: {
        'Authorization': 'Bearer $_accessToken',
      },
    );

    if (response.statusCode == 200) {
      print('Data: ${response.body}');
    } else {
      print('Failed to load data: ${response.statusCode}');
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('OAuth2 Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: authenticate,
              child: Text('Authenticate'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: fetchData,
              child: Text('Fetch Data'),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部