You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:25:31