Flutter JWT管理插件simple_jwt_manager的使用
Flutter JWT管理插件simple_jwt_manager的使用
(日语版本可见此处)。
概述
这是一个支持使用JWT进行身份验证的软件包。目前,它支持使用在RFC 6749中定义的“资源所有者密码凭据授权”,以及一般的注册功能。登出处理遵循RFC 7009。
使用方法
请参阅pub.dev上的示例标签。
支持
基本上不提供支持。如果你有任何问题,请在GitHub上打开一个issue。这个包优先级较低,但可能会被修复。
版本控制
当版本升级时,C部分会发生变化。然而,小于1.0.0的版本可能不受以下规则的约束。
- 添加变量、导致读取先前文件出现问题的结构更改。
- C.X.X
- 添加方法等。
- X.C.X
- 小修改和错误修复。
- X.X.C
许可证
版权所有 2024 Masahide Mori
根据Apache许可证2.0版(“许可证”)获得许可; 你不能使用此文件,除非遵守许可证。 你可以在以下网址获得许可证的副本:
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则根据许可证分发的软件是按“原样”分发的,没有任何明示或暗示的保证或条件。请参阅许可证以获取特定的语言规定权限和限制。
版权声明
“Dart”名称和“Flutter”名称是Google LLC的商标。 *该软件包的开发者不是Google LLC。
完整示例代码
import 'package:flutter/material.dart';
import 'package:simple_jwt_manager/simple_jwt_manager.dart';
import 'dart:convert';
// TODO 选择客户端版本。
late final ROPCClient ropcClient; // web 或 native
// late final ROPCClientForNative
// ropcClient; // native,使用自签名证书
// TODO: 请确保重写此URL。
const String registerURL = "https://your end point url";
const String signInURL = "https://your end point url";
const String refreshURL = "https://your end point url";
const String signOutURL = "https://your end point url";
const String deleteUserURL = "https://your end point url";
// 包含JWT的认证头的POST数据的URL。
const String postingDataURL = "https://your end point url";
void main() async {
Map<String, dynamic>? savedData;
// TODO: 如果有必要,以自己的方式恢复存储的令牌。
// savedData = jsonDecode(从存储中获取的令牌);
// 在实际应用中,可以将ROPCClient封装在一个单例类中。
// 因为ROPCClient类不是一个单例,
// 所以可以在多个ROPCClient中分别管理多个令牌。
// 对于web或native设备。
ropcClient = ROPCClient(
registerURL: registerURL,
signInURL: signInURL,
refreshURL: refreshURL,
signOutURL: signOutURL,
deleteUserURL: deleteUserURL,
savedData: savedData);
// 仅适用于native设备。
// 这个版本可以支持自签名证书。
// ropcClient = ROPCClientForNative(
// registerURL: registerURL,
// signInURL: signInURL,
// refreshURL: refreshURL,
// signOutURL: signOutURL,
// deleteUserURL: deleteUserURL,
// badCertificateCallback: (X509Certificate cert, String host, int port) {
// // TODO
// // 这里检查条件,如果返回true,则允许自签名证书。
// return true;
// },
// savedData: savedData);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _tecID = TextEditingController();
final TextEditingController _tecPW = TextEditingController();
[@override](/user/override)
void dispose() {
_tecID.dispose();
_tecPW.dispose();
super.dispose();
}
// TODO 请注意,这只是使用示例,并不会像这样布局。
[@override](/user/override)
Widget build(BuildContext context) {
// TODO 你可以这样获取signIn状态:
// final bool isSignedIn = ropcClient.isSignedIn();
return MaterialApp(
title: 'Simple JWT Manager Example',
home: Scaffold(
appBar: AppBar(
title: const Text('Simple JWT Manager Example'),
backgroundColor: const Color.fromARGB(255, 0, 255, 0),
),
backgroundColor: const Color.fromARGB(255, 255, 255, 255),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 320,
margin: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: TextField(
controller: _tecID,
decoration:
const InputDecoration(hintText: "User ID (e-mail)"),
)),
Container(
width: 320,
margin: const EdgeInsets.fromLTRB(0, 12, 0, 0),
child: TextField(
controller: _tecPW,
decoration:
const InputDecoration(hintText: "User password"),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 48, 0, 0),
child: ElevatedButton(
onPressed: () {
ropcClient
.register(_tecID.text, _tecPW.text)
.then((ServerResponse v) {
debugPrint(v.toString());
switch (v.resultStatus) {
case EnumSeverResponseStatus.success:
// TODO: 如果后端返回令牌,可以在这里存储。
// final String serializedClients = jsonEncode(ropcClient.toDict());
// TODO 如果你想,可以以自己的方式保存它。
// TODO 请添加用户注册完成后的处理过程。
break;
case EnumSeverResponseStatus.timeout:
// TODO: 处理超时情况。
break;
case EnumSeverResponseStatus.serverError:
// TODO: 处理服务器端错误。
break;
case EnumSeverResponseStatus.otherError:
// TODO: 处理其他错误。
break;
case EnumSeverResponseStatus.signInRequired:
// 通常不会发生在这里。
throw Exception();
}
});
},
child: const Text('注册'),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 12, 0, 0),
child: ElevatedButton(
onPressed: () {
ropcClient
.signIn(_tecID.text, _tecPW.text)
.then((ServerResponse v) {
debugPrint(v.toString());
switch (v.resultStatus) {
case EnumSeverResponseStatus.success:
// TODO: 如果后端返回令牌,可以在这里存储。
// final String serializedClients =
jsonEncode(ropcClient.toDict());
// TODO 如果你想,可以以自己的方式保存它。
// TODO 请添加用户注册完成后的处理过程。
break;
case EnumSeverResponseStatus.timeout:
// TODO: 处理超时情况。
break;
case EnumSeverResponseStatus.serverError:
// TODO: 处理服务器端错误。
break;
case EnumSeverResponseStatus.otherError:
// TODO: 处理其他错误。
break;
case EnumSeverResponseStatus.signInRequired:
// 通常不会发生在这里。
throw Exception();
}
});
},
child: const Text('登录'),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 12, 0, 0),
child: ElevatedButton(
onPressed: () {
ropcClient.signOutAllTokens().then((ServerResponse v) {
debugPrint(v.toString());
switch (v.resultStatus) {
case EnumSeverResponseStatus.success:
// 登出完成。
break;
case EnumSeverResponseStatus.timeout:
// TODO: 处理超时情况。
break;
case EnumSeverResponseStatus.serverError:
// TODO: 处理服务器端错误。
break;
case EnumSeverResponseStatus.otherError:
// TODO: 处理其他错误。
break;
case EnumSeverResponseStatus.signInRequired:
// 通常不会发生在这里。
throw Exception();
}
});
},
child: const Text('登出'),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 12, 0, 0),
child: ElevatedButton(
onPressed: () {
ropcClient
.deleteUser(_tecID.text, _tecPW.text)
.then((ServerResponse v) {
debugPrint(v.toString());
switch (v.resultStatus) {
case EnumSeverResponseStatus.success:
// 删除用户完成。
break;
case EnumSeverResponseStatus.timeout:
// TODO: 处理超时情况。
break;
case EnumSeverResponseStatus.serverError:
// TODO: 处理服务器端错误。
break;
case EnumSeverResponseStatus.otherError:
// TODO: 处理其他错误。
break;
case EnumSeverResponseStatus.signInRequired:
// 通常不会发生在这里。
throw Exception();
}
});
},
child: const Text('删除用户'),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 12, 0, 0),
child: ElevatedButton(
onPressed: () {
ropcClient
.refreshAndGetNewToken()
.then((ServerResponse v) {
debugPrint(v.toString());
switch (v.resultStatus) {
case EnumSeverResponseStatus.success:
// 完成。
break;
case EnumSeverResponseStatus.timeout:
// TODO: 处理超时情况。
break;
case EnumSeverResponseStatus.serverError:
// TODO: 处理服务器端错误。
break;
case EnumSeverResponseStatus.otherError:
// TODO: 处理其他错误。
break;
case EnumSeverResponseStatus.signInRequired:
// TODO:
debugPrint("登录所需");
break;
}
});
},
child: const Text('刷新令牌(仅调试)'),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 12, 0, 0),
child: ElevatedButton(
onPressed: () async {
String? jwt = await ropcClient.getToken();
debugPrint("令牌: ${jwt ?? "null"}");
if (jwt != null) {
// TODO 添加你的实现以在后端执行某些操作。
// 对于web或native设备。
final ServerResponse res = await UtilHttps.post(
postingDataURL,
{"test": "test params"},
EnumPostEncodeType.json,
jwt: jwt);
// 仅适用于native设备。
// 这个版本可以支持自签名证书。
// final ServerResponse res =
// await UtilHttpsForNative.post(
// postingDataURL,
// {"test": "test params"},
// EnumPostEncodeType.json,
// jwt: jwt, badCertificateCallback:
// (X509Certificate cert, String host,
// int port) {
// // TODO
// // 这里检查条件,如果返回true,则允许自签名证书。
// return true;
// });
// 服务器响应
debugPrint("服务器响应: $res");
switch (res.resultStatus) {
case EnumSeverResponseStatus.success:
// TODO: 处理这个情况。
break;
case EnumSeverResponseStatus.timeout:
// TODO: 处理这个情况。
break;
case EnumSeverResponseStatus.serverError:
// TODO: 处理这个情况。
break;
case EnumSeverResponseStatus.otherError:
// TODO: 处理这个情况。
break;
case EnumSeverResponseStatus.signInRequired:
// TODO: 处理这个情况。
break;
}
} else {
// TODO 令牌已过期或未获得,请转到登录屏幕。
debugPrint("令牌为空。");
}
},
child: const Text('向EndPoints发送数据'),
)),
],
)
],
),
),
);
}
}
更多关于Flutter JWT管理插件simple_jwt_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter JWT管理插件simple_jwt_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用simple_jwt_manager
插件进行JWT(JSON Web Token)管理的示例代码。simple_jwt_manager
插件可以帮助你轻松地在Flutter应用中处理JWT的存储、解析和验证等操作。
首先,确保你的Flutter项目中已经添加了simple_jwt_manager
依赖。你可以在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
simple_jwt_manager: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
示例代码
1. 导入必要的包
在你的Dart文件中导入simple_jwt_manager
包:
import 'package:simple_jwt_manager/simple_jwt_manager.dart';
2. 配置JWT Manager
配置JWT Manager实例,通常你会在应用的初始化阶段进行配置:
void configureJwtManager() {
// 配置JWT存储策略,这里使用内存存储作为示例
JwtStorage jwtStorage = new MemoryJwtStorage();
// 初始化JWT Manager
JwtManager jwtManager = new JwtManager(jwtStorage);
// 可选:设置JWT解析和验证规则
jwtManager.jwtParser = new JwtParser(
secret: 'your-secret-key', // 替换为你的密钥
issuer: 'your-issuer', // 替换为你的发行者
audience: 'your-audience' // 替换为你的受众
);
// 将JWT Manager实例保存到全局变量或依赖注入容器中
// 例如:
// globalJwtManager = jwtManager;
}
3. 存储JWT
在用户登录成功后,你可以将JWT存储起来:
void storeJwt(String jwtToken) {
JwtManager jwtManager = getJwtManagerInstance(); // 获取你之前配置的JWT Manager实例
jwtManager.storeToken(jwtToken);
}
4. 获取JWT
在需要的时候,你可以从存储中获取JWT:
String? retrieveJwt() {
JwtManager jwtManager = getJwtManagerInstance(); // 获取你之前配置的JWT Manager实例
return jwtManager.retrieveToken();
}
5. 解析JWT
你可以解析JWT以获取其中的信息:
void parseJwt() {
JwtManager jwtManager = getJwtManagerInstance(); // 获取你之前配置的JWT Manager实例
String? jwtToken = jwtManager.retrieveToken();
if (jwtToken != null) {
try {
JwtDecoded jwtDecoded = jwtManager.decodeToken(jwtToken);
print('JWT Payload: ${jwtDecoded.payload}');
} catch (e) {
print('Failed to decode JWT: $e');
}
} else {
print('No JWT token found.');
}
}
6. 验证JWT
在需要验证JWT有效性的时候,你可以进行验证:
bool verifyJwt() {
JwtManager jwtManager = getJwtManagerInstance(); // 获取你之前配置的JWT Manager实例
String? jwtToken = jwtManager.retrieveToken();
if (jwtToken != null) {
try {
bool isValid = jwtManager.verifyToken(jwtToken);
return isValid;
} catch (e) {
print('Failed to verify JWT: $e');
return false;
}
} else {
print('No JWT token found.');
return false;
}
}
7. 移除JWT
当用户注销时,你可以移除存储的JWT:
void removeJwt() {
JwtManager jwtManager = getJwtManagerInstance(); // 获取你之前配置的JWT Manager实例
jwtManager.clearToken();
}
注意事项
- 确保你的密钥(secret)、发行者(issuer)和受众(audience)与服务器端的配置相匹配。
- 在生产环境中,建议使用更安全的JWT存储方式,比如Keychain(iOS)或KeyStore(Android)。
- 定期检查JWT的有效性,并在必要时刷新JWT。
通过这些代码示例,你可以在Flutter应用中有效地使用simple_jwt_manager
插件来管理JWT。