我即将将ASP.NET Core MVC Web应用程序从1.1迁移到2.0。该应用程序使用AzureAd进行身份管理。
在1.1中,我已经在Startup.cs(OnTokenReceiver
)中处理了openidconnect事件(如OnAuthorizationCodeReceived
,OnRemoteFailure
,Configure()
等),我在那里使用依赖注入。我注入了很多服务,比如EF db context,并在事件处理程序中使用它们。
升级到2.0后,我不得不将整个身份验证迁移到AzureAdAuthenticationBuilderExtensions
的{{1}}类(实现ConfigureAzureOptions
接口),其中(如我所见)DI无法使用。
所以现在只有这个在Startup的ConfigureServices中:
IConfigureNamedOptions<OpenIdConnectOptions>
有人知道如何在openidconnect事件中使用服务吗?
更新:我能够在@ Balah的回答的帮助下解决这个问题。基本上,解决方案是使用通用services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie();
而不是创建名为.AddOpenIdConnect()
的扩展名
答案的一小部分:由于身份验证部分已从.AddAzureAd()
移至Configure()
,其中DI未启用且服务尚未注册,因此获取这些服务的方法是:< / p>
ConfigureServices()
请注意,您必须在此代码之上添加这些服务!
答案 0 :(得分:2)
您会发现您提到的那些事件已被转移到认证选项上的(适当命名的)Events
属性。
访问DI容器中注册的任何服务可以通过HttpContext.RequestServices
属性完成,如下所示:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(o =>
{
o.Events.OnAuthorizationCodeReceived = async ctx =>
{
var db = ctx.HttpContext.RequestServices.GetService<DbContext>();
await ...
};
});
您可能需要添加services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
,因为这也是我所拥有的。但我怀疑上述情况会在没有它的情况下发挥作用。
这是一个很好地涵盖它的article。
答案 1 :(得分:0)
我正在使用.net core 3.1,并且遇到了类似的问题。 我认为可以通过将身份验证逻辑移到单独的处理程序类上来使其更加整洁,因为我们希望保持Startup.cs尽可能紧密。
public class AzureAdOpendIdHandler : IConfigureNamedOptions<OpenIdConnectOptions>
{
public void Configure(string name, OpenIdConnectOptions options)
{
options.ClientId = _azureOptions.ClientId;
options.UseTokenLifetime = true;
// The callback path located in AzureAd settings should match the callback path setup up in Azure portal
options.CallbackPath = _azureOptions.CallbackPath;
options.RequireHttpsMetadata = false;
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.TokenValidationParameters = new TokenValidationParameters
{
// Ensure that User.Identity.Name is set correctly after login
NameClaimType = JwtRegisteredClaimNames.Email,
ValidateIssuer = false,
};
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = async context =>
{
var dbContext = (HighEloDbContext)context.HttpContext.RequestServices.GetService(typeof(HighEloDbContext));
var acc = dbContext.Accounts.First(x => x.EmailAddress == userEmail);
...
},
OnAuthenticationFailed = context =>
{
context.Response.Redirect("/Error");
context.HandleResponse(); // Suppress the exception
return Task.CompletedTask;
},
};
}
public void Configure(OpenIdConnectOptions options)
{
Configure(Options.DefaultName, options);
}
}
这是我的Starup.cs的样子:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages().AddMvcOptions(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => { Configuration.Bind(nameof(AzureAdConfig), options); });
//here comes registration of services, DAL contexts etc.
services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, AzureAdOpendIdHandler>();
}
请注意,它可以与.AddAzureAD