You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 20:42:31