.net core 5.0 CurrentPrincipal resets value



我有一个.net core 5.0应用程序,它需要额外的证书验证,并且基于证书,我在db中获得某些角色。我将它们作为声明存储在Thread.CurrentPrincipal或HttpContext.User中。但当调用到Controller时,这两个声明都会返回默认值。

这是Startup.cs

public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
....
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.RevocationMode = X509RevocationMode.NoCheck;
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{ //container.Resolve<CertificateHandler>();
OnCertificateValidated = context =>
{
if (!ValidateCertificate(context.ClientCertificate))
{
CreateErrorResponse(context, StatusCodes.Status403Forbidden, MaloConstants.NoValidClientCertificateReceived);
return Task.CompletedTask;
}
var certRoles = certificateProcessor.GetRoleIDs(context.ClientCertificate)
var roleClaims = certRoles.Roles.Distinct().OrderBy(r => r)
.Select(s => new Claim(ClaimsHelper.MALoInternalRole, s.ToString(CultureInfo.InvariantCulture), typeof(int).Name)).ToList();
var id = new ClaimsIdentity(roleClaims, AuthenticationType.X509.ToString());
var principal = new ClaimsPrincipal(new[] { id });
Thread.CurrentPrincipal = principal;
context.HttpContext.User = principal;
context.Success();
return Task.CompletedTask;
}
};
});
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "X-SSL-CERT";
options.HeaderConverter = (headerValue) =>
{
X509Certificate2 clientCertificate = null;
if (!string.IsNullOrWhiteSpace(headerValue))
{
byte[] bytes = StringToByteArray(headerValue);
clientCertificate = new X509Certificate2(bytes);
}
return clientCertificate;
};
});
services.AddControllers().AddNewtonsoftJson(o => o.SerializerSettings.ContractResolver = new DefaultContractResolver());
}
....
private static byte[] StringToByteArray(string hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var logger = new NLogger();
logger.Info("Application Configure started");

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCertificateForwarding();
app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware<ContentNegociationHandler>();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
logger.Info("Application Configure completed");
}
}

这是Program.cs

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(o =>
o.ClientCertificateMode =
ClientCertificateMode.RequireCertificate);
});
});
}

是否有理由不存储索赔?有变通办法吗?

编辑:设置Thread.CurrentPrincipal的图像之前控制器中Thread.CurrentPrincipal值的图像之后

找到了答案:你可以这样设置新身份:

context.Principal = principal;

然后我可以使用在控制器中检索新的主体

ControllerContext.HttpContext.User;

最新更新