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

Blazor MAUI谷歌登录问题求助:IHttpContextAccessor返回Null

Blazor MAUI 谷歌登录实现方案(解决IHttpContextAccessor Null问题)

问题核心

Blazor MAUI(移动端/桌面端)运行在本地应用容器中,不存在ASP.NET Core Web环境的HttpContext,因此IHttpContextAccessor必然返回Null,无法复用Web端的认证逻辑。以下是适配全平台的谷歌登录实现方案:

步骤1:配置谷歌OAuth应用

在谷歌云平台创建OAuth 2.0客户端ID,选择桌面应用类型(移动端通用),记录:

  • 客户端ID
  • 自定义回调URL Scheme(如com.googleusercontent.apps.你的客户端ID:/oauth2redirect)

步骤2:添加依赖包

安装NuGet包:

Install-Package Microsoft.AspNetCore.Components.WebAssembly.Authentication

步骤3:配置认证服务(Program.cs)

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Google", options.ProviderOptions);
    options.ProviderOptions.ResponseType = "code"; // 使用授权码流+PKCE
    options.ProviderOptions.AdditionalProviderParameters.Add("prompt", "consent");
})
.AddAccountClaimsPrincipalFactory<GoogleUserClaimsFactory>();

// 自定义Claims映射工厂,处理谷歌返回的额外字段(如头像)
public class GoogleUserClaimsFactory : AccountClaimsPrincipalFactory<RemoteUserAccount>
{
    public GoogleUserClaimsFactory(IAccessTokenProviderAccessor accessor) : base(accessor) { }

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(RemoteUserAccount account, RemoteAuthenticationUserOptions options)
    {
        var principal = await base.CreateUserAsync(account, options);
        if (principal.Identity.IsAuthenticated)
        {
            // 映射谷歌头像Claims
            if (account.AdditionalProperties.TryGetValue("picture", out var avatar))
            {
                ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("urn:google:image", avatar.ToString()));
            }
        }
        return principal;
    }
}

步骤4:添加认证配置(appsettings.json)

{
  "Google": {
    "Authority": "https://accounts.google.com",
    "ClientId": "你的谷歌客户端ID",
    "RedirectUri": "你的回调URL Scheme",
    "PostLogoutRedirectUri": "你的退出回调URL",
    "Scopes": "openid profile email"
  }
}

步骤5:重构登录组件(替换IHttpContextAccessor)

使用Blazor跨平台通用的AuthenticationStateProvider获取用户信息:

@using System.Security.Claims
@inject AuthenticationStateProvider AuthStateProvider
@inject NavigationManager NavManager

@if (User?.Identity.IsAuthenticated ?? false)
{
    <img src="@Avatar" />
    <b>已登录:@GivenName @Surname</b>
    <button class="ml-md-auto btn btn-primary" @onclick="Logout">退出登录</button>
}
else
{
    <button class="ml-md-auto btn btn-primary" @onclick="Login">登录</button>
}

@code {
    private ClaimsPrincipal User;
    private string GivenName;
    private string Surname;
    private string Avatar;

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthStateProvider.GetAuthenticationStateAsync();
        User = authState.User;
        
        if (User.Identity.IsAuthenticated)
        {
            GivenName = User.FindFirst(ClaimTypes.GivenName)?.Value ?? User.Identity.Name;
            Surname = User.FindFirst(ClaimTypes.Surname)?.Value ?? string.Empty;
            Avatar = User.FindFirst("urn:google:image")?.Value ?? string.Empty;
        }
    }

    private async Task Login()
    {
        var oidcProvider = (OidcAuthenticationStateProvider)AuthStateProvider;
        await oidcProvider.LoginAsync(new LoginOptions { RedirectUri = "/" });
    }

    private async Task Logout()
    {
        var oidcProvider = (OidcAuthenticationStateProvider)AuthStateProvider;
        await oidcProvider.LogoutAsync(new LogoutOptions { RedirectUri = "/" });
    }
}

步骤6:配置平台回调URL

  • Android:在AndroidManifest.xml中添加Intent Filter
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="你的回调URL Scheme前缀" />
    </intent-filter>
    
  • iOS:在Info.plist中添加URL Types
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>你的回调URL Scheme前缀</string>
            </array>
        </dict>
    </array>
    
  • Windows:在Package.appxmanifest中添加协议声明
    <Extensions>
        <uap:Extension Category="windows.protocol">
            <uap:Protocol Name="你的回调URL Scheme前缀">
                <uap:DisplayName>Google OAuth</uap:DisplayName>
            </uap:Protocol>
        </uap:Extension>
    </Extensions>
    

内容的提问来源于stack exchange,提问作者SYED HASSAN ALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:15:33