C# .net core 5.0 CurrentPrincipal重置值
我有一个.net core 5.0应用程序,它需要额外的证书验证,并根据证书在db中获得某些角色。我将这些作为声明存储在Thread.CurrentPrincipal或HttpContext.User中。但当调用到达控制器时,这两个函数都会返回其默认值 这是Startup.csC# .net core 5.0 CurrentPrincipal重置值,c#,.net-core,current-principal,C#,.net Core,Current Principal,我有一个.net core 5.0应用程序,它需要额外的证书验证,并根据证书在db中获得某些角色。我将这些作为声明存储在Thread.CurrentPrincipal或HttpContext.User中。但当调用到达控制器时,这两个函数都会返回其默认值 这是Startup.cs public class Startup { public Startup(IConfiguration configuration) { Configuration = configur
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");
}
}
公共类启动
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
....
//此方法由运行时调用。请使用此方法将服务添加到容器中。
public void配置服务(IServiceCollection服务)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(选项=>
{
options.RevocationMode=X509RevocationMode.NoCheck;
options.AllowedCertificateTypes=CertificateTypes.All;
options.Events=新的CertificateAuthenticationEvents
{//container.Resolve();
OnCertificateValidated=上下文=>
{
如果(!ValidateCertificate(context.ClientCertificate))
{
CreateErrorResponse(上下文、StatusCodes.Status403禁止、MalocConstants.NoValidClientCertificateReceived);
返回Task.CompletedTask;
}
var certRoles=certificateProcessor.GetRoleIDs(context.ClientCertificate)
var roleClaims=certRoles.Roles.Distinct().OrderBy(r=>r)
.Select(s=>newclaim(ClaimsHelper.MALoInternalRole,s.ToString(CultureInfo.InvariantCulture),typeof(int.Name)).ToList();
var id=newclaimsidentity(roleClaims,AuthenticationType.X509.ToString());
var principal=newclaimsprincipal(new[]{id});
Thread.CurrentPrincipal=主体;
context.HttpContext.User=主体;
context.Success();
返回Task.CompletedTask;
}
};
});
services.AddCertificateForwarding(选项=>
{
options.CertificateHeader=“X-SSL-CERT”;
options.HeaderConverter=(headerValue)=>
{
X509Certificate2 clientCertificate=null;
如果(!string.IsNullOrWhiteSpace(headerValue))
{
字节[]字节=StringToByteArray(headerValue);
clientCertificate=新的X509Certificate2(字节);
}
返回客户证书;
};
});
services.AddControllers().AddNewtonsoftJson(o=>o.SerializerSettings.ContractResolver=new DefaultContractResolver());
}
....
私有静态字节[]StringToByteArray(字符串十六进制)
{
int numbercars=十六进制长度;
字节[]字节=新字节[numbercars/2];
对于(int i=0;i
{
endpoints.MapControllers();
});
logger.Info(“应用程序配置完成”);
}
}
这是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);
});
});
}
公共类程序
{
公共静态void Main(字符串[]args)
{
CreateHostBuilder(args.Build().Run();
}
公共静态IHostBuilder CreateHostBuilder(字符串[]args)=>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext,logging)=>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog()
.ConfigureWebHostDefaults(webBuilder=>
{
webBuilder.UseStartup();
webBuilder.ConfigureKestrel(选项=>
{
选项。配置HttpSDEFULTS(o=>
o、 客户认证模块=
客户认证模式。要求重新认证);
});
});
}
是否有理由不存储索赔?有解决办法吗
编辑:设置线程的图像。CurrentPrincipal
. 控制器中线程.CurrentPrincipal
值的图像
找到了答案:
您可以按如下方式设置新标识:
context.Principal = principal;
然后我可以使用以下命令在controller中检索新主体:
ControllerContext.HttpContext.User;
你在哪里回写数据库?@jdweng我没有。我只从数据库中读取数据。我获取当前证书的角色,并希望将这些角色作为声明存储在CurrentPrincipal中。您正在写入Thread.CurrentPrincipal,它不是CurrentPrincipal。我将CurrentPrincipal作为一般术语写入,因为我尝试同时使用Thread.CurrentPrincipal和来存储它,但当调用到达控制器时,它们都被重置。控制器解析接收响应。在控制器中解析响应后,必须更改值。