- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试在桌面应用程序中使用 C# 使用 Java Web 服务。
My first attempt正在使用 WebServicesClientProtocol,但我无法添加 WSSE Username and Token Security Spec 1.1
我需要创建具有这种结构的请求:
<soap:Envelope xmlns:dz="http://dom.query.api.com" xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://dz.api.swd.zbp.pl/xsd">
<soap:Header>
<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">
<wsse:UsernameToken wsu:Id="UsernameToken-E94CEB6F4708FB7C23148611494797612">
<wsse:Username>my_login</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">XqEwZ/CxaBfFvh487TjvN8qD63c=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">JzURe0CxvzRjmEcH/ndldw==</wsse:Nonce>
<wsu:Created>2017-02-09T09:42:27.976Z</wsu:Created>
</wsse:UsernameToken>
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" wsu:Id="X509-E94CEB6F4708FB7C2314861149479517">MIIKnDCCB.........nmIngeg6d6TNI=</wsse:BinarySecurityToken>
<ds:Signature Id="SIG-E94CEB6F4708FB7C23148611494795311" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="dz soap xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-E94CEB6F4708FB7C23148611494795310">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="dz xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>mlABQuNUFOmLqsDswxXxQ6XnjpQ=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>lYhBHSQ/L...XL1HEbMQjJ/Q2Rvg==</ds:SignatureValue>
<ds:KeyInfo Id="KI-E94CEB6F4708FB7C2314861149479518">
<wsse:SecurityTokenReference wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" wsu:Id="STR-E94CEB6F4708FB7C2314861149479519" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd">
<wsse:Reference URI="#X509-E94CEB6F4708FB7C2314861149479517" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soap:Header>
<soap:Body wsu:Id="id-E94CEB6F4708FB7C23148611494795310" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<dz:query>
<dz:param>
<xsd:userQueryId>27467</xsd:userQueryId>
</dz:param>
</dz:query>
</soap:Body>
</soap:Envelope>
我已经设法使用 IEndpointBehavior 和 IClientMessageInspector 创建自定义类,但使用它们我只能添加 UsernameToken
public class InspectorBehavior : IEndpointBehavior
{
/// <summary>
/// Gets or sets the custom ClientInspector.
/// </summary>
public ClientInspector ClientInspector { get; set; }
/// <summary>
/// Constructs a new InspectorBehavior
/// </summary>
/// <param name="clientInspector"><see cref="ClientInspector"/></param>
public InspectorBehavior(ClientInspector clientInspector)
{
ClientInspector = clientInspector;
}
/// <summary>
/// Implement to confirm that the endpoint meets some intended criteria.
/// </summary>
/// <param name="endpoint"><see cref="ServiceEndpoint"/></param>
public void Validate(ServiceEndpoint endpoint)
{
// not calling the base implementation
}
/// <summary>
/// Implement to pass data at runtime to bindings to support custom behavior.
/// </summary>
/// <param name="endpoint"><see cref="ServiceEndpoint"/></param>
/// <param name="bindingParameters"><see cref="BindingParameterCollection"/></param>
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
// not calling the base implementation
}
/// <summary>
/// Implements a modification or extension of the service across an endpoint.
/// </summary>
/// <param name="endponit"><see cref="ServiceEndpoint"/></param>
/// <param name="endpointDispatcher"><see cref="EndpointDispatcher"/></param>
public void ApplyDispatchBehavior(ServiceEndpoint endponit, EndpointDispatcher endpointDispatcher)
{
// not calling the base implementation
}
/// <summary>
/// Implements the custom modification of the WCF client across an endpoint.
/// </summary>
/// <param name="endpoint"><see cref="ServiceEndpoint"/></param>
/// <param name="clientRuntime"><see cref="ClientRuntime"/></param>
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
if (this.ClientInspector == null)
throw new InvalidOperationException("Caller must supply ClientInspector.");
clientRuntime.ClientMessageInspectors.Add(ClientInspector);
}
}
public class ClientInspector : IClientMessageInspector
{
/// <summary>
/// Gets or sets the custom MessageHeader.
/// </summary>
public MessageHeader[] Headers
{
get;
set;
}
/// <summary>
/// Constructs a new ClientInspector
/// </summary>
/// <param name="headers"><see cref="MessageHeader"/></param>
public ClientInspector(params MessageHeader[] headers)
{
Headers = headers;
}
/// <summary>
/// Enables inspection or modification of a message before a request message is sent to a service.
/// </summary>
/// <param name="request"><see cref="Message"/></param>
/// <param name="channel"><see cref="IClientChannel"/></param>
/// <returns></returns>
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if (Headers != null)
{
for (int i = Headers.Length - 1; i >= 0; i--)
request.Headers.Insert(0, Headers[i]);
}
return request;
}
/// <summary>
/// Enables inspection or modification of a message after a reply message is received but
/// prior to passing it back to the client.
/// </summary>
/// <param name="reply"><see cref="Message"/></param>
/// <param name="correlationState">object</param>
public void AfterReceiveReply(ref Message reply, object correlationState)
{
// not calling the base implementation
}
}
public class SecurityHeader : MessageHeader
{
private readonly APIConfig config;
/// <summary>
/// Constructors a new SecurityHeader
/// </summary>
/// <param name="config"><see cref="APIConfig"/></param>
public SecurityHeader(APIConfig config)
{
this.config = config;
}
/// <summary>
/// Gets or sets a value that indicates whether the header must be understood, according to SOAP 1.1/1.2 specification.
/// </summary>
public override bool MustUnderstand
{
get
{
return true;
}
}
/// <summary>
/// Gets the name of the message header.
/// </summary>
public override string Name
{
get
{
return "Security";
}
}
/// <summary>
/// Gets the namespace of the message header.
/// </summary>
public override string Namespace
{
get
{
return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
}
}
protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
writer.WriteStartElement("wsse", Name, Namespace);
writer.WriteXmlnsAttribute("wsse", Namespace);
}
/// <summary>
/// Called when the header content is serialized using the specified XML writer.
/// </summary>
/// <param name="writer"><see cref="XmlDictionaryWriter"/></param>
/// <param name="messageVersion"><see cref="MessageVersion"/></param>
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
WriteHeader(writer);
}
/// <summary>
/// Overwrites the default SOAP Security Header values generated by WCF with
/// those required by the UserService which implements WSE 2.0. This is required
/// for interoperability between a WCF Client and a WSE 2.0 Service.
/// </summary>
/// <param name="writer"><see cref="XmlDictionaryWriter"/></param>
private void WriteHeader(XmlDictionaryWriter writer)
{
// Create the Nonce
byte[] nonce = GenerateNonce();
// Create the Created Date
string created = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
// Create the WSSE Security Header, starting with the Username Element
writer.WriteStartElement("wsse", "UsernameToken", Namespace);
writer.WriteXmlnsAttribute("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
writer.WriteStartElement("wsse", "Username", null);
writer.WriteString(config.Username);
writer.WriteEndElement();
// Add the Password Element
writer.WriteStartElement("wsse", "Password", null);
writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
writer.WriteString(GeneratePasswordDigest(nonce, created, config.Password));
writer.WriteEndElement();
// Add the Nonce Element
writer.WriteStartElement("wsse", "Nonce", null);
writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
writer.WriteBase64(nonce, 0, nonce.Length);
writer.WriteEndElement();
// Lastly, add the Created Element
writer.WriteStartElement("wsu", "Created", null);
writer.WriteString(created);
writer.WriteEndElement();
writer.WriteEndElement();
writer.Flush();
}
/// <summary>
/// Generates a random Nonce for encryption purposes
/// </summary>
/// <returns>byte[]</returns>
private byte[] GenerateNonce()
{
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
byte[] buf = new byte[0x10];
rand.GetBytes(buf);
return buf;
}
/// <summary>
/// Generates the PasswordDigest using a SHA1 Hash
/// </summary>
/// <param name="nonceBytes">byte[]</param>
/// <param name="created">string</param>
/// <param name="password">string</param>
/// <returns>string</returns>
private string GeneratePasswordDigest(byte[] nonceBytes, string created, string password)
{
// Convert the values to be hashed to bytes
byte[] createdBytes = Encoding.UTF8.GetBytes(created);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] msgBytes = new byte[nonceBytes.Length + createdBytes.Length + passwordBytes.Length];
// Combine the values into one byte array
Array.Copy(nonceBytes, msgBytes, nonceBytes.Length);
Array.Copy(createdBytes, 0, msgBytes, nonceBytes.Length, createdBytes.Length);
Array.Copy(passwordBytes, 0, msgBytes, (nonceBytes.Length + createdBytes.Length), passwordBytes.Length);
// Generate the hash
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] hashBytes = sha1.ComputeHash(msgBytes);
return Convert.ToBase64String(hashBytes);
}
}
public class APIConfig
{
/// <summary>
/// Gets or Sets the Password property
/// </summary>
public string Password
{
get;
set;
}
/// <summary>
/// Gets or Sets the Username property
/// </summary>
public string Username
{
get;
set;
}
}
使用上面的代码我可以创建这个请求:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>Demo</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">1TiCoKWfNF3EdEH3qdU4inKklaw=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">mAyz3SywR8sR9IkhDGJRIw==</wsse:Nonce>
<wsu:Created>2017-02-09T23:29:14.371Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<query xmlns="http://dom.query.api.com">
<param>
<userQueryId xsi:nil="true" xmlns="http://dom.query.api.com/xsd"/>
</param>
</query>
</s:Body>
</s:Envelope>
如您所见,我的 Security
元素中缺少 BinarySecurityToken
和 Signature
元素。我试过使用 Microsoft.Web.Services3
但没有成功。
例如 BinarySecurityToken
的构造函数是 protected 。
我在我的证书库中导入了我的客户端证书。我只需要在请求的正文上签名。
如何将这两个元素添加到 Header
内的 Security
元素?我知道我必须使用 Microsoft.Web.Services3
但我不知道如何使用。
我在网上搜索过类似的问题,但我找到的都是关于如何添加用户名和密码的教程,关于添加Signature
和BinarySecurityToken
的问题仍然没有答案- How to sign xml with X509 cert, add digest value and signature to xml template
最佳答案
此编码绑定(bind)应产生类似的消息:
var b = new CustomBinding();
var sec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);
sec.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
sec.MessageSecurityVersion =
MessageSecurityVersion.
WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
sec.IncludeTimestamp = false;
sec.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.EncryptBeforeSign;
b.Elements.Add(sec);
b.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
b.Elements.Add(new HttpsTransportBindingElement());
var c =
new ServiceReference1.SimpleServiceSoapClient(b, new EndpointAddress(new Uri("https://www.bankhapoalim.co.il/"), new DnsEndpointIdentity("WSE2QuickStartServer"), new AddressHeaderCollection()));
c.ClientCredentials.UserName.UserName = "yaron";
c.ClientCredentials.UserName.Password = "1234";
c.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
System.ServiceModel.Security.X509CertificateValidationMode.None;
c.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(@"C:\Program Files\Microsoft WSE\v2.0\Samples\Sample Test Certificates\Server Public.cer");
c.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(@"C:\Program Files\Microsoft WSE\v2.0\Samples\Sample Test Certificates\Client Private.pfx", "wse2qs");
c.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
您选择的路径需要您自己实现消息签名,这更难。
关于c# - ClientMessageInspector 添加 BinarySecurityToken 和签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42149068/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!