我正在尝试在C#中为我正在尝试连接的Web服务构建SAML断言。我使用SamlAssertion
和X509 Cert作为SigningCredentials
这会生成SamlSecurityToken
,然后我会序列化。当我尝试验证签名时,我收到一条错误消息,说明
格式错误的参考元素。
要序列化的代码
var result = new StringBuilder();
using (var writer = XmlWriter.Create(result))
{
var serializer = new WSSecurityTokenSerializer(SecurityVersion.WSSecurity11, true);
serializer.WriteToken(writer, obj); //Obj is the SamlSecurityToken
}
var xml = result.ToString();
生成签名:
<Signature
xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
<Reference URI="#_caeceed6-7006-4354-a398-75a8e4c52818">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>SOME VALUE</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>SOME VALUE</SignatureValue>
</Signature>
这几乎就是我从网络服务提供商那里得到的例子。部分示例:
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="code ds kind rw saml samlp typens #default xsd xsi"></ec:InclusiveNamespaces>
</ds:Transform>
除了一些前缀和 InclusiveNamespaces 标记外,示例和生成的XML看起来几乎相同。
我也看过人们使用SignedXml
代替WSSecurityTokenSerializer的例子,为什么会这样?更多地控制生成的XML?或者我可以不使用WSSecurityTokenSerializer来创建令牌吗?
答案 0 :(得分:1)
我根据Thuan发布的示例创建了一个类来返回正确的元素,我不得不用自定义搜索AssertionID来覆盖SignedXml类,以返回要验证的正确元素。
public class SignedSamlXml : SignedXml
{
public SignedSamlXml()
{
}
public SignedSamlXml(XmlDocument doc)
: base(doc)
{
}
public override XmlElement GetIdElement(XmlDocument document, string idValue)
{
var idElement = base.GetIdElement(document, idValue);
if (idElement == null)
{
var attributes = document.SelectNodes("//@AssertionID");
if (attributes == null) return null;
foreach (XmlAttribute attr in attributes)
{
if (attr.Value == idValue)
{
return attr.OwnerElement;
}
}
}
return idElement;
}
}