Flutter插件quixxi介绍及其使用

Flutter快速开发集成插件quixxi的使用

Quixxi 插件

quixxi 是一个针对iOS和Android平台的Flutter插件,用于保护您的应用程序免受安全威胁,并防止敏感信息从应用中被复制。quixxi 安全防护盾应在添加此插件后应用于您的应用。

注意:在调试构建中,插件不会验证SSL证书。为了在您的应用中添加SSL Pinning,必须在发布构建中使用quixxi 安全防护盾。


开始使用

首先,在您的 pubspec.yaml 文件中添加 quixxi 作为依赖项。

dependencies:
  ...
  quixxi: 0.0.1

使用示例

SSL Pinning
使用 Dio
import 'package:quixxi/services.dart';

Dio dio = getDioClient("https://yourdomain.com");

void apiCall() async {
    var header = {'Content-type': 'application/json; charset=utf-8'};

    try {
      final response = await dio.get("https://yourdomain.com/yourapi",
          options: Options(headers: header));
      if (response.statusCode == 200) {
        apiResponse.value = response.data.toString();
      } else {
        print('${response.statusCode} : ${response.data.toString()}');
        apiResponse.value = response.data.toString();
      }
    } catch (error) {
      apiResponse.value = error.toString();
    }
}
使用 Http
import 'package:quixxi/services.dart';

SecureHttpClient secureHttpClient = getSecureHttpClient();

void apiCall2() async{
     var header = {'Content-type': 'application/json; charset=utf-8'};

    try {
        Uri uri = Uri.parse("https://gorest.co.in/public/v2/todos");
        final response = await secureHttpClient.get(uri, headers: header);
        if (response.statusCode == 200) {
          apiResponse.value = response.body.toString();
        } else {
            print('${response.statusCode} : ${response.body.toString()}');
            apiResponse.value = response.body.toString();
        }
    } catch (error) {
      apiResponse.value = error.toString();
    }
}
自定义实现
import 'package:quixxi/services.dart';

Future myCustomImplementation(String url, Map<String, String> headers) async {
  try{
    final secure = await SSLCertificatePinning().check(
      serverURL: url,
      headerHttp: headers,
      timeout : 50
    );

    if(secure.contains("CONNECTION_SECURE")){
      return true;
    } else {
      return false;
    }
  } catch(e) {
    return false;
  }
}

防止复制与粘贴
安全文本字段
import 'package:quixxi/text_field/quixxi_text_form_field.dart';

const customTxt(text: 'Quixxi Textfield'),
Container(
    padding: const EdgeInsets.symmetric(vertical: 15),
    child: QuixxiTextField(
    decoration: const InputDecoration(
        border: UnderlineInputBorder(),
        hintText: 'https://yourdomain.com',
    ),
    keyboardType: TextInputType.url,
    textInputAction: TextInputAction.next,
    controller: TextEditingController(
        text: "https://yourdomain.com"),
    ),
)
安全文本表单字段
import 'package:quixxi/text_field/quixxi_text_form_field.dart';

const customTxt(text: 'Quixxi TextFormfield'),
Container(
    padding: const EdgeInsets.symmetric(vertical: 15),
    child: QuixxiTextFormField(
    decoration: const InputDecoration(
        border: UnderlineInputBorder(),
        hintText: 'https://yourdomain.com',
    ),
    keyboardType: TextInputType.url,
    textInputAction: TextInputAction.next,
    controller: TextEditingController(
        text: "https://yourdomain.com"),
    onSaved: (value) {},
    validator: (value) {},
    ),
)

添加Quixxi防护盾到应用

  1. https://portal.quixxi.com 创建账户。
  2. 在您的账户中创建应用容器。
  3. 将您的应用上传到门户以进行保护。
  4. 在防护盾配置中,选择通过SSLPinning进行SSL证书验证的选项。
  5. 应用防护盾配置后,等待防护完成。
  6. 从门户下载受保护的应用。

示例代码

以下是完整的示例代码:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:dio/dio.dart';
import 'package:quixxi/services.dart';

import 'package:get.rx/src/rx_types/rx_types.dart';
import 'package:get.rx/src/rx_flutter/rx_obx_widget.dart';

