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

如何在ASP.NET Core 6中配置Azure AD独立登录/登出页面

自定义Azure AD登录页:未认证用户重定向至自有Razor页面(ASP.NET Core 6)

问题背景

我之前集成Okta时,它提供可嵌入的登录组件,能通过控制器触发认证流程。但Azure AD没有类似组件,所以我想把带自有Logo的Razor页面(路径/pages/login/index)设为唯一允许匿名访问的页面,作为未登录用户的初始界面,点击页面按钮后调用控制器Post操作跳转至Azure AD登录页。

当前代码会直接跳转到微软登录页,核心Program.cs代码如下:

using System.Collections.Generic;
using System.Configuration;
using System.IO;
using Project.Models;
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;

var builder = WebApplication.CreateBuilder(args);

//authentication pipeline
var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
                    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                        .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
                        .AddInMemoryTokenCaches();

builder.Services.AddControllers(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
});

builder.Services.AddRazorPages()
                .AddMicrosoftIdentityUI();

var RootPath = builder.Environment.ContentRootPath;
var WebPath = builder.Environment.WebRootPath;
var fileDirectory = Path.Combine(Directory.GetParent(RootPath).Parent.ToString(), "armsfiles");
IFileProvider physicalProvider = new PhysicalFileProvider(fileDirectory);
builder.Services.AddSingleton<IFileProvider>(physicalProvider);

var connectionString = builder.Configuration.GetConnectionString("DBContext");
builder.Services.AddDbContext<DBContext>(options => options.UseSqlServer(connectionString));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
else
{
    app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = physicalProvider,
    RequestPath = "/files"
});

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action}/{id?}",
    defaults: new { controller = "Home", action = "Index" });

app.Run();

尝试过的配置

我曾添加过Razor页面权限配置,但不确定是否生效,因为找不到未登录用户的重定向设置:

builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
    options.Conventions.AllowAnonymousToFolder("/Login");
    options.Conventions.AuthorizeFolder("/");
    options.Conventions.AuthorizeFolder("/files");
});

已解决的部分(2022年11月22日更新)

除了未认证用户自动重定向至/login/页面外,其余问题已解决。登录页按钮的OnPost方法已实现挑战逻辑:

public class IndexModel : PageModel
{
    private string SignedInRedirectUri;

    public IndexModel(IConfiguration configuration)
    {
        SignedInRedirectUri = configuration["AzureAd:SignedInRedirectUri"];
    }

    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
        return Challenge(
            new AuthenticationProperties { RedirectUri = SignedInRedirectUri },
            OpenIdConnectDefaults.AuthenticationScheme);
    }
}

核心疑问

是否存在类似Cookie认证中设置LoginPath的方式,让未认证用户自动重定向到自定义登录页?比如Cookie认证的配置方式:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(cookieOptions =>
{
    cookieOptions.Cookie.Name = "UserLoginCookie";
    cookieOptions.LoginPath = "/Login/";
    cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(30);
    cookieOptions.SlidingExpiration = true;
});

解决方案

在ASP.NET Core 6中使用Azure AD(Microsoft Identity Web)时,要实现未认证用户重定向到自定义登录页,需要通过Cookie认证选项配置,因为Azure AD的OpenID Connect认证最终依赖Cookie维持会话。

修改认证配置

修改Program.cs中的认证配置段,在AddMicrosoftIdentityWebApp之后添加Cookie配置,指定LoginPath:

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
        .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
            .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
            .AddInMemoryTokenCaches()
    // 配置Cookie认证的LoginPath,指向自定义登录页
    .AddCookie(options =>
    {
        options.LoginPath = "/Login";
    });

确保Razor页面权限配置正确

调整Razor页面服务配置,确保/Login文件夹允许匿名访问,其余路径强制认证:

builder.Services.AddRazorPages(options =>
{
    options.Conventions.AllowAnonymousToFolder("/Login");
    options.Conventions.AuthorizeFolder("/");
    options.Conventions.AuthorizeFolder("/files");
})
.AddMicrosoftIdentityUI();

关键说明

  • Azure AD的OpenID Connect认证默认使用Cookie存储会话,因此修改Cookie认证的LoginPath即可控制未认证用户的重定向目标。
  • 自定义登录页的OnPost触发Azure AD认证的逻辑无需修改,保持现有实现即可。
  • 必须确保/Login路径确实允许匿名访问,否则会出现重定向循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:01:22