Как устанавливать свойства ProtectionLevel
Уровень защиты можно задать, применив соответствующий атрибут и задав свойство. Защиту на уровне службы можно задать таким образом, чтобы она влияла на все части каждого сообщения, либо задать защиту на более детальных уровнях — от методов до частей сообщения. Дополнительные сведения свойстве ProtectionLevel см. в разделе Основные сведения об уровне защиты.
Примечание |
---|
Уровни защиты можно задавать только в коде, а не в конфигурации. |
Подписание всех сообщений для службы
Создайте интерфейс для службы.
Примените к службе атрибут ServiceContractAttribute и задайте значение Sign для свойства ProtectionLevel, как показано в следующем примере кода (уровень по умолчанию — EncryptAndSign).
' Set the ProtectionLevel on the whole service to Sign. <ServiceContract(ProtectionLevel:=ProtectionLevel.Sign)> _ Public Interface ICalculator
// Set the ProtectionLevel on the whole service to Sign. [ServiceContract(ProtectionLevel = ProtectionLevel.Sign)] public interface ICalculator
Подписание всех частей сообщения для операции
Создайте интерфейс для службы и примените к нему атрибут ServiceContractAttribute.
Добавьте в интерфейс объявление метода.
Примените к методу атрибут OperationContractAttribute и задайте значение Sign для свойства ProtectionLevel, как показано в следующем примере кода.
' Set the ProtectionLevel on the whole service to Sign. <ServiceContract(ProtectionLevel:=ProtectionLevel.Sign)> _ Public Interface ICalculator ' Set the ProtectionLevel on this operation to Sign. <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _ Function Add(ByVal a As Double, ByVal b As Double) As Double End Interface
// Set the ProtectionLevel on the whole service to Sign. [ServiceContract(ProtectionLevel = ProtectionLevel.Sign)] public interface ICalculator { // Set the ProtectionLevel on this operation to None. [OperationContract(ProtectionLevel = ProtectionLevel.Sign)] double Add(double a, double b); }
Защита сообщений об ошибках
Создаваемые в службе исключения можно отправить клиенту в виде ошибок SOAP. Дополнительные сведения создании строго типизированных ошибок см. в разделах Задание и обработка сбоев в контрактах и службах и Практическое руководство. Объявление сбоев в контрактах служб.
Защита сообщения об ошибке
Создайте тип, представляющий сообщение об ошибке. В следующем примере описано создание класса, именуемого
MathFault
, с двумя полями.Примените к типу атрибут DataContractAttribute, а к каждому полю, которое должно быть сериализовано, — атрибут DataMemberAttribute, как показано в следующем примере кода.
<DataContract()> _ Public Class MathFault <DataMember()> _ Public operation As String <DataMember()> _ Public description As String End Class
[DataContract] public class MathFault { [DataMember] public string operation; [DataMember] public string description; }
Примените атрибут FaultContractAttribute к методу, который будет возвращать ошибку, и настройте параметр detailType к типу класса ошибки в интерфейсе, который будет возвращать ошибку,
Задайте для свойства ProtectionLevel значение EncryptAndSign в конструкторе, как показано в следующем примере кода.
Public Interface ICalculator ' Set the ProtectionLevel on a FaultContractAttribute. <OperationContract(ProtectionLevel := ProtectionLevel.EncryptAndSign), _ FaultContract(GetType(MathFault), ProtectionLevel := ProtectionLevel.EncryptAndSign)> _ Function Add(ByVal a As Double, ByVal b As Double) As Double End Interface
public interface ICalculator { // Set the ProtectionLevel on a FaultContractAttribute. [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)] [FaultContract( typeof(MathFault), Action = @"https://localhost/Add", Name = "AddFault", Namespace = "https://contoso.com", ProtectionLevel = ProtectionLevel.EncryptAndSign)] double Add(double a, double b); }
Защита частей сообщения
Для защиты частей сообщения следует использовать контракт сообщения. Дополнительные сведения контрактах сообщения см. в разделе Использование контрактов сообщений
Защита тела сообщения
Создайте тип, представляющий сообщение. В следующем примере описано создание класса
Company
двумя полями:CompanyName
иCompanyID
.Примените атрибут MessageContractAttribute к классу и задайте значение EncryptAndSign для свойства ProtectionLevel.
Примените атрибут MessageHeaderAttribute к полю, которое будет выражено как заголовок сообщения, и задайте значение EncryptAndSign для свойства
ProtectionLevel
.Примените атрибут MessageBodyMemberAttribute к любому полю, которое будет выражено как часть текста сообщения, и задайте значение
ProtectionLevel
для свойства EncryptAndSign, как показано в следующем примере.<MessageContract(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _ Public Class Company <MessageHeader(ProtectionLevel := ProtectionLevel.Sign)> _ Public CompanyName As String <MessageBodyMember(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _ Public CompanyID As String End Class
[MessageContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)] public class Company { [MessageHeader(ProtectionLevel = ProtectionLevel.Sign)] public string CompanyName; [MessageBodyMember(ProtectionLevel = ProtectionLevel.EncryptAndSign)] public string CompanyID; }
Пример
В следующем примере демонстрируется, как задать свойство ProtectionLevel
нескольких классов атрибута в разных местах службы.
<ServiceContract(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Public Interface ICalculator
<OperationContract(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Function Add(ByVal a As Double, ByVal b As Double) As Double
<OperationContract(), _
FaultContract _
(GetType(MathFault), _
Action := "https://localhost/Add", _
Name := "AddFault", _
Namespace :="https://contoso.com", _
ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Function Subtract(ByVal a As Double, ByVal b As Double) As Double
<OperationContract(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Function GetCompanyInfo() As Company
End Interface
<DataContract()> _
Public Class MathFault
<DataMember()> _
Public operation As String
<DataMember()> _
Public description As String
End Class
<MessageContract(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Public Class Company
<MessageHeader(ProtectionLevel := ProtectionLevel.Sign)> _
Public CompanyName As String
<MessageBodyMember(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Public CompanyID As String
End Class
<MessageContract(ProtectionLevel := ProtectionLevel.Sign)> _
Public Class Calculator
Implements ICalculator
Public Function Add(ByVal a As Double, ByVal b As Double) As Double _
Implements ICalculator.Add
Return a + b
End Function
Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double _
Implements ICalculator.Subtract
Return a - b
End Function
Public Function GetCompanyInfo() As Company Implements ICalculator.GetCompanyInfo
Dim co As New Company()
co.CompanyName = "www.cohowinery.com"
Return co
End Function
End Class
Public Class Test
Shared Sub Main()
Dim t As New Test()
Try
t.Run()
Catch inv As System.InvalidOperationException
Console.WriteLine(inv.Message)
End Try
End Sub
Private Sub Run()
' Create a binding and set the security mode to Message.
Dim b As New WSHttpBinding()
b.Security.Mode = SecurityMode.Message
Dim contractType As Type = GetType(ICalculator)
Dim implementedContract As Type = GetType(Calculator)
Dim baseAddress As New Uri("https://localhost:8044/base")
' Create the ServiceHost and add an endpoint.
Dim sh As New ServiceHost(implementedContract, baseAddress)
sh.AddServiceEndpoint(contractType, b, "Calculator")
Dim sm As New ServiceMetadataBehavior()
sm.HttpGetEnabled = True
sh.Description.Behaviors.Add(sm)
sh.Credentials.ServiceCertificate.SetCertificate( _
StoreLocation.CurrentUser, StoreName.My, _
X509FindType.FindByIssuerName, "ValidCertificateIssuer")
Dim se As ServiceEndpoint
For Each se In sh.Description.Endpoints
Dim cd As ContractDescription = se.Contract
Console.WriteLine(vbLf + "ContractDescription: ProtectionLevel = {0}", _
cd.Name, cd.ProtectionLevel)
Dim od As OperationDescription
For Each od In cd.Operations
Console.WriteLine(vbLf + "OperationDescription: Name = {0}", od.Name, od.ProtectionLevel)
Console.WriteLine("ProtectionLevel = {1}", od.Name, od.ProtectionLevel)
Dim m As MessageDescription
For Each m In od.Messages
Console.WriteLine(vbTab + " {0}: {1}", m.Action, m.ProtectionLevel)
Dim mh As MessageHeaderDescription
For Each mh In m.Headers
Console.WriteLine(vbTab + vbTab + " {0}: {1}", mh.Name, mh.ProtectionLevel)
Dim mp As MessagePropertyDescription
For Each mp In m.Properties
Console.WriteLine("{0}: {1}", mp.Name, mp.ProtectionLevel)
Next mp
Next mh
Next m
Next od
Next se
sh.Open()
Console.WriteLine("Listening")
Console.ReadLine()
sh.Close()
End Sub
End Class
[ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public interface ICalculator
{
[OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
double Add(double a, double b);
[OperationContract()]
[FaultContract(typeof(MathFault),
ProtectionLevel = ProtectionLevel.EncryptAndSign)]
double Subtract(double a, double b);
[OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
Company GetCompanyInfo();
}
[DataContract]
public class MathFault
{
[DataMember]
public string operation;
[DataMember]
public string description;
}
[MessageContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public class Company
{
[MessageHeader(ProtectionLevel = ProtectionLevel.Sign)]
public string CompanyName;
[MessageBodyMember(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public string CompanyID;
}
[MessageContract(ProtectionLevel = ProtectionLevel.Sign)]
public class Calculator : ICalculator
{
public double Add(double a, double b)
{
return a + b;
}
public double Subtract(double a, double b)
{
return a - b;
}
public Company GetCompanyInfo()
{
Company co = new Company();
co.CompanyName = "www.cohowinery.com";
return co;
}
}
public class Test
{
static void Main()
{
Test t = new Test();
try
{
t.Run();
}
catch (System.InvalidOperationException inv)
{
Console.WriteLine(inv.Message);
}
}
private void Run()
{
// Create a binding and set the security mode to Message.
WSHttpBinding b = new WSHttpBinding();
b.Security.Mode = SecurityMode.Message;
Type contractType = typeof(ICalculator);
Type implementedContract = typeof(Calculator);
Uri baseAddress = new Uri("https://localhost:8044/base");
// Create the ServiceHost and add an endpoint.
ServiceHost sh = new ServiceHost(implementedContract, baseAddress);
sh.AddServiceEndpoint(contractType, b, "Calculator");
ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
sm.HttpGetEnabled = true;
sh.Description.Behaviors.Add(sm);
sh.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindByIssuerName,
"ValidCertificateIssuer");
foreach (ServiceEndpoint se in sh.Description.Endpoints)
{
ContractDescription cd = se.Contract;
Console.WriteLine("\nContractDescription: ProtectionLevel = {0}", cd.Name, cd.ProtectionLevel);
foreach (OperationDescription od in cd.Operations)
{
Console.WriteLine("\nOperationDescription: Name = {0}", od.Name, od.ProtectionLevel);
Console.WriteLine("ProtectionLevel = {1}", od.Name, od.ProtectionLevel);
foreach (MessageDescription m in od.Messages)
{
Console.WriteLine("\t {0}: {1}", m.Action, m.ProtectionLevel);
foreach (MessageHeaderDescription mh in m.Headers)
{
Console.WriteLine("\t\t {0}: {1}", mh.Name, mh.ProtectionLevel);
foreach (MessagePropertyDescription mp in m.Properties)
{
Console.WriteLine("{0}: {1}", mp.Name, mp.ProtectionLevel);
}
}
}
}
}
sh.Open();
Console.WriteLine("Listening");
Console.ReadLine();
sh.Close();
}
}
Компиляция кода
В следующем примере кода показаны пространства имен, необходимые для компиляции примера кода.
Imports System
Imports System.ServiceModel
Imports System.Net.Security
Imports System.ServiceModel.Description
Imports System.Security.Permissions
Imports System.Security.Cryptography.X509Certificates
Imports System.Runtime.Serialization
using System;
using System.ServiceModel;
using System.Net.Security;
using System.ServiceModel.Description;
using System.Security.Permissions;
using System.Security.Cryptography.X509Certificates;
using System.Runtime.Serialization;
См. также
Справочник
ServiceContractAttribute
OperationContractAttribute
FaultContractAttribute
MessageContractAttribute
MessageBodyMemberAttribute