Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе показано, как включить безопасность транспорта в службе Windows Communication Foundation (WCF), которая находится в домене Windows и вызывается клиентами в том же домене. Дополнительные сведения об этом сценарии см. в статье Транспортная безопасность с проверкой подлинности Windows. Пример приложения см. в примере WSHttpBinding .
Этот раздел предполагает, что у вас уже определены существующий интерфейс контракта и его реализация, и дополняет эти сведения. Вы также можете изменять существующие службы и клиентов.
Вы можете защитить службу, используя учетные данные Windows полностью на уровне кода. Кроме того, можно опустить часть кода, воспользовавшись файлом конфигурации. В этом разделе описаны оба метода. Убедитесь, что используете только один из методов, а не оба.
Первые три процедуры показывают, как защитить службу с помощью кода. Четвертая и пятая процедуры показывают, как сделать это с помощью файла конфигурации.
Использование кода
Полный код для службы и клиента приводится в подразделе "Примеры" в конце данного раздела.
В первой процедуре описывается создание и настройка класса WSHttpBinding в коде. Привязка использует транспорт HTTP. Та же привязка используется в клиенте.
Создание привязки WSHttpBinding, использующей учетные данные Windows и безопасность сообщений
Код этой процедуры вставлен в начало кода метода
RunклассаTestв коде службы, приведенном в подразделе "Примеры".Создайте экземпляр класса WSHttpBinding.
Задайте свойству Mode класса WSHttpSecurity значение Message.
Задайте свойству ClientCredentialType класса MessageSecurityOverHttp значение Windows.
Для данной процедуры используется следующий код.
// First procedure: // create a WSHttpBinding that uses Windows credentials and message security WSHttpBinding myBinding = new WSHttpBinding(); myBinding.Security.Mode = SecurityMode.Message; myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;Dim myBinding As New WSHttpBinding() myBinding.Security.Mode = SecurityMode.Message myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
Использование привязки в сервисе
Это вторая процедура, в которой показано, как использовать привязку в резидентной службе. Для получения дополнительной информации о хостинговых услугах см. Службы хостинга.
Использование привязки в службе
Вставьте код этой процедуры после кода предыдущей процедуры
Создайте переменную Type с именем
contractTypeи присвойте ей тип интерфейса (ICalculator). При использовании Visual Basic используйте операторGetType; при использовании C# используйте ключевое словоtypeof.Создайте вторую переменную Type с именем
serviceTypeи присвойте ей тип реализованного контракта (Calculator).Создайте экземпляр класса Uri с именем
baseAddressс базовым адресом службы. Базовый адрес должен иметь схему, которая соответствует транспорту. В этом случае схема транспорта — HTTP, а адрес включает специальный универсальный идентификатор ресурса (URI) localhost и номер порта (8036), а также базовый адрес конечной точки ("serviceModelSamples/):http://localhost:8036/serviceModelSamples/Создайте экземпляр класса ServiceHost с переменными
serviceTypeиbaseAddress.Добавьте конечную точку в сервис, используя
contractType, привязку и имя конечной точки (secureCalculator). При инициировании вызова службы клиент должен объединять базовый адрес и имя конечной точки.Чтобы запустить службу, вызовите метод Open. Код для данной процедуры показан далее.
// 2nd Procedure: // Use the binding in a service // Create the Type instances for later use and the URI for // the base address. Type contractType = typeof(ICalculator); Type serviceType = typeof(Calculator); Uri baseAddress = new Uri("http://localhost:8036/SecuritySamples/"); // Create the ServiceHost and add an endpoint, then start // the service. ServiceHost myServiceHost = new ServiceHost(serviceType, baseAddress); myServiceHost.AddServiceEndpoint (contractType, myBinding, "secureCalculator"); //enable metadata ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; myServiceHost.Description.Behaviors.Add(smb); myServiceHost.Open();' Create the Type instances for later use and the URI for ' the base address. Dim contractType As Type = GetType(ICalculator) Dim serviceType As Type = GetType(Calculator) Dim baseAddress As New Uri("http://localhost:8036/serviceModelSamples/") ' Create the ServiceHost and add an endpoint, then start ' the service. Dim myServiceHost As New ServiceHost(serviceType, baseAddress) myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator") myServiceHost.Open()
Использование привязки в клиентском приложении
Эта процедура показывает, как создать прокси, взаимодействующий со службой. Прокси-сервер создается с помощью средства служебной программы метаданных ServiceModel (Svcutil.exe), которая использует метаданные службы для создания прокси-сервера.
Эта процедура также создает экземпляр класса WSHttpBinding для взаимодействия со службой, а затем вызывает службу.
В этом примере для создания клиента используется только код. В качестве альтернативы можно использовать файл конфигурации, показанный в следующем после этой процедуры разделе.
Использование привязки в клиенте с кодом
Используйте средство SvcUtil.exe, чтобы создать код прокси из метаданных службы. Дополнительные сведения см. в разделе "Практическое руководство. Создание клиента". Созданный прокси-код наследует от ClientBase<TChannel> класса, что гарантирует, что каждый клиент имеет необходимые конструкторы, методы и свойства для взаимодействия со службой WCF. В данном примере созданный код включает класс
CalculatorClient, который реализует интерфейсICalculator, тем самым обеспечивая совместимость с кодом службы.Код этой процедуры вставляется в начало метода
Mainпрограммы клиента.Создайте экземпляр класса WSHttpBinding и задайте его режиму безопасности значение
Message, а его типу учетных данных клиента -Windows. В примере называется переменнаяclientBinding.Создайте экземпляр класса EndpointAddress с именем
serviceAddress. Инициализируйте экземпляр с базовым адресом, объединенным с именем конечной точки.Создайте экземпляр созданного класса клиента с переменными
serviceAddressиclientBinding.Вызовите метод Open, как показано в следующем примере кода.
Вызовите службу и отобразите результаты.
// 3rd Procedure: // Creating a binding and using it in a service // To run using config, comment the following lines, and uncomment out the code // following this section WSHttpBinding b = new WSHttpBinding(SecurityMode.Message); b.Security.Message.ClientCredentialType = MessageCredentialType.Windows; EndpointAddress ea = new EndpointAddress("Http://localhost:8036/SecuritySamples/secureCalculator"); CalculatorClient cc = new CalculatorClient(b, ea); cc.Open(); // Now call the service and display the results // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = cc.Add(value1, value2); Console.WriteLine($"Add({value1},{value2}) = {result}"); // Closing the client gracefully closes the connection and cleans up resources. cc.Close();Dim b As New WSHttpBinding(SecurityMode.Message) b.Security.Message.ClientCredentialType = MessageCredentialType.Windows Dim ea As New EndpointAddress("net.tcp://machinename:8036/endpoint") Dim cc As New CalculatorClient(b, ea) cc.Open() ' Alternatively, use a binding name from a configuration file generated by the ' SvcUtil.exe tool to create the client. Omit the binding and endpoint address ' because that information is provided by the configuration file. ' CalculatorClass cc = new CalculatorClient("ICalculator_Binding")
Использование файла конфигурации.
Вместо создания привязки с процедурным кодом можно использовать следующий код, приведенный для раздела привязок файла конфигурации.
Если у вас еще нет определенной службы, см. статью "Проектирование и реализация служб" и "Настройка служб".
Примечание.
Этот код конфигурации используется как в файлах службы, так и в файлах конфигурации клиента.
Включение безопасности передачи в службе в домене Windows с использованием конфигурации
Добавьте элемент <wsHttpBinding> в секцию элемента <bindings> файла конфигурации.
Добавьте элемент
<binding>в элемент<WSHttpBinding>и задайте атрибутуconfigurationNameзначение, соответствующее вашей программе.<security>Добавьте элемент и задайте для атрибутаmodeзначение Message.Добавьте элемент
<message>и задайте атрибутclientCredentialTypeв Windows.В файле конфигурации службы замените раздел
<bindings>с помощью следующего кода. Если у вас еще нет файла конфигурации службы, см. статью "Использование привязок для настройки служб и клиентов".<bindings> <wsHttpBinding> <binding name = "wsHttpBinding_Calculator"> <security mode="Message"> <message clientCredentialType="Windows"/> </security> </binding> </wsHttpBinding> </bindings>
Использование привязки в клиентском приложении
Эта процедура показывает, как создать два файла: прокси, взаимодействующий со службой, и файл конфигурации. В этой процедуре также описаны изменения программы клиента, которая является третьим файлом, используемым в клиенте.
Использование привязки в клиенте с конфигурацией
Используйте средство SvcUtil.exe, чтобы создать код прокси и файл конфигурации из метаданных службы. Дополнительные сведения см. в разделе "Практическое руководство. Создание клиента".
Замените <раздел привязок> созданного файла конфигурации кодом конфигурации из предыдущего раздела.
Процедурный код вставлен в начало метода
Mainпрограммы клиента.Создайте экземпляр созданного класса клиента, передав имя привязки в файле конфигурации в качестве входного параметра.
Вызовите метод Open, как показано в следующем примере кода.
Вызовите службу и отобразите результаты.
// 4th Procedure: // Using config instead of the binding-related code // In this case, use a binding name from a configuration file generated by the // SvcUtil.exe tool to create the client. Omit the binding and endpoint address // because that information is provided by the configuration file. CalculatorClient cc = new CalculatorClient("ICalculator_Binding"); cc.Open(); // Now call the service and display the results // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = cc.Add(value1, value2); Console.WriteLine($"Add({value1},{value2}) = {result}"); // Closing the client gracefully closes the connection and cleans up resources. cc.Close();
Пример
using System;
using System.Collections;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Microsoft.Security.Samples
{
public class Test
{
static void Main()
{
Test t = new Test();
Console.WriteLine("Starting....");
t.Run();
}
private void Run()
{
// First procedure:
// create a WSHttpBinding that uses Windows credentials and message security
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
MessageCredentialType.Windows;
// 2nd Procedure:
// Use the binding in a service
// Create the Type instances for later use and the URI for
// the base address.
Type contractType = typeof(ICalculator);
Type serviceType = typeof(Calculator);
Uri baseAddress = new
Uri("http://localhost:8036/SecuritySamples/");
// Create the ServiceHost and add an endpoint, then start
// the service.
ServiceHost myServiceHost =
new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint
(contractType, myBinding, "secureCalculator");
//enable metadata
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
myServiceHost.Description.Behaviors.Add(smb);
myServiceHost.Open();
Console.WriteLine("Listening");
Console.WriteLine("Press Enter to close the service");
Console.ReadLine();
myServiceHost.Close();
}
}
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double a, double b);
}
public class Calculator : ICalculator
{
public double Add(double a, double b)
{
return a + b;
}
}
}
using System;
using System.Collections.Generic;
using System.ServiceModel;
namespace Client
{
static class SecureClientCode
{
static void Main()
{
// 3rd Procedure:
// Creating a binding and using it in a service
// To run using config, comment the following lines, and uncomment out the code
// following this section
WSHttpBinding b = new WSHttpBinding(SecurityMode.Message);
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
EndpointAddress ea = new EndpointAddress("Http://localhost:8036/SecuritySamples/secureCalculator");
CalculatorClient cc = new CalculatorClient(b, ea);
cc.Open();
// Now call the service and display the results
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = cc.Add(value1, value2);
Console.WriteLine($"Add({value1},{value2}) = {result}");
// Closing the client gracefully closes the connection and cleans up resources.
cc.Close();
}
static void Main2()
{
// 4th Procedure:
// Using config instead of the binding-related code
// In this case, use a binding name from a configuration file generated by the
// SvcUtil.exe tool to create the client. Omit the binding and endpoint address
// because that information is provided by the configuration file.
CalculatorClient cc = new CalculatorClient("ICalculator_Binding");
cc.Open();
// Now call the service and display the results
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = cc.Add(value1, value2);
Console.WriteLine($"Add({value1},{value2}) = {result}");
// Closing the client gracefully closes the connection and cleans up resources.
cc.Close();
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples", ConfigurationName = "ICalculator")]
public interface ICalculator
{
[System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")]
double Add(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")]
double Subtract(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")]
double Multiply(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")]
double Divide(double n1, double n2);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public class CalculatorClient : System.ServiceModel.ClientBase<ICalculator>, ICalculator
{
public CalculatorClient()
{
}
public CalculatorClient(string endpointConfigurationName)
:
base(endpointConfigurationName)
{
}
public CalculatorClient(string endpointConfigurationName, string remoteAddress)
:
base(endpointConfigurationName, remoteAddress)
{
}
public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
:
base(endpointConfigurationName, remoteAddress)
{
}
public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
:
base(binding, remoteAddress)
{
}
public double Add(double n1, double n2)
{
return base.Channel.Add(n1, n2);
}
public double Subtract(double n1, double n2)
{
return base.Channel.Subtract(n1, n2);
}
public double Multiply(double n1, double n2)
{
return base.Channel.Multiply(n1, n2);
}
public double Divide(double n1, double n2)
{
return base.Channel.Divide(n1, n2);
}
}
}
Imports System.Collections.Generic
Imports System.ServiceModel
Public Class Program
Shared Sub Main()
Dim b As New WSHttpBinding(SecurityMode.Message)
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows
Dim ea As New EndpointAddress("net.tcp://machinename:8036/endpoint")
Dim cc As New CalculatorClient(b, ea)
cc.Open()
' Alternatively, use a binding name from a configuration file generated by the
' SvcUtil.exe tool to create the client. Omit the binding and endpoint address
' because that information is provided by the configuration file.
' CalculatorClass cc = new CalculatorClient("ICalculator_Binding")
End Sub
End Class
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0"), System.ServiceModel.ServiceContractAttribute([Namespace]:="http://Microsoft.ServiceModel.Samples", ConfigurationName:="ICalculator")> _
Public Interface ICalculator
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")> _
Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")> _
Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")> _
Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")> _
Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double
End Interface 'ICalculator
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _
Public Interface ICalculatorChannel
: Inherits ICalculator, System.ServiceModel.IClientChannel
End Interface 'ICalculatorChannel
<System.Diagnostics.DebuggerStepThroughAttribute(), System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _
Public Class CalculatorClient
Inherits System.ServiceModel.ClientBase(Of ICalculator)
Implements ICalculator
Public Sub New()
'
End Sub
Public Sub New(ByVal endpointConfigurationName As String)
MyBase.New(endpointConfigurationName)
End Sub
Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As String)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub
Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub
Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(binding, remoteAddress)
End Sub
Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add
Return MyBase.Channel.Add(n1, n2)
End Function 'Add
Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract
Return MyBase.Channel.Subtract(n1, n2)
End Function 'Subtract
Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply
Return MyBase.Channel.Multiply(n1, n2)
End Function 'Multiply
Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide
Return MyBase.Channel.Divide(n1, n2)
End Function 'Divide
End Class