first commit

This commit is contained in:
2026-09-21 17:37:53 +08:00
commit 67d4dd5b7c
141 changed files with 8558 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
import 'dart:convert';
/// 本地解析 JWT 的 exp 字段,判断是否已过期。
///
/// 目的:App 启动时立刻发现"登录已过期",不必先发一次请求才报错。
/// 注意:只做本地时间判断,不校验签名——签名的真伪由后端负责。
/// 返回 false(视为未过期)的条件:token 不是标准 JWT 格式或没有 exp 字段,
/// 避免因格式差异把正常登录态误判为过期。
bool isJwtExpired(String? token, {Duration leeway = const Duration(seconds: 30)}) {
if (token == null || token.isEmpty) return true;
final parts = token.split('.');
if (parts.length != 3) return false;
try {
final payload = utf8.decode(base64Url.decode(base64Url.normalize(parts[1])));
final claims = jsonDecode(payload);
if (claims is! Map) return false;
final exp = claims['exp'];
if (exp is! num) return false; // 无 exp 字段 → 不做本地判断
final expireAt = DateTime.fromMillisecondsSinceEpoch(exp.toInt() * 1000);
return expireAt.isBefore(DateTime.now().add(leeway));
} catch (_) {
return false;
}
}