如何在.NET 6 Blazor Hybrid应用中实现Azure AD登录认证?
为.NET 6 Blazor Hybrid应用集成Azure AD身份认证与授权
1. 安装依赖包
在项目中安装以下NuGet包:
Microsoft.Identity.Client:用于MSAL认证逻辑Microsoft.AspNetCore.Components.Authorization:Blazor授权基础组件
2. 配置Azure AD注册应用
在Azure门户完成应用注册后,记录并配置以下信息:
- 租户ID(TenantId)、客户端ID(ClientId)
- 设置重定向URI:根据你的Blazor Hybrid平台选择对应格式:
- MAUI:
maui://com.yourcompany.yourapp - WPF/WinForms:
http://localhost
- MAUI:
- 按需添加
User.Read等Microsoft Graph权限(确保管理员同意必要权限)
3. 注册认证服务(Program.cs)
在Program.cs中配置MSAL客户端和自定义认证状态提供者:
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Identity.Client; var builder = WebApplication.CreateBuilder(args); // 添加Blazor基础服务 builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); // 注册MSAL客户端 builder.Services.AddSingleton(sp => { var config = sp.GetRequiredService<IConfiguration>(); return PublicClientApplicationBuilder .Create(config["AzureAd:ClientId"]) .WithAuthority($"https://login.microsoftonline.com/{config["AzureAd:TenantId"]}") .WithRedirectUri(config["AzureAd:RedirectUri"]) .Build(); }); // 注册自定义认证状态提供者与授权服务 builder.Services.AddScoped<AuthenticationStateProvider, AzureAdAuthStateProvider>(); builder.Services.AddAuthorizationCore(); var app = builder.Build(); // 配置中间件(静态文件、路由等) app.UseStaticFiles(); app.UseRouting(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
在appsettings.json中添加Azure AD配置节点:
{ "AzureAd": { "TenantId": "你的租户ID", "ClientId": "你的客户端ID", "RedirectUri": "对应平台的重定向URI" } }
4. 实现自定义AuthenticationStateProvider
创建AzureAdAuthStateProvider.cs类,处理登录、登出及用户状态同步:
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Identity.Client; using System.Security.Claims; public class AzureAdAuthStateProvider : AuthenticationStateProvider { private readonly IPublicClientApplication _msalClient; private IEnumerable<Claim> _currentUserClaims = Enumerable.Empty<Claim>(); public AzureAdAuthStateProvider(IPublicClientApplication msalClient) { _msalClient = msalClient; } public override async Task<AuthenticationState> GetAuthenticationStateAsync() { var accounts = await _msalClient.GetAccountsAsync(); if (accounts.Any()) { try { // 静默获取令牌(可替换为你需要的API权限范围) var result = await _msalClient.AcquireTokenSilent(new[] { "User.Read" }, accounts.First()) .ExecuteAsync(); _currentUserClaims = result.ClaimsPrincipal.Claims; } catch (MsalUiRequiredException) { // 无有效会话,需交互式登录 _currentUserClaims = Enumerable.Empty<Claim>(); } } var identity = _currentUserClaims.Any() ? new ClaimsIdentity(_currentUserClaims, "AzureAD") : new ClaimsIdentity(); return new AuthenticationState(new ClaimsPrincipal(identity)); } public async Task LoginAsync() { try { var result = await _msalClient.AcquireTokenInteractive(new[] { "User.Read" }) .ExecuteAsync(); _currentUserClaims = result.ClaimsPrincipal.Claims; NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } catch (MsalException) { // 处理登录异常(如用户取消登录) } } public async Task LogoutAsync() { var accounts = await _msalClient.GetAccountsAsync(); foreach (var account in accounts) { await _msalClient.RemoveAsync(account); } _currentUserClaims = Enumerable.Empty<Claim>(); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } }
5. 在Blazor组件中使用认证与授权
登录/登出组件(LoginDisplay.razor)
@inject AzureAdAuthStateProvider AzureAdAuth <AuthorizeView> <Authorized> <span>欢迎, @context.User.Identity.Name!</span> <button @onclick="AzureAdAuth.LogoutAsync" class="ml-2">登出</button> </Authorized> <NotAuthorized> <button @onclick="AzureAdAuth.LoginAsync">使用Azure AD登录</button> </NotAuthorized> </AuthorizeView>
保护路由(App.razor)
用AuthorizeRouteView替换默认RouteView,实现路由级授权:
<Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized> <div class="p-4"> <p>你需要登录才能访问此页面。</p> <LoginDisplay /> </div> </NotAuthorized> </AuthorizeRouteView> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p>抱歉,未找到该页面。</p> </LayoutView> </NotFound> </Router>
组件级授权
在需要保护的组件顶部添加[Authorize]特性:
@attribute [Authorize] <h1>仅授权用户可见的内容</h1> <p>此页面需要Azure AD登录才能访问。</p>
平台特定注意事项
- MAUI:需在Android的
AndroidManifest.xml中配置重定向URI的intent过滤器,在iOS的Info.plist中添加URL类型配置。 - WPF/WinForms:确保重定向URI设置为
http://localhost,并在应用启动时处理MSAL的回调(WPF可通过Dispatcher处理异步回调)。
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