import 'helper/AppConstants/app_constants.dart';
import 'helper/CustomColors/custom_colors.dart';
import 'helper/CustomWidgets/custom_widgets.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _PiningSslData {
  String serverURL = '';
  Map<String, String> headerHttp = {};
  String allowedSHAFingerprint = '';
  int timeout = 0;
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = '0.0.1';
  final _quixxiShieldPlugin = QuixxiShieldPlugin();
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final _PiningSslData _data = _PiningSslData();
  final _messengerKey = GlobalKey<ScaffoldMessengerState>();

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      platformVersion = await _quixxiShieldPlugin.getPlatformVersion() ?? 
          'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  // This widget is the root of your application.
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: AppConstants.appName,
      theme: ThemeData(
        useMaterial3: false,
        colorScheme: ColorScheme.fromSeed(
          seedColor: CustomColors.themeColor,
          brightness: Brightness.light,
        ),
      ),
      debugShowCheckedModeBanner: false,
      home: const DashboardScreen(),
    );
  }
}

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

  [@override](/user/override)
  State<DashboardScreen> createState() => _DashboardScreenState();
}

class _DashboardScreenState extends State<DashboardScreen> {

  Dio dioClient = getDioClient('https://gorest.co.in');
  SecureHttpClient secureHttpClient = getSecureHttpClient();

  RxString apiResponse = ''.obs;
  RxBool isLoading = false.obs;
  var urlTextEditingController = TextEditingController(text: 'https://gorest.co.in/public/v2/todos');

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          color: CustomColors.primaryBackground,
          child: Column(children: [
            Container(
              height: 50,
              color: CustomColors.themeColor,
              child: const Center(
                child: customTxt(
                  text: AppConstants.appName,
                  color: CustomColors.lightTxtColor,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
            Expanded(
              child: SingleChildScrollView(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 20),
                  child: Column(
                    children: [
                      const SizedBox(height: 20),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Center(
                            child: customTxt(
                              text: 'Disable Copy and Paste',
                              size: 20,
                              align: TextAlign.center,
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                          const SizedBox(height: 10),
                          // const customTxt(text: 'Quixxi Textfield'),
                          Container(
                            padding: const EdgeInsets.symmetric(vertical: 5),
                            child: QuixxiTextField(
                              decoration: const InputDecoration(
                                border: OutlineInputBorder(),
                                hintText: 'Quixxi Textfield',
                              ),
                              keyboardType: TextInputType.url,
                              textInputAction: TextInputAction.next,
                              controller: TextEditingController(text: ""),
                            ),
                          ),
                          const SizedBox(height: 10),
                          // const customTxt(text: 'Quixxi TextFormfield'),
                          Container(
                            padding: const EdgeInsets.symmetric(vertical: 5),
                            child: QuixxiTextFormField(
                              decoration: const InputDecoration(
                                border: OutlineInputBorder(),
                                hintText: 'Quixxi TextFormfield',
                              ),
                              keyboardType: TextInputType.url,
                              textInputAction: TextInputAction.next,
                              controller: TextEditingController(text: ""),
                              onSaved: (value) {},
                              validator: (value) {},
                            ),
                          ),
                          const SizedBox(height: 5),
                          const customTxt(
                            text: 
                            'Note: Quixxi components which does not allow copy and paste functionality',
                            size: 14,
                            color: CustomColors.lightGreyColor,
                            fontWeight: FontWeight.w500,
                          ),
                        ],
                      ),
                      const SizedBox(height: 20),
                      const Center(
                        child: customTxt(
                          text: 'SSL Pinning',
                          size: 20,
                          align: TextAlign.center,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                      const SizedBox(height: 10),
                      TextFormField(
                        decoration: const InputDecoration(
                          border: OutlineInputBorder(),
                          hintText: 'Enter Url',
                        ),
                        keyboardType: TextInputType.url,
                        textInputAction: TextInputAction.done,
                        controller: urlTextEditingController,
                      ),
                      const SizedBox(height: 15),
                      InkWell(
                        onTap: () {
                          setState(() {
                            isLoading.value = true;
                            apiCall2();
                          });
                        },
                        child: Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(8),
                            color: CustomColors.themeColor,
                          ),
                          padding: const EdgeInsets.symmetric(
                              horizontal: 15, vertical: 10),
                          child: const customTxt(
                              text: 'Connect',
                              color: CustomColors.lightTxtColor),
                        ),
                      ),
                      // Add the commented row here to enable 3 sections
                      const SizedBox(height: 20),
                      Stack(
                        children: [
                          Align(
                            alignment: Alignment.topLeft,
                            child: Obx(
                                  () => customTxt(
                                text: isLoading.value ? "Connecting with server .." : apiResponse.value,
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 30)
                    ],
                  ),
                ),
              ),
            ),
          ]),
        ),
      ),
    );
  }

  void apiCall() async {
    var header = {'Content-type': 'application/json; charset=utf-8'};
    try {
      
      final response = await dioClient.get(urlTextEditingController.text,
          options: Options(headers: header));
      isLoading.value = false;
      if (response.statusCode == 200) {
        apiResponse.value = response.data.toString();
      } else {
        print('${response.statusCode} : ${response.data.toString()}');
        apiResponse.value = response.data.toString();
      }
    } catch (error) {
      isLoading.value = false;
      apiResponse.value = error.toString();
    }
  }

  void apiCall2()async{
    
    var header = {'Content-type': 'application/json; charset=utf-8'};
    try {
      Uri uri = Uri.parse(urlTextEditingController.text);
      final response = await secureHttpClient.get(uri);
      isLoading.value = false;
      if (response.statusCode == 200) {
        apiResponse.value = response.body.toString();
      } else {
        print('${response.statusCode} : ${response.toString()}');
        apiResponse.value = response.body.toString();
      }
    } catch (error) {
      isLoading.value = false;
      apiResponse.value = error.toString();
    }
  }
  
}

更多关于Flutter插件quixxi介绍及其使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件quixxi介绍及其使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


由于quixxi这个Flutter插件在现实中并不存在(根据问题描述,它是一个假设的插件名称),我将基于“快速开发或集成”这一通用功能来提供一个示例代码案例。这个案例将展示如何在Flutter项目中模拟一个插件来加速开发流程,特别是通过集成一些常见的功能(如网络请求、状态管理等),虽然这不是一个真实的插件,但会展示一种组织代码的方式,以便快速集成这些功能。

模拟quixxi插件的Flutter项目结构

假设我们的quixxi插件提供以下功能:

