使用Microsoft Entra ID认证时如何覆盖默认登录跳转路径?
问题
我正在探索Microsoft Entra ID单租户工作组认证,按照线上教程配置后已正常运行:当访问需要认证的页面时,应用会通过302跳转至https://login.microsoftonline.com/.../oauth2/v2.0/authorize端点。
现在我需要让用户访问未授权内容时,先跳转至一个自定义着陆页(含说明信息和微软登录按钮,点击按钮再跳转至认证端点),而非直接跳转至微软认证端点。请问有哪些方法或配置可以覆盖默认的302跳转认证端点?
此前我们使用.NET Core EF Identity框架,通过配置应用Cookie的LoginPath即可实现该需求:
builder.Services.ConfigureApplicationCookie(options => { options.LoginPath = new PathString("/LoginLandingPage"); });
但切换至Entra ID后该配置失效(这在预期之内),以下是当前的Program.cs代码:
using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; using Microsoft.EntityFrameworkCore; using MudBlazor.Services; using FieldOne_AI_SomTam.Components; using FieldOne_AI_SomTam.Data; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.Authorization; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); builder.Services.AddMudServices(); builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration); builder.Services.AddHttpContextAccessor(); builder.Services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }).AddMicrosoftIdentityUI(); // This doesn't work //builder.Services.ConfigureApplicationCookie(options => //{ // options.LoginPath = new PathString("/Login"); //}); builder.Services.AddCascadingAuthenticationState(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.MapControllers(); app.Run();
解决方案
方法1:自定义授权结果处理程序
通过实现IAuthorizationMiddlewareResultHandler拦截授权失败请求,重定向到自定义着陆页:
- 创建自定义处理类:
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization.Policy; public class CustomAuthorizationHandler : IAuthorizationMiddlewareResultHandler { private readonly AuthorizationMiddlewareResultHandler _defaultHandler = new(); public async Task HandleAsync( RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) { if (authorizeResult.Challenged) { // 重定向到自定义着陆页 context.Response.Redirect("/CustomLoginLanding"); return; } // 其他授权结果使用默认逻辑处理 await _defaultHandler.HandleAsync(next, context, policy, authorizeResult); } }
- 在Program.cs中注册该服务:
builder.Services.AddSingleton<IAuthorizationMiddlewareResultHandler, CustomAuthorizationHandler>();
方法2:修改OpenID Connect事件配置
通过配置OpenID Connect的跳转事件,实现先到自定义着陆页,再触发认证:
- 调整Entra ID认证配置:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(options => { builder.Configuration.Bind("AzureAd", options); options.Events.OnRedirectToIdentityProvider = context => { // 非着陆页请求时,重定向到自定义登录页 if (!context.Request.Path.StartsWithSegments("/CustomLoginLanding")) { // 保存原始访问路径,登录后跳转回去 context.Properties.RedirectUri = context.Request.Path; context.Response.Redirect("/CustomLoginLanding"); return Task.CompletedTask; } // 来自着陆页的请求,正常跳转到Entra ID认证端点 return Task.CompletedTask; }; });
- 在自定义着陆页(如
/CustomLoginLanding)添加登录触发逻辑:
在Razor组件中调用认证挑战:
@inject SignInManager<IdentityUser> SignInManager <button @onclick="TriggerMicrosoftLogin">使用Microsoft账号登录</button> @code { private async Task TriggerMicrosoftLogin() { var authProps = new AuthenticationProperties { // 跳转回之前的页面,或指定默认路径 RedirectUri = HttpContext.Request.Query["ReturnUrl"] ?? "/" }; await SignInManager.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, authProps); } }
注意事项
- 确保自定义着陆页不需要认证,避免循环重定向。
- 保存用户原始访问路径,登录成功后跳转回去提升体验。
- Razor Components项目需确保
CascadingAuthenticationState配置正确,认证状态能正常传递。
内容的提问来源于stack exchange,提问作者Han
相关产品推荐
相关产品推荐

