如何通过代码限制Azure AD多租户Razor Pages应用仅允许指定租户登录
解决方法
你可以直接通过代码实现指定租户/域名访问限制,不需要使用Azure付费的租户限制功能,以下是两种可行的实现方案:
方案1:在身份验证流程中直接校验(推荐)
该方案在用户登录完成、令牌校验通过后立刻做域名/租户校验,不满足条件直接返回403,无需后续流程处理,性能最高,无需修改其他业务代码。
修改你ConfigureServices方法中的身份验证配置即可:
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(options => { // 绑定原有AzureAd配置 Configuration.Bind("AzureAd", options); // 添加令牌校验通过后的事件处理 options.Events = new OpenIdConnectEvents { OnTokenValidated = context => { // 与你的伪代码逻辑一致:校验邮箱后缀 var userEmail = context.Principal.Identity?.Name; // 可以配置多个允许的域名 var allowedDomains = new[] { "@alloweddomain.com" }; if (userEmail == null || !allowedDomains.Any(domain => userEmail.EndsWith(domain, StringComparison.OrdinalIgnoreCase))) { context.Fail("访问权限不足"); context.Response.StatusCode = 403; return Task.CompletedTask; } // 可选更安全的校验逻辑:直接校验租户ID,避免同域名其他租户用户访问 // var tenantId = context.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/tenantid"); // var allowedTenantIds = new[] { "你的允许租户ID1", "你的允许租户ID2" }; // if (tenantId == null || !allowedTenantIds.Contains(tenantId)) // { // context.Fail("访问权限不足"); // context.Response.StatusCode = 403; // return Task.CompletedTask; // } return Task.CompletedTask; } }; }); // 原有授权配置保持不变即可 services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; }); services.AddRazorPages() .AddMvcOptions(options => { }) .AddMicrosoftIdentityUI(); }
方案2:自定义全局授权策略
如果你希望把校验逻辑放在授权层统一管理,可以通过自定义授权策略实现,所有页面默认生效:
- 先定义自定义授权要求和处理逻辑:
// 自定义授权要求标记类 public class AllowedAccessRequirement : IAuthorizationRequirement { } // 授权校验逻辑处理类 public class AllowedAccessHandler : AuthorizationHandler<AllowedAccessRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AllowedAccessRequirement requirement) { var userEmail = context.User.Identity?.Name; var allowedDomains = new[] { "@alloweddomain.com" }; if (userEmail != null && allowedDomains.Any(domain => userEmail.EndsWith(domain, StringComparison.OrdinalIgnoreCase))) { context.Succeed(requirement); } else { context.Fail(); } return Task.CompletedTask; } }
- 修改
ConfigureServices中的授权配置:
services.AddAuthorization(options => { options.AddPolicy("AllowedAccessPolicy", policy => { policy.RequireAuthenticatedUser(); policy.AddRequirements(new AllowedAccessRequirement()); }); // 全局生效:所有请求默认使用该策略校验 options.FallbackPolicy = options.GetPolicy("AllowedAccessPolicy"); }); // 注册自定义授权处理程序 services.AddScoped<IAuthorizationHandler, AllowedAccessHandler>();
两种方案都可以实现你需要的效果,无需额外付费,也不需要修改现有页面的业务代码。
内容的提问来源于stack exchange,提问作者TravelingFox
相关产品推荐
相关产品推荐

