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

ITfoxtec Identity SAML2生成SAML请求时Destination端口443被移除如何处理

SAML请求Destination字段443端口丢失解决方案

问题根源

.NET的Uri类默认会自动省略HTTPS协议的默认端口443、HTTP协议的默认端口80,你传入带443的地址构造Uri对象后,其标准化输出的AbsoluteUri属性会自动删除端口,而你使用的ITfoxtec Identity SAML2库序列化Destination字段时默认读取Uri的标准化值,所以最终生成的请求就丢失了443端口,无法通过对端IdP的校验。

可行解决方案

方案1:直接修改绑定后的请求XML(最易实现,兼容性最好)

你可以在调用Bind方法生成SAML请求后,直接修改XML根节点的Destination属性为你配置的原始带端口地址,不需要调整原有逻辑:

Saml2Configuration samlconfig = GetSAMLConfig();
// 先取出原始带端口的Destination地址备用
string rawDestination = _appConfiguration["Saml2:SingleSignOnDestination"];

var samlRequest = new Saml2AuthnRequest(samlconfig);
samlRequest.AssertionConsumerServiceUrl = new Uri(_appConfiguration["Saml2:AssertionConsumerServiceUrl"]); 
samlRequest.Destination = new Uri(rawDestination);

samlRequest.NameIdPolicy = new NameIdPolicy()
{
    AllowCreate = false,
    Format = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
    SPNameQualifier = _appConfiguration["Saml2:SPNameQualifier"]
};

samlRequest.Conditions = new Condition();
samlRequest.Conditions.Items = new List<ITfoxtec.Identity.Saml2.Schemas.Conditions.ICondition>();
samlRequest.Conditions.Items.Add(new ITfoxtec.Identity.Saml2.Schemas.Conditions.AudienceRestriction() { Audiences = new List<Audience>() { new Audience() { Uri = _appConfiguration["Saml2:AllowedAudienceUris"] } } });

var bnd = binding.Bind(samlRequest);
// 新增:强制替换Destination为原始带端口的地址
bnd.Xml.DocumentElement.SetAttribute("Destination", rawDestination);

如果你的请求是签名请求,要确保修改XML的操作在签名生成之前完成,若默认Bind方法已经内置签名逻辑,你可以改用方案2。

方案2:自定义SAML请求类覆写序列化逻辑(签名场景适用)

继承官方Saml2AuthnRequest类,重写XML属性序列化逻辑,强制写入你需要的原始Destination地址:

// 自定义请求类
public class PortReservedSaml2AuthnRequest : Saml2AuthnRequest
{
    // 存储原始带端口的Destination地址
    public string OriginalDestination { get; set; }
    public PortReservedSaml2AuthnRequest(Saml2Configuration config) : base(config) { }

    protected override void WriteXmlAttributes(XmlWriter writer)
    {
        base.WriteXmlAttributes(writer);
        // 序列化时直接写入原始地址,覆盖Uri标准化后的值
        if (!string.IsNullOrWhiteSpace(OriginalDestination))
        {
            writer.WriteAttributeString("Destination", OriginalDestination);
        }
    }
}

替换原有代码中的请求实例即可:

string rawDestination = _appConfiguration["Saml2:SingleSignOnDestination"];
var samlRequest = new PortReservedSaml2AuthnRequest(samlconfig);
samlRequest.OriginalDestination = rawDestination;
// 其他赋值逻辑保持不变

方案3:全局配置Uri不省略默认端口(.NET 6+适用)

如果你的项目是.NET 6及以上版本,可以在程序启动时加全局配置,让Uri序列化时保留默认端口:

// Program.cs启动时添加
AppContext.SetSwitch("System.Uri.DisableDefaultPortInSerialization", true);

这个配置全局生效,开启后所有Uri对象的AbsoluteUri输出都会保留80/443端口,不需要修改SAML相关代码,适合全项目都需要保留默认端口的场景。

注意事项

  • 若使用Redirect绑定方式,修改XML后需要重新生成签名并做URL编码,避免请求校验失败
  • 确保替换的Destination地址和你配置的原始值完全一致,不要有多余的转义字符

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 14:45:05