【发布时间】:2021-09-01 09:52:59
【问题描述】:
我在 Visual Studio 2019 中添加了一个连接引用。它使用了一个 https 端点,并将所需的所有绑定信息创建到一个 reference.cs 文件中。
它没有生成任何App.config 文件,所以我怀疑我需要的东西被捆绑到reference.cs 文件中。确实,仔细研究一下,它大多是。
所以我尝试创建一个客户端,以两种方式指定客户端凭据,如您所见,但不管我如何指定它,在下面调用此代码时都会出现异常。
public async Task SendFile(Stream fileStream, string fileName, Guid machineKey)
{
_logger.LogInformation("Starting file sending to Manager 1.");
_logger.LogInformation($"Sending file {fileName} from Machine {machineKey}");
try
{
var client = new FileTransferClient(FileTransferClient.EndpointConfiguration.BasicHttpBinding_IFileTransfer, _options.FileTransferEndPoint)
{
ClientCredentials =
{
UserName =
{
UserName = _options.FileTransferUsername,
Password = _options.FileTransferPassword
}
}
};
client.ClientCredentials.UserName.UserName = _options.FileTransferUsername;
client.ClientCredentials.UserName.Password = _options.FileTransferPassword;
using (new OperationContextScope(client.InnerChannel))
{
}
await client.UploadAsync(new FileUploadMessage
{
// Assume that this is enough. Can't really supply file length...
FileInfo = new FileTransferInfo
{
TransferId = new Guid(),
MachineUUID = machineKey.ToString(),
Name = fileName
},
TransferStream = fileStream
});
}
catch (Exception e)
{
_logger.LogError("An unexpected exception occurred while sending file to Manager 1G.", e);
}
_logger.LogInformation("File sending finished.");
}
例外是"The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic Realm'."
我比较了使用前面提到的App.config 的类似 API,并编辑了 reference.cs 以匹配我认为它应该具有的安全性。
具体来说,我在这里添加了与安全相关的行:
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IFileTransfer))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
result.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
result.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
return result;
}
if ((endpointConfiguration == EndpointConfiguration.MetadataExchangeHttpsBinding_IFileTransfer))
{
System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
result.Elements.Add(textBindingElement);
System.ServiceModel.Channels.HttpsTransportBindingElement httpsBindingElement = new System.ServiceModel.Channels.HttpsTransportBindingElement();
httpsBindingElement.AllowCookies = true;
httpsBindingElement.MaxBufferSize = int.MaxValue;
httpsBindingElement.MaxReceivedMessageSize = int.MaxValue;
result.Elements.Add(httpsBindingElement);
return result;
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
我发现令人震惊的是,在调用设置 ClientCredentials 的构造函数中嵌入时,当我检查带有调试会话的 client 时,它们并没有以任何方式填充。因此我尝试在之后专门设置它。
但无论哪种方式,最终结果都是一样的,得到同样的错误。
如何解决代码中的错误?
理论上我可以尝试添加App.config 并在那里执行,但我不知道合同。而且我不确定在生成的reference.cs 中寻找什么来识别它。所以我更喜欢通过代码来学习这样做,因为合同已经在那里,我可以通过_options 提供端点,所以它应该能够配置不同的环境。
【问题讨论】:
-
请编辑您的问题,并以 text 的形式提供代码、错误消息和其他 基于文本的信息,而不是作为截屏。谢谢。
-
根据要求从图片更改为基于文本的信息。
标签: c# authentication wcf