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

基于MSAL.NET与Microsoft Graph API的WPF应用SSO认证后自动关闭localhost标签页

解决WPF应用MSAL认证后自动关闭浏览器标签页的问题

当使用系统浏览器(WithUseEmbeddedWebView(false))进行MSAL认证时,要自动关闭认证完成后的localhost标签页,可以通过自定义本地HTTP监听器返回自动关闭页面的方式实现,具体步骤如下:

1. 修改Azure应用注册的重定向URI

将Azure门户中应用注册的重定向URI改为一个带具体端口的本地地址,比如 http://localhost:5000/redirect,确保和代码中配置的地址完全一致。

2. 实现本地HTTP监听器

在认证流程启动前,启动一个HttpListener监听指定地址,当收到AAD的重定向请求时,返回一段包含自动关闭窗口脚本的HTML页面。

3. 修正并调整MSAL认证代码

移除代码中重复的.ExecuteAsync();错误,配置正确的重定向URI,并在认证完成后停止HTTP监听器避免资源泄漏。

完整示例代码

private HttpListener _httpListener;
private async void Button_Click(object sender, RoutedEventArgs e)
{
    // 1. 启动本地HTTP监听器
    var redirectUri = "http://localhost:5000/redirect";
    _httpListener = new HttpListener();
    _httpListener.Prefixes.Add(redirectUri + "/");
    _httpListener.Start();
    // 异步处理重定向请求
    _ = HandleRedirectRequest();

    // 2. 初始化MSAL应用
    _app = PublicClientApplicationBuilder
        .Create(ClientId)
        .WithRedirectUri(redirectUri)
        .WithAuthority(Authority)
        .Build();

    AuthenticationResult authResult = null;
    var accounts = await _app.GetAccountsAsync();
    IAccount account = accounts.FirstOrDefault();

    IEnumerable<string> scopes = new string[] { "User.Read", "openid" };

    try
    {
        authResult = await _app.AcquireTokenSilent(scopes, account).ExecuteAsync();
    }
    catch (MsalUiRequiredException ex)
    {
        // 修正原代码中重复的ExecuteAsync()错误
        authResult = await _app.AcquireTokenInteractive(scopes)
            .WithUseEmbeddedWebView(false)
            .ExecuteAsync();
    }

    // 3. 停止并关闭HTTP监听器
    _httpListener.Stop();
    _httpListener.Close();

    // 后续Graph API调用逻辑
    BaseBearerTokenAuthenticationProvider accessTokenProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider(authResult.AccessToken));
    GraphServiceClient graphServiceClient = new GraphServiceClient(accessTokenProvider);
    User result = await graphServiceClient.Me.GetAsync();
    GroupCollectionResponse g = await graphServiceClient.Groups.GetAsync();
    DisplayBasicTokenInfo(authResult);
    DisplayGroupInformation(g);
}

private async Task HandleRedirectRequest()
{
    while (_httpListener.IsListening)
    {
        var context = await _httpListener.GetContextAsync();
        // 返回自动关闭窗口的HTML页面
        string responseHtml = @"
        <html>
            <head>
                <script type='text/javascript'>
                    window.close();
                </script>
            </head>
            <body>
                认证已完成,窗口将自动关闭...
            </body>
        </html>";
        byte[] buffer = Encoding.UTF8.GetBytes(responseHtml);
        context.Response.ContentLength64 = buffer.Length;
        context.Response.ContentType = "text/html";
        await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
        context.Response.Close();
    }
}

注意事项

  • 确保所选本地端口未被其他应用占用,可根据实际情况修改端口号。
  • 若使用.NET Core/.NET 5+环境,需确认已引入System.Net.HttpListener相关依赖。
  • 认证完成后必须停止并关闭HttpListener,避免不必要的资源占用。

内容的提问来源于stack exchange,提问作者Himanshu Pal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:30:34