&НаКлиентеНаСервереБезКонтекста
Функция СоздатьСтруктуруWSSecurityДляSOAPсообщения2(СтрокаXML) Экспорт
// Построим DOM из строки XML.
ЧтениеXML_ = Новый ЧтениеXML;
ЧтениеXML_.УстановитьСтроку(СтрокаXML);
ПостроительDOM_ = Новый ПостроительDOM;
ДокументDOM_ = ПостроительDOM_.Прочитать(ЧтениеXML_);
// Корневой элемент - это SOAP-ENV:Envelope.
КорневойЭлемент_ = ДокументDOM_.ЭлементДокумента;
// Пространства имен SOAP версии 1.1 и 1.2 различаются,
// поэтому извлечем нужное пространство имен из корневого тега.
xmlnsSOAP_ENV_ = КорневойЭлемент_.URIПространстваИмен;
// Добавим в конверт тег SOAP-ENV:Header, если его не было.
Если Не "Header" = КорневойЭлемент_.ПервыйДочерний.ЛокальноеИмя Тогда
Header_ = ДокументDOM_.СоздатьЭлемент(xmlnsSOAP_ENV_, "Header");
КорневойЭлемент_.ВставитьПеред(Header_, КорневойЭлемент_.ПервыйДочерний);
КонецЕсли;
// Добавляем атрибут wsu:Id в тег <SOAP-ENV:Body>.
xmlns_wsu_ = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
wsuId_ = "uuid:" + Строка(Новый УникальныйИдентификатор);
// За следующие строки кода спасибо автору топика. Сам не смог догадаться.
Атрибут_wsuId_ = ДокументDOM_.СоздатьАтрибут(xmlns_wsu_, "wsu:Id");
Атрибут_wsuId_.Значение = wsuId_;
// ПоследнийДочерний - это тег <SOAP-ENV:Body>.
КорневойЭлемент_.ПоследнийДочерний.Атрибуты.УстановитьИменованныйЭлемент(Атрибут_wsuId_);
// Тег <wsse:Security> сформируем из строкового шаблона. Так гораздо более читабельно,
// чем работа с DOM.
// Параметрами шаблона выступают два атрибута wsu:Id и пространство имен SOAP-ENV.
Шаблон_wsseSecurity_ =
"<wsse:Security
| xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""
| xmlns:wsu=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd""
| xmlns:SOAP-ENV=""%3""
| SOAP-ENV:mustUnderstand=""1""
| SOAP-ENV:actor=""http://smev.gosuslugi.ru/actors/smev"">
| <wsse:BinarySecurityToken
| wsu:Id=""%1""
| ValueType=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3""
| EncodingType=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"">#Certificate_ENCODE_BASE64</wsse:BinarySecurityToken>
| <ds:Signature xmlns:ds=""http://www.w3.org/2000/09/xmldsig#"">
| <ds:SignedInfo>
| <ds:CanonicalizationMethod Algorithm=""http://www.w3.org/2001/10/xml-exc-c14n#""/>
| <ds:SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411""/>
| <ds:Reference URI=""#%2"">
| <ds:Transforms>
| <ds:Transform Algorithm=""http://www.w3.org/2001/10/xml-exc-c14n#""/>
| </ds:Transforms>
| <ds:DigestMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#gostr3411""/>
| <ds:DigestValue/>
| </ds:Reference>
| </ds:SignedInfo>
| <ds:SignatureValue/>
| <ds:KeyInfo>
| <wsse:SecurityTokenReference>
| <wsse:Reference
| ValueType=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3""
| URI=""#%1""/>
| </wsse:SecurityTokenReference>
| </ds:KeyInfo>
| </ds:Signature>
|</wsse:Security>"
;
Тег_wsseSecurity_ = СтрШаблон(
Шаблон_wsseSecurity_,
"uuid:" + Строка(Новый УникальныйИдентификатор),
wsuId_,
xmlnsSOAP_ENV_
);
// Полученную строку с тегом <wsse:Security> прочитаем в другой DOM.
ЧтениеXML_ = Новый ЧтениеXML;
ЧтениеXML_.УстановитьСтроку(Тег_wsseSecurity_);
ПостроительDOM_ = Новый ПостроительDOM;
ДокументDOM_wsseSecurity_ = ПостроительDOM_.Прочитать(ЧтениеXML_);
// Теперь перенесем тег <wsse:Security> из одного документа DOM в другой.
wsseSecurity_ = ДокументDOM_.ИмпортироватьУзел(ДокументDOM_wsseSecurity_.ЭлементДокумента, Истина);
// ПервыйДочерний - это <SOAP-ENV:Header>. Добавим в него тег <wsse:Security>.
КорневойЭлемент_.ПервыйДочерний.ДобавитьДочерний(wsseSecurity_);
// Осталось только записать DOM в строку.
ЗаписьXML_ = Новый ЗаписьXML;
ЗаписьXML_.УстановитьСтроку("UTF-8");
ЗаписьDOM_ = Новый ЗаписьDOM;
ЗаписьDOM_.КонфигурацияDOM.УстановитьПараметр("xml-declaration", Истина);
ЗаписьDOM_.КонфигурацияDOM.УстановитьПараметр("discard-default-content", Истина);
ЗаписьDOM_.Записать(ДокументDOM_, ЗаписьXML_);
СформированныйДокумент_ = ЗаписьXML_.Закрыть();
Возврат СформированныйДокумент_;
КонецФункции