如何从ASP.NET Core服务器端验证Unity游戏客户端真实性?
IIS 10下ASP.NET Core 6证书认证仅OnChallenged触发的问题排查与解决
问题背景
部署了启用HTTP/HTTPS的ASP.NET Core 6服务器,运行环境为IIS 10。实现了CertValidationService类处理客户端证书认证逻辑,配置了证书认证服务并为指定路由添加了证书认证授权。但访问需授权的weather路由时,仅OnChallenged事件触发,ValidateCertificate方法、OnSuccess及OnFailed事件均未触发,无法验证Unity游戏客户端的真实性。
相关代码
CertValidationService类代码
public class CertValidationService { public bool ValidateCertificate(X509Certificate2 clientCertificate) { Log("\nInside validate"); //NOT triggered /*my custom verification logic*/ return true; } public static void Handler(CertificateAuthenticationOptions options) { Log("\nCalled handler"); //NOT triggered options.AllowedCertificateTypes = CertificateTypes.All; options.Events = new CertificateAuthenticationEvents { OnAuthenticationFailed = OnFailed, OnCertificateValidated = OnSuccess, OnChallenge = OnChallenged }; } private static Task OnChallenged(CertificateChallengeContext context){ Log("\nInside challenge"); return Task.CompletedTask; //triggered } private static Task OnFailed(CertificateAuthenticationFailedContext context){ context.Fail("Failed!"); return Task.CompletedTask; //NOT triggered } private static Task OnSuccess(CertificateValidatedContext context){ Log("\nInside OnSuccess"); //NOT triggered var validationService = context.HttpContext.RequestServices.GetService<CertValidationService>(); if (validationService != null && validationService.ValidateCertificate(context.ClientCertificate)){ Log("\nValidated!"); var claims = new List<Claim>{ new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.SubjectName.Name), new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer) }; context.Principal = new ClaimsPrincipal( new ClaimsIdentity( claims, context.Scheme.Name //CertificateAuthenticationDefaults.AuthenticationScheme ) ); context.Success(); } else { Log("\nBad Certificate"); context.Fail("Bad Certificate"); } return Task.CompletedTask; } public static void Log(string log) { string path = "logs.txt"; try { File.AppendAllText(path, log); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
服务器配置代码
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); // ADDED VALIDATION builder.Services.AddSingleton<CertValidationService>(); builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(CertValidationService.Handler); // ---------------- builder.Services.Configure<IISServerOptions>(options => { options.AllowSynchronousIO = true; }); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
路由控制器代码
// baseURL/myroute/weather [ApiController] [Route("myroute")] public class WeatherForecastController : ControllerBase { [HttpGet(Name = "weather")] [Authorize(AuthenticationSchemes = CertificateAuthenticationDefaults.AuthenticationScheme)] public string<WeatherForecast> Get() { return "data"; } [HttpGet(Name = "weather_noauth")] public string<WeatherForecast2> Get() { return "data"; } }
排查与解决步骤
1. 检查IIS站点的客户端证书配置
IIS作为反向代理时,必须正确配置SSL设置才能将客户端证书传递给ASP.NET Core应用:
- 打开IIS管理器,找到目标站点,进入SSL设置
- 勾选要求SSL
- 在客户端证书选项中选择接受或要求(根据业务需求,若强制验证选要求)
- 点击应用保存配置
2. 配置ASP.NET Core转发客户端证书
在IIS环境下,需要配置让ASP.NET Core接收IIS转发的客户端证书:
修改服务器配置代码,替换原有IISServerOptions配置为IISOptions:
// 替换原有的IISServerOptions配置 builder.Services.Configure<IISOptions>(options => { options.ForwardClientCertificate = true; });
3. 修正证书认证中间件配置
确保AddCertificate的配置逻辑被正确执行,可调整为直接内联配置替代静态Handler,避免静态方法调用问题:
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(options => { CertValidationService.Log("\nCalled handler"); options.AllowedCertificateTypes = CertificateTypes.All; // 若使用自签名证书,可禁用证书链验证(生产环境谨慎使用) // options.ValidateCertificateChain = false; options.Events = new CertificateAuthenticationEvents { OnAuthenticationFailed = CertValidationService.OnFailed, OnCertificateValidated = CertValidationService.OnSuccess, OnChallenge = CertValidationService.OnChallenged }; });
4. 修正控制器路由冲突问题
控制器中存在两个同名的Get方法,会导致路由匹配异常,修改路由配置:
[ApiController] [Route("myroute")] public class WeatherForecastController : ControllerBase { // 明确指定路由路径 [HttpGet("weather")] [Authorize(AuthenticationSchemes = CertificateAuthenticationDefaults.AuthenticationScheme)] public string<WeatherForecast> GetWeather() { return "data"; } [HttpGet("weather_noauth")] public string<WeatherForecast2> GetWeatherNoAuth() { return "data"; } }
5. 验证客户端是否正确携带证书
使用Fiddler或Postman模拟请求,确认Unity客户端在HTTPS请求中正确附加了客户端证书:
- 若测试工具携带证书后能触发
OnSuccess事件,说明问题出在Unity客户端的证书传递逻辑 - 若仍无法触发,检查证书是否为有效证书(如是否在服务器信任列表中)
内容的提问来源于stack exchange,提问作者SKB_BGPL
相关产品推荐
相关产品推荐

