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

单元测试ExternalAuthenticationService遇空引用异常,缺失哪些配置?

问题:Saml2RedirectBinding.Bind抛出NullReferenceException,缺失必要配置项?

我正尝试为ExternalAuthenticationService类编写单元测试,测试RedirectToLogin方法并确保RelayStateQuery被正确填充:

public IActionResult RedirectToLogin(LoginInfo loginInfo)
{
    var binding = new Saml2RedirectBinding();

    var dict = new Dictionary<string, string>
    {
        { "SomeKey", info.SomeStringIWantToRoundTrip }
    };

    binding.SetRelayStateQuery(dict);
            
    return binding.Bind(new Saml2AuthnRequest(config)).ToActionResult();
}

测试代码如下:

public class ExternalAuthenticationServiceTests
{
    private IExternalAuthenticationService service;
    public ExternalAuthenticationServiceTests()
    {
        var testCertificate = GenerateCertificate("Test Certificate");
        var config = new Saml2Configuration
        {
            CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
            Issuer = "http://wonderwoman.com",
            RevocationMode = X509RevocationMode.NoCheck,
            SignatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
            SigningCertificate = testCertificate
        };
        service = new ExternalAuthenticationService(config);
    }


    [Fact]
    public void RedirectToLogin_sets_tenantName_in_RelayStateQuery()
    {
        LoginInfo loginInfo = new() { 
           SomeStringIWantToRoundTrip = "user location or whatever" 
        };
        var result = service.RedirectToLogin(loginInfo);
    }

    private X509Certificate2 GenerateCertificate(string subjectName)
    {
        // Generate a new RSA key pair
        using var rsa = RSA.Create(2048);
        // Create a certificate request
        CertificateRequest request = new($"CN={subjectName}", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

        // Set certificate validity dates
        DateTimeOffset now = DateTimeOffset.UtcNow;
        request.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
        request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, false));
        request.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false));
        request.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(request.PublicKey, false));

        // Create a self-signed certificate
        X509Certificate2 certificate = request.CreateSelfSigned(now, now.AddYears(1));

        // Return the generated certificate
        return certificate;
    }
  }
}

运行测试时,还没添加断言就抛出异常:

Message: 
System.NullReferenceException : Object reference not set to an instance of an object.

Stack Trace:

Saml2RedirectBinding.BindInternal(Saml2Request saml2RequestResponse, String messageName)
Saml2Binding`1.Bind(Saml2Request saml2Request)
ExternalAuthenticationService.RedirectToLogin(LoginInfo loginInfo) line 39

我推测Saml2Configuration类缺少未配置的必要属性,但无法确定具体项,请问我遗漏了什么?


解答

这个空引用异常是因为Saml2AuthnRequest缺少必要的目标地址配置,而这依赖于Saml2Configuration中配置的身份提供者(IdP)信息。具体来说,你需要在Saml2Configuration中添加一个IdentityProvider,并设置其SingleSignOnServiceLocation,否则在生成AuthnRequest时无法确定跳转目标,导致绑定过程中出现空引用。

解决步骤

  1. 修改测试中的配置,添加IdentityProvider信息
var config = new Saml2Configuration
{
    CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
    Issuer = "http://wonderwoman.com",
    RevocationMode = X509RevocationMode.NoCheck,
    SignatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
    SigningCertificate = testCertificate
};

// 添加必要的IdP配置
var idp = new Saml2IdentityProvider(new EntityId("http://test-idp.com"))
{
    SingleSignOnServiceLocation = new Uri("http://test-idp.com/sso"),
    SigningCertificates = { testCertificate } // 测试环境可复用自签证书,实际场景需使用IdP的公钥证书
};
config.IdentityProviders.Add(idp);
// 设置默认IdP,让AuthnRequest自动使用该配置
config.DefaultIdentityProvider = "http://test-idp.com";
  1. 可选:显式指定AuthnRequest的目标地址
    如果服务类中未自动关联默认IdP,可在RedirectToLogin方法中显式设置:
var authnRequest = new Saml2AuthnRequest(config)
{
    Destination = config.IdentityProviders.First().SingleSignOnServiceLocation.AbsoluteUri
};
return binding.Bind(authnRequest).ToActionResult();

核心原因是SAML的AuthnRequest必须包含目标IdP的单点登录地址,你的配置中缺少这一关键信息,导致绑定过程中尝试访问未初始化的属性,最终抛出NullReferenceException。


内容的提问来源于stack exchange,提问作者Scott Baker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 12:37:02