.NET MAUI如何读取SecureStorage中JWT并正确设置启动页
.NET MAUI 启动时异步验证JWT并跳转页面的解决方案
核心问题梳理
- 构造函数不支持异步,直接用
Task.Run会导致判断逻辑在JWT获取完成前执行,结果错误 - 移到App类时未正确重写
CreateWindow方法,触发Either set MainPage or override CreateWindow异常 - SecureStorage读取异常未被捕获,导致方法静默退出
正确实现步骤
1. 重写App类的CreateWindow方法
CreateWindow支持返回Task<Window>,可以安全执行异步操作,避开构造函数的限制。
修改App.xaml.cs代码:
using System.Text; using System.Text.Json; using Microsoft.Maui.Controls; namespace YourAppNamespace; public partial class App : Application { public App() { InitializeComponent(); // 不要在这里设置MainPage,由CreateWindow处理 } public override async Task<Window> CreateWindow(IActivationState activationState) { var window = new Window(); // 可选:先显示启动加载页,提升用户体验 window.Page = new SplashPage(); try { // 异步从SecureStorage获取JWT var jwtToken = await SecureStorage.GetAsync("auth_jwt"); // 验证JWT有效性(替换为你的实际验证逻辑) bool isAuthenticated = !string.IsNullOrEmpty(jwtToken) && !IsJwtExpired(jwtToken); // 根据验证结果设置主页面 window.Page = isAuthenticated ? new AppShell() : new LoginPage(); } catch (Exception ex) { // 捕获异常(比如SecureStorage访问失败),默认跳转到登录页 window.Page = new LoginPage(); // 可选:记录异常日志 // Logger.Error(ex, "Failed to validate JWT on app startup"); } return window; } // 示例:JWT过期时间验证方法,需根据实际业务调整 private bool IsJwtExpired(string jwt) { try { // 解析JWT Payload(仅示例,生产环境建议使用JWT库如System.IdentityModel.Tokens.Jwt) var payloadPart = jwt.Split('.')[1]; var decodedBytes = Convert.FromBase64String(payloadPart.Replace('-', '+').Replace('_', '/')); var payloadJson = Encoding.UTF8.GetString(decodedBytes); var payload = JsonSerializer.Deserialize<JwtPayload>(payloadJson); return payload.Exp < DateTimeOffset.UtcNow.ToUnixTimeSeconds(); } catch { // 解析失败视为无效JWT return true; } } // 辅助类:用于解析JWT Payload的过期字段 private class JwtPayload { [JsonPropertyName("exp")] public long Exp { get; set; } } }
2. 确保AppShell结构正确
AppShell.xaml保持常规的Shell内容定义即可,无需在其中处理页面跳转逻辑:
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:pages="clr-namespace:YourAppNamespace.Pages" x:Class="YourAppNamespace.AppShell"> <ShellContent Title="首页" ContentTemplate="{DataTemplate pages:MainPage}" /> <!-- 其他ShellContent定义 --> </Shell>
3. 处理SecureStorage读取异常
在CreateWindow的try-catch块中捕获所有可能的异常,避免方法静默退出。常见异常包括:
- 平台权限限制(MAUI已默认处理大部分场景)
- JWT格式错误
- SecureStorage初始化未完成
关键注意事项
- JWT验证逻辑:示例仅验证过期时间,生产环境需补充签名验证、Issuer/Audience校验等,建议使用成熟的JWT库(如
System.IdentityModel.Tokens.Jwt) - 键名一致性:确保存入和读取SecureStorage时使用的键名完全一致(示例中为
auth_jwt) - 加载状态:添加启动加载页可以避免用户看到空白页面,提升体验
内容的提问来源于stack exchange,提问作者Wasyster
相关产品推荐
相关产品推荐

