User.Identity 不再在启用身份验证的 Azure Web 应用程序中设置
User.Identity no longer set in Azure web app with Authentication enabled
我正在将 .NET 4.8 应用程序迁移到 .NET Core。当前应用运行在Azure上,使用微软作为身份提供者进行身份验证(在Azure应用的Authentication页面设置,代码中没有任何内容,见下图),以便Azure AD中的任何用户都可以访问它。身份验证工作正常,当您尚未使用 Azure AD 帐户登录时,您将重定向到 login.microsoftonline.com 页面。
该应用程序包含一段在 .NET 4.8 中始终有效的简单代码
@if (Request.IsAuthenticated)
{
<strong>@User.Identity.Name</strong>
}
else
{
<div><i>Not logged in</i></div>
}
(开发者也可以在本地使用此应用,无需身份验证)
我现在已准备好在 Azure 上测试新应用程序,但我发现 User.Identity 未填充,我连接了一个远程调试器并发现所有属性都是空的(没有声明,默认的标识值)。
我发现了一些主题也报告了这个问题,但其中大多数已经在使用一些代码。
我想我可能遗漏了一些启动代码,但我无法弄清楚它是什么。目前我有
// ConfigureServices
services.AddAuthentication();
services.Configure<IdentityOptions>(options =>
options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier); // found this somewhere as solution, but didn't work so it's probably not required
// Configure
app.UseAuthentication();
app.UseAuthorization();
总结一下:
- 在 Azure 门户中设置的带有 Microsoft 身份提供程序 (Azure AD) 的 Azure Web 应用程序在 .NET 4.8 (MVC5) 中运行良好
- 相同的应用程序,相同的设置,但迁移到 .NET Core 不再具有 User.Identity 属性 设置
经过更多的挖掘,我发现 有同样的问题。所以事实证明它是由 ASP.NET 以不同方式工作的内核引起的。
其中一个答案包含一段解决问题的代码,我用它来创建一个新的简单中间件:
public static class AzureAuthExtensions
{
/// <summary>
/// Enables support for Azure EasyAuth, so that User.Identity.Name is populated correctly.
/// </summary>
public static IApplicationBuilder UseAzureEasyAuth(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<AzureEasyAuthMiddleware>();
}
}
public class AzureEasyAuthMiddleware
{
private readonly RequestDelegate _next;
public AzureEasyAuthMiddleware(RequestDelegate next)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
}
/// <summary>
/// Invoke the middleware.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
public Task Invoke(HttpContext context)
{
// Create a user on current thread from provided header
if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
{
// Read headers from Azure
var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
// Create claims id
var claims = new Claim[] {
new System.Security.Claims.Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", azureAppServicePrincipalIdHeader),
new System.Security.Claims.Claim("name", azureAppServicePrincipalNameHeader)
};
// Set user in current context as claims principal
var identity = new GenericIdentity(azureAppServicePrincipalNameHeader);
identity.AddClaims(claims);
// Set current thread user to identity
context.User = new GenericPrincipal(identity, null);
};
return _next(context);
}
}
这很有魅力!
我正在将 .NET 4.8 应用程序迁移到 .NET Core。当前应用运行在Azure上,使用微软作为身份提供者进行身份验证(在Azure应用的Authentication页面设置,代码中没有任何内容,见下图),以便Azure AD中的任何用户都可以访问它。身份验证工作正常,当您尚未使用 Azure AD 帐户登录时,您将重定向到 login.microsoftonline.com 页面。
该应用程序包含一段在 .NET 4.8 中始终有效的简单代码
@if (Request.IsAuthenticated)
{
<strong>@User.Identity.Name</strong>
}
else
{
<div><i>Not logged in</i></div>
}
(开发者也可以在本地使用此应用,无需身份验证)
我现在已准备好在 Azure 上测试新应用程序,但我发现 User.Identity 未填充,我连接了一个远程调试器并发现所有属性都是空的(没有声明,默认的标识值)。 我发现了一些主题也报告了这个问题,但其中大多数已经在使用一些代码。 我想我可能遗漏了一些启动代码,但我无法弄清楚它是什么。目前我有
// ConfigureServices
services.AddAuthentication();
services.Configure<IdentityOptions>(options =>
options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier); // found this somewhere as solution, but didn't work so it's probably not required
// Configure
app.UseAuthentication();
app.UseAuthorization();
总结一下:
- 在 Azure 门户中设置的带有 Microsoft 身份提供程序 (Azure AD) 的 Azure Web 应用程序在 .NET 4.8 (MVC5) 中运行良好
- 相同的应用程序,相同的设置,但迁移到 .NET Core 不再具有 User.Identity 属性 设置
经过更多的挖掘,我发现
public static class AzureAuthExtensions
{
/// <summary>
/// Enables support for Azure EasyAuth, so that User.Identity.Name is populated correctly.
/// </summary>
public static IApplicationBuilder UseAzureEasyAuth(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<AzureEasyAuthMiddleware>();
}
}
public class AzureEasyAuthMiddleware
{
private readonly RequestDelegate _next;
public AzureEasyAuthMiddleware(RequestDelegate next)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
}
/// <summary>
/// Invoke the middleware.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
public Task Invoke(HttpContext context)
{
// Create a user on current thread from provided header
if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
{
// Read headers from Azure
var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
// Create claims id
var claims = new Claim[] {
new System.Security.Claims.Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", azureAppServicePrincipalIdHeader),
new System.Security.Claims.Claim("name", azureAppServicePrincipalNameHeader)
};
// Set user in current context as claims principal
var identity = new GenericIdentity(azureAppServicePrincipalNameHeader);
identity.AddClaims(claims);
// Set current thread user to identity
context.User = new GenericPrincipal(identity, null);
};
return _next(context);
}
}
这很有魅力!