- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
为此,我在网上找遍了。我一直在做这件事,但我尝试使用其 Web 服务的供应商拒绝正式支持 WCF 作为一种使用方法。
我不是 Web 服务专家,所以我会尽我所能在最初的帖子中记录和解释,但无论如何,如果您需要更多信息,请索取更多信息,希望我能够提供任何信息是必要的。
服务
在我的公司,我们使用公开服务的供应商应用程序。该应用程序是用 java 编写的,看起来 wsdl 是使用 Apache Axis 1.2 创建的。
代码
我的遗留代码使用 WSE 3.0。特别是,它使用了在末尾自动添加“WSE”的代理类。这使我可以使用更简单的身份验证方案(这是我让它工作的唯一方法)。我不需要使用证书。我使用 SecurityPolicyAssertion
的派生词,并将其包装在 Policy
对象中,该对象传递给客户端类的 SetPolicy
方法。这是创建客户端的工作实例所需要做的所有事情:
MyWebServiceWse api = new MyWebServiceWse();
api.Url = myUrl;
api.SetPolicy(new Policy(new MyDerivedSecurityAssertion(user, pass)));
我的 WCF 默认开箱即用代码(使用服务引用生成)不接受凭据,因此我知道马上就会出现问题。我在网上阅读了各种关于在我的 app.config
中使用不同的 security
或绑定(bind)设置的内容,但没有任何内容完全有效。经过大量修改后,我最常见的错误是 WSDoAllReceiver: Request does not contain required Security header
。
这是 app.config。或许我们可以先告诉我这里应该更改哪些内容以促进凭据的通过——同样,我在网上看到了不同的意见。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MySoapBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xyz:12345/services/MyService"
binding="basicHttpBinding" bindingConfiguration="MySoapBinding"
contract="MyNS.MyService" name="MyService" />
</client>
</system.serviceModel>
</configuration>
我更改了一些属性以模糊我们正在使用的特定服务(公司政策等)。
这是到目前为止的示例 C# 代码(在控制台应用程序中测试):
MyClient client = new MyClient();
client.listMethod();
更新
阅读这篇 SO 帖子:wcf security . . . .
我已经相应地更新了我的 app.config,现在正在代码中传递用户名和密码。我仍然收到同样的错误:
WSDoAllReceiver: Request does not contain required Security header
20120517 更新
一个成功的请求(来自 WSE3):
<soap:Header>
<wsa:Action>
</wsa:Action>
<wsa:MessageID>urn:uuid:cb739422-c077-4eec-8cb2-686837b76878</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://removed-for-security</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-e13feaf9-33d9-47bf-ab5b-60b4611eb81a">
<wsu:Created>2012-05-17T11:25:41Z</wsu:Created>
<wsu:Expires>2012-05-17T11:30:41Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-00c26e1a-3b3b-400f-a99a-3aa54cf8c8ff">
<wsse:Username>change-to-protect-the-innocent</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">nice-try</wsse:Password>
<wsse:Nonce>KJMvUuWF2eO2uIJCuxJC4A==</wsse:Nonce>
<wsu:Created>2012-05-17T11:25:41Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<listChannels xmlns="http://removed-for-security">
<rowfrom>0</rowfrom>
<rowto>10</rowto>
</listChannels>
</soap:Body>
</soap:Envelope>
正在获取 WCF 跟踪——将很快添加。
20120517 更新 2
这是来自 WCF 的信封:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none"></Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<listChannels xmlns="http://removed-for-security">
<rowfrom>1</rowfrom>
<rowto>2147483647</rowto>
</listChannels>
</s:Body>
</s:Envelope>
20120518 更新我已经尝试在 Mike Miller 在评论中链接到的帖子中实现解决方案。现在我收到以下错误(没有消息最终被发送,因为该方案有问题):
The provided URI scheme 'http' is invalid; expected 'https'.
如果有人想问,是的,我需要通过 http 发送,是的,我知道凭据是作为未加密的字符串发送的:-)
最佳答案
您需要通过 wcf ootb 不支持的 http 传输发送用户名 token 。此外,您的 token 使用 nonce/created,这也不是 ootb。你有两个选择:
这oss project将 nonce/created 添加到用户名 token 。这个oss project添加通过 http 发送用户名的功能。您需要将这两个项目组合在一起。
ws-security 通常被认为很复杂,但您可以以最简单的形式(用户名)使用它。最简单的方法是一起取消所有 wcf 安全设置,并在 message inspector 中自己创建整个安全 header 。 !如您所见,大多数 header 只是静态 xml 节点,并且大多数值都非常清楚(您知道用户名)。唯一棘手的两个是 nonce 和时间戳,您可以在此 oss project 中查看如何操作(每行一行)。此选项有一个变体可能更容易 - 使用 CUB毕竟并实现 custom encoder这插入了 timestmpa/nonce。我会选择后者,但我有偏见,因为我开发了 CUB...
还有 ws-addressing header ,您可以在自定义编码“messageVersion”属性上进行配置。我无法说出确切的值,因为您省略了带有 wsa 前缀定义的信封 header 。
如果您想私下寻求帮助(因为您似乎有安全限制),请务必通过 my blog 给我发一封电子邮件.
编辑:我已经为您实现了它。请按照以下步骤操作:
下载 cub并让自己熟悉它(不是内部结构,只是根据博客文章如何使用它)
将对 System.Runtime.Serialization.dll 的引用添加到项目 ClearUsernameBinding
向该项目添加一个新文件:UsernameExEncoder.cs。粘贴此内容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.IO;
using System.Xml;
using System.Security.Cryptography;
namespace Webservices20.BindingExtensions
{
class UsernameExEncoderBindingElement : MessageEncodingBindingElement
{
MessageEncodingBindingElement inner;
public UsernameExEncoderBindingElement(MessageEncodingBindingElement inner)
{
this.inner = inner;
}
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
context.BindingParameters.Add(this);
var res = base.BuildChannelFactory<TChannel>(context);
return res;
}
public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
{
var res = base.CanBuildChannelFactory<TChannel>(context);
return res;
}
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new UsernameExEncoderFactory(this.inner.CreateMessageEncoderFactory());
}
public override MessageVersion MessageVersion
{
get
{
return this.inner.MessageVersion;
}
set
{
this.inner.MessageVersion = value;
}
}
public override BindingElement Clone()
{
var c = (MessageEncodingBindingElement)this.inner.Clone();
var res = new UsernameExEncoderBindingElement(c);
return res;
}
public override T GetProperty<T>(BindingContext context)
{
var res = this.inner.GetProperty<T>(context);
return res;
}
}
class UsernameExEncoderFactory : MessageEncoderFactory
{
MessageEncoderFactory inner;
public UsernameExEncoderFactory(MessageEncoderFactory inner)
{
this.inner = inner;
}
public override MessageEncoder Encoder
{
get { return new UsernameExEncoder(inner.Encoder); }
}
public override MessageVersion MessageVersion
{
get { return this.inner.MessageVersion; }
}
}
class UsernameExEncoder : MessageEncoder
{
MessageEncoder inner;
public override T GetProperty<T>()
{
return inner.GetProperty<T>();
}
public UsernameExEncoder(MessageEncoder inner)
{
this.inner = inner;
}
public override string ContentType
{
get { return this.inner.ContentType; }
}
public override string MediaType
{
get { return this.inner.MediaType; }
}
public override MessageVersion MessageVersion
{
get { return this.inner.MessageVersion; }
}
public override bool IsContentTypeSupported(string contentType)
{
return this.inner.IsContentTypeSupported(contentType);
}
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
return this.inner.ReadMessage(buffer, bufferManager, contentType);
}
public override Message ReadMessage(System.IO.Stream stream, int maxSizeOfHeaders, string contentType)
{
return this.inner.ReadMessage(stream, maxSizeOfHeaders, contentType);
}
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
//load the message to dom
var mem = new MemoryStream();
var x = XmlWriter.Create(mem);
message.WriteMessage(x);
x.Flush();
mem.Flush();
mem.Position = 0;
XmlDocument doc = new XmlDocument();
doc.Load(mem);
//add the missing elements
var token = doc.SelectSingleNode("//*[local-name(.)='UsernameToken']");
var created = doc.CreateElement("Created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
var nonce = doc.CreateElement("Nonce", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
token.AppendChild(created);
token.AppendChild(nonce);
//set nonce value
byte[] nonce_bytes = new byte[16];
RandomNumberGenerator rndGenerator = new RNGCryptoServiceProvider();
rndGenerator.GetBytes(nonce_bytes);
nonce.InnerText = Convert.ToBase64String(nonce_bytes);
//set create value
created.InnerText = XmlConvert.ToString(DateTime.Now.ToUniversalTime(), "yyyy-MM-ddTHH:mm:ssZ");
//create a new message
var r = XmlReader.Create(new StringReader(doc.OuterXml));
var newMsg = Message.CreateMessage(message.Version, message.Headers.Action, r);
return this.inner.WriteMessage(newMsg, maxMessageSize, bufferManager, messageOffset);
}
public override void WriteMessage(Message message, System.IO.Stream stream)
{
this.inner.WriteMessage(message, stream);
}
}
}
在文件 ClearUsernameBinding.cs 中替换为:
res.Add(new TextMessageEncodingBindingElement() { MessageVersion = this.messageVersion});
用这个:
var textEncoder = new TextMessageEncodingBindingElement() { MessageVersion = this.messageVersion };
res.Add(new UsernameExEncoderBindingElement(textEncoder));
在 app.config 的项目 TestClient 中,绑定(bind)元素上有一个 messageVersion 属性。您尚未发布信封的根目录,因此我无法确定,但您可能需要将其设置为 Soap11WSAddressingAugust2004 或 Soap11WSAddressing10(或其中之一改为使用 Soap12)。
祝你好运!
关于c# - (尝试)从 WSE 3.0 迁移到 WCF 以获取客户端代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10589561/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!