我刚刚创建了一个新的 MVC 项目并在 Azure 中创建了一个应用程序注册。以下是我目前拥有的代码:
启动.cs
public class Startup
{
public IConfiguration Configuration { get; }
public IWebHostEnvironment Env { get; set; }
public Startup(IConfiguration configuration, IWebHostEnvironment env) {
Configuration = configuration;
Env = env;
}
public void ConfigureServices(IServiceCollection services) {
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Database")), ServiceLifetime.Singleton);
services.AddHttpContextAccessor();
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
services.AddAuthorization(options => {
options.AddPolicy("AzureAccount", policyBuilder => {
policyBuilder.RequireAuthenticatedUser();
policyBuilder.AddRequirements(new PolicyRequirement());
});
});
services.AddSingleton<IAuthorizationHandler, PolicyAuthorizationHandler>();
services.AddControllersWithViews();
var mvcBuilder = services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
var cultureInfo = new CultureInfo("nl-NL");
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
if ( env.IsDevelopment() ) {
app.UseDeveloperExceptionPage();
} else {
app.UseExceptionHandler("/Home/Error");
// 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.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
程序.cs
public class Program
{
public static void Main(string[] args) {
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup<Startup>();
});
}
PolicyAuthorizationHandler.cs
public class PolicyAuthorizationHandler : AuthorizationHandler<PolicyRequirement>
{
private readonly DataContext _dataContext;
private readonly IHttpContextAccessor _httpContextAccessor;
public PolicyAuthorizationHandler(DataContext dataContext, IHttpContextAccessor httpContextAccessor) {
_dataContext = dataContext;
_httpContextAccessor = httpContextAccessor;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authorizationHandlerContext, PolicyRequirement policyRequirement) {
if ( await policyRequirement.Pass(_httpContextAccessor, _dataContext) ) {
authorizationHandlerContext.Succeed(policyRequirement);
}
}
}
政策要求.cs
public class PolicyRequirement : IAuthorizationRequirement
{
public async Task<bool> Pass(IHttpContextAccessor httpContextAccessor, DataContext dataContext) {
bool authorized = false;
if ( dataContext is not null ) {
string? email = httpContextAccessor.HttpContext!.User.Identity?.Name;
if ( email is not null ) {
User? user = dataContext.Users.AsQueryable().Where(x => x.Email == email && x.Active).FirstOrDefault();
if ( user is not null ) {
ClaimsIdentity claimsIdentity = new();
claimsIdentity.AddClaim(new(ClaimTypes.Email, email));
claimsIdentity.AddClaim(new(ClaimTypes.Name, user.Name));
claimsIdentity.AddClaim(new(ClaimTypes.Role, user.Role));
httpContextAccessor.HttpContext!.User.AddIdentity(claimsIdentity);
authorized = true;
}
}
}
return await Task.FromResult(authorized);
}
}
我的 HomeController 具有
[Authorize("AzureAccount")]
属性,并且该控制器的 Index 方法具有 var identities = _httpContextAccessor.HttpContext.User.Identities
行。我在这条线上放置了一个断点,发现此时它将有 2 个身份。 PolicyRequirement.Pass
方法运行了两次,我不明白为什么。我该如何解决这个问题并确保 _httpContextAccessor.HttpContext.User.Identity
具有我自己设置的正确身份?预先感谢。
Microsoft Identity Web (MIW) 将自动处理将用户添加到身份变量中的操作。因此,如果您想采用经过身份验证的上下文以及 MIW 预先添加的身份,并将其替换为您自己的身份,则需要删除其中一个身份。
通过不删除 MIW 添加的原始用户身份,正如您所指出的,您将拥有两个身份,并且该函数将为每个身份运行。
在我看来,您为
PolicyRequirement
提供的代码似乎没有明显的需要。当您已经拥有 MIW 中间件提供的用户身份时,您的意图可能是导致您拥有一个兔子洞。
[Authorize("AzureAccount")]
属性到达端点时,您都会获得一个额外的身份(2,然后 3,然后 4,等等...)。