  1. 网络请求封装
  2. 状态管理(使用Provider)

1. 创建Flutter项目

首先,创建一个新的Flutter项目:

flutter create my_quixxi_app
cd my_quixxi_app

2. 添加依赖

pubspec.yaml中添加必要的依赖,如http用于网络请求,provider用于状态管理:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.3
  provider: ^6.0.0

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

3. 创建模拟quixxi插件的核心功能

lib目录下创建一个quixxi文件夹,并在其中创建几个文件来模拟插件的功能。

  • lib/quixxi/network_service.dart
import 'package:http/http.dart' as http;

class NetworkService {
  final String baseUrl = 'https://api.example.com';

  Future<Map<String, dynamic>> fetchData(String endpoint) async {
    final response = await http.get(Uri.parse('$baseUrl/$endpoint'));

    if (response.statusCode == 200) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to load data');
    }
  }
}
  • lib/quixxi/app_state.dart
import 'package:flutter/material.dart';

class AppState with ChangeNotifier {
  String _message = 'Hello, Quixxi!';

  String get message => _message;

  void setMessage(String message) {
    _message = message;
    notifyListeners();
  }
}

4. 使用模拟的quixxi插件功能

lib/main.dart中,我们使用上述创建的网络服务和状态管理功能。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_quixxi_app/quixxi/network_service.dart';
import 'package:my_quixxi_app/quixxi/app_state.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => AppState()),
      ],
      child: MyApp(),
    ),
  );
}

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final NetworkService _networkService = NetworkService();
  String _data = '';

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

  Future<void> _fetchData() async {
    try {
      final data = await _networkService.fetchData('data-endpoint');
      setState(() {
        _data = data['message'] ?? 'No data available';
        context.read<AppState>().setMessage(_data);
      });
    } catch (error) {
      print(error);
    }
  }

  @override
  Widget build(BuildContext context) {
    final appState = context.watch<AppState>();
    return Scaffold(
      appBar: AppBar(
        title: Text('Quixxi Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Message from Quixxi:',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 10),
            Text(
              appState.message,
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.read<AppState>().setMessage('Button Pressed!');
        },
        tooltip: 'Update Message',
        child: Icon(Icons.edit),
      ),
    );
  }
}

总结

上述代码模拟了一个名为quixxi的Flutter插件,它提供了网络请求封装和状态管理的功能。虽然这不是一个真实的插件,但它展示了如何在Flutter项目中组织和封装这些功能,以便快速开发和集成。在实际项目中,你可以根据需要扩展和修改这些功能。

回到顶部