Flutter安全保护插件aegis_flutter_sdk的使用
Flutter安全保护插件aegis_flutter_sdk的使用
项目介绍
Aegis(读音/ˈiːdʒɪs/) 是腾讯云监控团队提供的前端监控 SDK,涵盖了错误监控,资源测速(img, script, css),接口测速,页面性能(首屏时间)。无需侵入代码,只需引入 SDK 即可自动完成所有监控上报。
在使用 aegis 时无需在业务代码中打点或者做任何其他操作,可以做到与业务代码充分解耦。aegis 将会自动监控前端错误,在错误发生时上报错误的具体情况,帮助您快速定位问题。当您开启资源测速时,aegis 将会自动监听页面资源加载情况(耗费时长、成功率等),并在不影响前端性能的前提下收集前端的性能数据,帮助您快速定位性能短板,提升用户体验。
使用本 SDK 需要配合使用腾讯云前端性能监控 RUM 平台。
快速上手
- 前往腾讯云前端性能监控 RUM 平台。
- 申请项目,申请完成后得到
上报 id
,id 在 SDK 初始化的时候会使用。
Aegis SDK 在上报所有数据时都会带上 上报 id
,后端服务将根据 上报 id
辨别数据来自哪一个项目,因此,Aegis 建议为每一个项目都单独申请一个 id,如果一个项目下有多个页面,还可以为每一个页面都申请一个项目 id,方便单独查看每一个页面的 PV、错误率、请求错误率等数据。
支持的特性
特性 | Android | iOS | Web |
---|---|---|---|
普通日志上报 | ✅ | ✅ | ✅ |
错误日志上报 | ✅ | ✅ | ✅ |
白名单日志上报 | ✅ | ✅ | ✅ |
自定义事件上报 | ✅ | ✅ | ✅ |
自定义测速 | ✅ | ✅ | ✅ |
页面加载速度自动测速 | ✅ | ✅ | ✅ |
离线日志 | |||
Http接口测速 | |||
钩子函数 |
发布
运行 dry-run
命令以查看是否都准备 OK 了:
flutter packages pub publish --dry-run
运行 publish
命令正式发布:
flutter packages pub publish
使用SDK
依赖引入
在 Flutter SDK 项目中加入依赖:
dependencies:
...
aegis_flutter_sdk:
初始化实例
import 'package:aegis_flutter_sdk/aegis_flutter_sdk.dart'
final aegis = Aegis(
Config(
id: 'xxxxx',
uin: 'xxxxx',
),
);
日志上报
创建完 Aegis 实例之后,就可以开心的上报日志啦 🥰,日志上报同样简单:
/// aegis.info支持任意类型的参数,包括map, list, string, int等。 如果是object对象,务必提供“toJson方法”
/// 同时可以指定ext1/ext2/ext3(一个或多个)特定参数
aegis.info(
'我是一条白名单上报的信息,只有在白名单中的用户才会上报哟。你可以在开发者平台把老板、产品、测试统统都加进白名单中。'
);
aegis.info(
'我是一条白名单上报的信息,只有在白名单中的用户才会上报哟。你可以在开发者平台把老板、产品、测试统统都加进白名单中。',
ext1: 'xxx',
ext1: 'xxx',
ext1: 'xxx'
);
/// aegis.infoAll支持任意类型的参数,包括map, list, string, int等。 如果是object对象,务必提供“toJson方法”
/// 同时可以指定ext1/ext2/ext3(一个或多个)特定参数
aegis.infoAll(
'我是一条普通的信息,如果上报量很大的话请谨慎使用哟。'
);
aegis.infoAll(
'我是一条普通的信息,如果上报量很大的话请谨慎使用哟。',
ext1: 'xxx',
ext1: 'xxx',
ext1: 'xxx'
);
/// aegis.report支持任意类型的参数,包括map, list, string, int等。 如果是object对象,务必提供“toJson方法”
/// 同时可以指定ext1/ext2/ext3(一个或多个)特定参数
aegis.report(
'error'
)
aegis.report(
'error',
ext1: 'xxx',
ext1: 'xxx',
ext1: 'xxx'
)
aid
Aegis SDK 为每个用户设备分配的唯一标示,会存储在客户端里,用来区分用户,计算 UV 等。aid 只有用户删除 app 才会更新。
算法如下:
void setAid() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? aid = prefs.getString('AEGIS_ID');
if (aid != null) {
bean['aid'] = aid;
config.setAid(aid);
} else {
aid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.replaceAllMapped(RegExp(r"[xy]"), (match) {
int r = Random().nextInt(16);
int v = match[0] == 'x' ? r : (r & 0x3) | 0x8;
return v.toRadixString(16);
});
prefs.setString('AEGIS_ID', aid);
bean['aid'] = aid;
config.setAid(aid);
}
}
实例方法
Aegis 实例暴露接口简单实用,目前 Aegis 实例有以下方法供您使用:
setConfig
info
infoAll
report
error
reportEvent
reportTime
time
timeEnd
setConfig
该方法用来修改实例配置,比如下面场景:
import 'package:aegis_flutter_sdk/aegis_flutter_sdk.dart'
final aegis = Aegis(
Config(
id: 'xxxxx',
uin: 'xxxxx',
),
);
很多情况下,并不能一开始就获取到用户的 uin
,而等获取到用户的 uin
才开始实例化 Aegis,如果这期间发生了错误 Aegis 将监听不到。uin
的设置可以在获取到用户的时候:
final aegis = Aegis(
Config(
id: 'xxxxx',
uin: 'xxxxx',
),
);
// 拿到uin之后...
aegis.setConfig({
uin: 'yyyyyyy'
})
setConfig 支持传入的参数包括 uin
, aid
, version
, ext1
, ext2
, ext3
info、infoAll、report
这三个方法是 Aegis 提供的主要上报手段。
aegis.info('上报一条白名单日志,这两种情况这条日志才会报到后台:1、打开页面的用户在名单中;2、对应的页面发生了错误认真脸');
aegis.infoAll('上报了一条日志,该上报与 info 唯一的不同就在于,所有用户都会上报');
aegis.report('error');
如上接口均可添加可选参数 `ext1`/`ext2`/`ext3` 指定具体的扩展参数
reportEvent
该方法可用来上报自定义事件,平台将会自动统计上报事件的各项指标,诸如:PV、UV、平台分布等…
aegis.reportEvent('XXX请求成功');
reportTime
该方法可用来上报自定义测速,例如:
// 假如‘onload’的时间是1s
aegis.reportTime('onLoad', 1000);
// 或者如果需要使用额外参数,可以传入对象类型参数,ext1,ext2,ext3 会覆盖默认值:
aegis.reportTime('onLoad', 1000,
ext1: 'ext1', ext2: 'ext2', ext3: 'ext3', from: '');
time、timeEnd
该方法同样可用来上报自定义测速,适用于两个时间点之间时长的计算并上报,例如:
aegis.time('complexOperation');
/**
* .
* .
* 做了很久的复杂操作之后。。。
* .
* .
*/
aegis.timeEnd('complexOperation'); /** 此时日志已经报上去了😄**/
白名单
白名单功能是适用于开发者希望对某些特定的用户上报更多的日志,但是又不希望太多上报来影响到全部日志数据,并且减少用户的接口请求次数,因为 TAM 设定了白名单的逻辑。
- 白名单用户会上报全部的 API 请求信息,包括接口请求和请求结果。
- 白名单用户可以使用
info
接口信息数据上报。 info
vsinfoAll
:在开发者实际体验过程中,白名单用户可以添加更多的日志,并且使用info
进行上报。infoAll
会对所有用户无差别进行上报,因此可能导致日志量上报巨大。- 通过接口
whitelist
来判断当前用户是否是白名单用户,白名单用户的返回结果会绑定在aegis
实例上 (aegis.isWhiteList
) 用来给开发者使用。 - 用了减少开发者使用负担,白名单用户是团队有效,可以在 组织管理-白名单管理 内创建白名单,则团队下全部项目都生效。
页面加载耗时上报
页面加载耗时上报需按如下步骤:
runApp
之前先初始化Aegis
,并将config
的enablePageLoadTime
设置为true
void main() {
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
// 先初始化 Aegis 组件,因为需要计算页面渲染时间
final aegis = Aegis(
Config(
id: 'xxxxx',
uin: 'xxxxx',
enablePageLoadTime: true,
),
);
runApp(MyApp());
}, (Object error, StackTrace stack) async {
});
}
- 在
MaterialApp
中添加navigatorObservers
,初始化TAM
的PageNavigatorObserver()
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Demo(),
navigatorObservers: [PageNavigatorObserver()],
);
}
}
- 启动页面由 SDK 内部命名为了
firstPage
,后续其他页面的命名建议在初始化router
时进行设置,SDK 默认上报为unknown
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return ChangeNotifierProvider<Catalog>(
create: (context) => Catalog(),
child: InfiniteListPage(),
);
},
settings: RouteSettings(name: 'InfiniteListPage'),
),
);
钩子函数/错误监控/离线日志
建设中
配置文档
配置 | 描述 |
---|---|
id | 必须,string,默认 无。开发者平台分配的项目 key |
uin | 建议,string。当前用户的唯一标识符,白名单上报时将根据该字段判定用户是否在白名单中,字段仅支持字母数字@=._-,正则表达式: /^[@=.0-9a-zA-Z_-]{1,60}$/ |
version | 可选,string,默认 SDK 版本号。当前上报版本,当页面使用了 PWA 或者存在离线包时,可用来判断当前的上报是来自哪一个版本的代码,仅支持字母数字.,:_-,长度在 60 位以内 |
delay | 可选,int,默认 1000 ms。上报节流时间,在该时间段内的上报将会合并到一个上报请求中。 |
repeat | 可选,int,默认 5。重复上报次数,对于同一个错误超过多少次不上报。 |
url | 可选,string,默认 //aegis.qq.com/collect 。日志上报地址 |
speedUrl | 可选,string,默认 //aegis.qq.com/speed 。测速日志上报地址 |
whiteListUrl | 可选,string,默认 //aegis.qq.com/collect/whitelist 。白名单确认接口。如果想要关闭白名单接口请求,可以传空字符串。 |
ext1 | 可选,string,自定义上报的额外维度,上报的时候可以被覆盖。 |
ext2 | 可选,string,自定义上报的额外维度,上报的时候可以被覆盖。 |
ext3 | 可选,string,自定义上报的额外维度,上报的时候可以被覆盖。 |
常见问题(FAQ)
- 接口请求报错 403 要怎么处理?
接口 403 一般是因为页面域名校验失败导致的,可以检查项目创建时候设置的域名跟实际上报的域名是否一致。如果项目刚刚创建或者修改域名校验,TAM 数据同步需要一定的时间,大概在 1-2min,可以稍微等一下,这段时间用来读一下文档也是不错的。
- RUM 自定义测速为什么仅支持 0 - 60000 之间的数据?
之前自定义测速的逻辑是用户上报任意数据,我们对用户数据进行求均值和中位数,然后显示计算后的结果,但是这样带来的问题就是,服务端无法判断脏数据,但是少量脏数据对用户实际数据却会产生非常大的影响,因此我们目前在服务端对用户数据进行了限制,目前只支持 0-60000 内的数据。
- RUM 根据哪个字段来计算 UV?
aegis SDK 没有根据用户设置的 uin 来计算 UV,因为如果当前用户没有登录,则无法计算,而且 uin 值由开发者设置,并不完全可靠,还有无法将用户登录前后状态统一起来,因此 aegis SDK 为每个用户独立生成一个 aid 作为用户(设备)的唯一标识,并且存储在 localStorage 里面,不受登录态影响
行为准则(Code Of Conduct)
如何加入(How To Join)
团队介绍(Members)
完整示例 demo
example/lib/main.dart
import 'dart:async';
import 'package:aegis_flutter_sdk/aegis_flutter_sdk.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'infinite_list/catalog.dart';
import 'infinite_list/infinite_list_page.dart';
import 'util/aegis_manager.dart';
void main() {
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
// 先初始化 Aegis 组件,因为需要计算页面渲染时间
AegisManager();
runApp(MyApp());
}, (Object error, StackTrace stack) async {
AegisManager()
.ageis
.error('flutter uncaught error, error:$error, stackTrace:$stack');
});
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Demo(),
navigatorObservers: [PageNavigatorObserver()],
);
}
}
class Demo extends StatelessWidget {
// 项目id需要在https://tam.woa.com/role/group-projects-manage内申请
final aegis = AegisManager().ageis;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo'),
),
body: ListView(
children: [
TextButton(
onPressed: onPressedInfoAll,
child: Text('aegis.infoAll [日志上报]'),
style: TextButton.styleFrom(
primary: Colors.green,
),
),
TextButton(
onPressed: onPressedInfo,
child: Text('aegis.info [白名单日志上报]'),
style: TextButton.styleFrom(
primary: Colors.blue,
),
),
TextButton(
onPressed: onPressedReport,
child: Text('aegis.report [自定义错误日志上报]'),
style: TextButton.styleFrom(
primary: Colors.orange,
),
),
TextButton(
onPressed: onPressedError,
child: Text('aegis.error [系统级error日志上报]'),
style: TextButton.styleFrom(
primary: Colors.red,
),
),
TextButton(
onPressed: onPressedEvent,
child: Text('aegis.event'),
style: TextButton.styleFrom(
primary: Colors.red,
),
),
TextButton(
onPressed: onPressedReporttime,
child: Text('aegis.reportTime'),
style: TextButton.styleFrom(
primary: Colors.teal,
),
),
TextButton(
onPressed: onPressedTime,
child: Text('aegis.time'),
style: TextButton.styleFrom(
primary: Colors.lightGreen,
),
),
TextButton(
onPressed: onPressedTimeEnd,
child: Text('aegis.timeEnd'),
style: TextButton.styleFrom(
primary: Colors.lightGreen,
),
),
TextButton(
onPressed: () {
openInfiniteListPage(context);
},
child: Text('打开无限List流测试上报页面渲染时间'),
style: TextButton.styleFrom(
primary: Colors.deepPurple,
),
),
],
),
);
}
void onPressedInfo() {
aegis.info({
'text': 'test',
'number': 1,
'cool': {'a': 3}
});
}
void onPressedReport() {
aegis.report('report');
}
void onPressedInfoAll() {
aegis.infoAll({
'text': 'inforest',
'number': 1,
'cool': {'a': 3}
});
}
void onPressedError() {
aegis.error('error');
}
void onPressedEvent() {
aegis.reportEvent('example event 2', ext1: 'testExt1');
}
void onPressedReporttime() {
aegis.reportTime('exampletime2', 1000);
}
void onPressedTime() {
aegis.time('customTime2');
}
void onPressedTimeEnd() {
aegis.timeEnd('customTime2');
}
void openInfiniteListPage(BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return ChangeNotifierProvider<Catalog>(
create: (context) => Catalog(),
child: InfiniteListPage(),
);
},
settings: RouteSettings(name: 'InfiniteListPage'),
),
);
}
}
更多关于Flutter安全保护插件aegis_flutter_sdk的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter安全保护插件aegis_flutter_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中集成和使用aegis_flutter_sdk
插件来进行安全保护的代码示例。aegis_flutter_sdk
是一个常用于Flutter应用的安全保护插件,它提供了一系列功能来增强应用的安全性。
首先,你需要在你的pubspec.yaml
文件中添加aegis_flutter_sdk
依赖:
dependencies:
flutter:
sdk: flutter
aegis_flutter_sdk: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter应用中,你可以按照以下步骤来使用aegis_flutter_sdk
:
- 初始化SDK:
在应用启动时,你需要初始化aegis_flutter_sdk
。这通常在main.dart
文件的MyApp
类中完成。
import 'package:flutter/material.dart';
import 'package:aegis_flutter_sdk/aegis_flutter_sdk.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 初始化Aegis SDK
AegisFlutterSdk.init(
appId: '你的AppId', // 替换为你的AppId
appKey: '你的AppKey', // 替换为你的AppKey
channel: '你的Channel', // 替换为你的Channel,通常是你的应用发布渠道
);
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
- 使用SDK提供的安全功能:
aegis_flutter_sdk
提供了多种安全功能,如设备指纹、防篡改检测等。以下是如何使用这些功能的示例:
import 'package:flutter/material.dart';
import 'package:aegis_flutter_sdk/aegis_flutter_sdk.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String deviceFingerprint = '';
@override
void initState() {
super.initState();
// 获取设备指纹
_getDeviceFingerprint();
}
Future<void> _getDeviceFingerprint() async {
try {
String fingerprint = await AegisFlutterSdk.getDeviceFingerprint();
setState(() {
deviceFingerprint = fingerprint;
});
} catch (e) {
print('获取设备指纹失败: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'设备指纹: $deviceFingerprint',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
try {
bool isTampered = await AegisFlutterSdk.checkAppTamper();
if (isTampered) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('警告'),
content: Text('应用检测到被篡改!'),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('确定'),
),
],
);
},
);
} else {
print('应用未被篡改。');
}
} catch (e) {
print('检查应用篡改失败: $e');
}
},
child: Text('检查应用是否被篡改'),
),
],
),
),
);
}
}
在上面的代码中,我们展示了如何获取设备指纹以及如何检查应用是否被篡改。当然,aegis_flutter_sdk
提供了更多的功能,你可以根据文档进一步探索和使用这些功能。
请确保你已经正确配置了aegis_flutter_sdk
所需的AppId、AppKey和Channel,这些通常是在你注册和使用该SDK服务时获得的。
希望这个示例能帮助你在Flutter项目中集成和使用aegis_flutter_sdk
!