使用Perl XML::Sig签名XML时dsig命名空间异常的问题咨询
使用Perl的XML::Sig签名XML时出现dsig前缀的问题
我尝试用Perl的XML::Sig库给XML文档签名,代码基于MetaCPAN示例修改后如下:
use XML::Sig; my $xml = '<?xml version="1.0"?><foo ID="abc"><bar>123</bar></foo>'; my $pkey = '/path/to/X509/private.key'; my $cert = '/path/to/X509/certificate.pem'; my $signer = XML::Sig->new({ key => $pkey, cert => $cert, x509 => 1, sig_hash => 'sha256', digest_hash => 'sha256' }); my $signedXml = $signer->sign($xml); print $signedXml;
预期输出中,签名相关元素直接声明http://www.w3.org/2000/09/xmldsig#命名空间,不会在foo标签添加dsig前缀,但实际输出里foo标签被加上了xmlns:dsig="http://www.w3.org/2000/09/xmldsig#",后续所有签名元素都使用dsig前缀,这修改了原文档结构,导致结构验证失败。请问该现象的原因是什么?如何移除这些dsig前缀?
问题原因
XML::Sig默认会将签名相关的命名空间绑定到dsig前缀,并把这个命名空间声明添加到被签名的根元素(即foo标签)上。这是因为库内部处理签名元素时,默认用前缀区分命名空间,且自动将命名空间声明提升到根节点,以保证整个文档的命名空间有效性。
解决方法
要移除dsig前缀,让签名元素直接使用默认命名空间,需在创建XML::Sig实例时指定prefix参数为空字符串,同时将dsig命名空间设为默认命名空间:
修改后的代码如下:
use XML::Sig; my $xml = '<?xml version="1.0"?><foo ID="abc"><bar>123</bar></foo>'; my $pkey = '/path/to/X509/private.key'; my $cert = '/path/to/X509/certificate.pem'; my $signer = XML::Sig->new({ key => $pkey, cert => $cert, x509 => 1, sig_hash => 'sha256', digest_hash => 'sha256', prefix => '', # 设置为空前缀 ns => 'http://www.w3.org/2000/09/xmldsig#' # 将该命名空间设为默认 }); my $signedXml = $signer->sign($xml); print $signedXml;
修改后,签名相关元素会直接使用http://www.w3.org/2000/09/xmldsig#作为默认命名空间,不会给根元素添加dsig前缀,签名元素也不会使用该前缀,从而保留原文档的结构。
注意:这种方式下签名元素属于默认命名空间,需确保原XML文档没有使用其他默认命名空间,否则可能引发命名空间冲突。
内容的提问来源于stack exchange,提问作者Jorge_Freitas
相关产品推荐
相关产品推荐

