Как упорядочить отключения безопасных сеансов в WSFederationHttpBinding
Некоторые службы могут требовать федеративных учетных данных, но не поддерживать безопасные сеансы. В этом случае необходимо отключить функцию безопасных сеансов. В отличие от класса WsHttpBinding, класс WSFederationHttpBinding не предоставляет способа отключения безопасных сеансов при взаимодействии со службой. Вместо этого необходимо создать пользовательскую привязку, которая заменяет параметры безопасного сеанса начальной загрузкой.
В этом разделе показано, как изменить элементы привязки, содержащиеся в привязке WSFederationHttpBinding, чтобы создать пользовательскую привязку. Результат совпадает с WSFederationHttpBinding, за исключением того, что не используются безопасные сеансы.
Создание пользовательской федеративной привязки без безопасных сеансов
Создайте экземпляр класса WSFederationHttpBinding либо принудительно в коде, либо загрузив один из файлов конфигурации.
Клонируйте WSFederationHttpBinding в CustomBinding.
Найдите SecurityBindingElement в CustomBinding.
Найдите SecureConversationSecurityTokenParameters в SecurityBindingElement.
Замените исходный элемент SecurityBindingElement элементом привязки безопасности начальной загрузки из SecureConversationSecurityTokenParameters.
Пример
В следующем примере создается пользовательская федеративная привязка без безопасных сеансов.
Imports System
Imports System.Collections.Generic
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Security.Tokens
Imports System.Security.Permissions
<Assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution:=True)>
Public NotInheritable Class CustomBindingCreator
' This method creates a CustomBinding based on a WSFederationHttpBinding which does not use secure conversation.
Public Shared Function CreateFederationBindingWithoutSecureSession(ByVal inputBinding As WSFederationHttpBinding) As CustomBinding
' This CustomBinding starts out identical to the specified WSFederationHttpBinding.
Dim outputBinding As New CustomBinding(inputBinding.CreateBindingElements())
' Find the SecurityBindingElement for message security.
Dim security As SecurityBindingElement = outputBinding.Elements.Find(Of SecurityBindingElement)()
' If the security mode is message, then the secure session settings are the protection token parameters.
Dim secureConversation As SecureConversationSecurityTokenParameters
If WSFederationHttpSecurityMode.Message = inputBinding.Security.Mode Then
Dim symmetricSecurity As SymmetricSecurityBindingElement = CType(security, SymmetricSecurityBindingElement)
secureConversation = CType(symmetricSecurity.ProtectionTokenParameters, SecureConversationSecurityTokenParameters)
' If the security mode is message, then the secure session settings are the endorsing token parameters.
ElseIf WSFederationHttpSecurityMode.TransportWithMessageCredential = inputBinding.Security.Mode Then
Dim transportSecurity As TransportSecurityBindingElement = CType(security, TransportSecurityBindingElement)
secureConversation = CType(transportSecurity.EndpointSupportingTokenParameters.Endorsing(0), SecureConversationSecurityTokenParameters)
Else
Throw New NotSupportedException(String.Format("Unhandled security mode {0}.", inputBinding.Security.Mode))
End If
' Replace the secure session SecurityBindingElement with the bootstrap SecurityBindingElement.
Dim securityIndex As Integer = outputBinding.Elements.IndexOf(security)
outputBinding.Elements(securityIndex) = secureConversation.BootstrapSecurityBindingElement
' Return modified binding.
Return outputBinding
End Function
' It is a good practice to create a private constructor for a class that only
' defines static methods.
Private Sub New()
End Sub 'New
Shared Sub Main()
End Sub 'Main
End Class 'CustomBindingCreator ' Code not shown.
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security.Tokens;
using System.Security.Permissions;
[assembly: SecurityPermission(
SecurityAction.RequestMinimum, Execution = true)]
namespace Samples
{
public sealed class CustomBindingCreator
{
// This method creates a CustomBinding based on a WSFederationHttpBinding which does not use secure conversation.
public static CustomBinding CreateFederationBindingWithoutSecureSession(WSFederationHttpBinding inputBinding)
{
// This CustomBinding starts out identical to the specified WSFederationHttpBinding.
CustomBinding outputBinding = new CustomBinding(inputBinding.CreateBindingElements());
// Find the SecurityBindingElement for message security.
SecurityBindingElement security = outputBinding.Elements.Find<SecurityBindingElement>();
// If the security mode is message, then the secure session settings are the protection token parameters.
SecureConversationSecurityTokenParameters secureConversation;
if (WSFederationHttpSecurityMode.Message == inputBinding.Security.Mode)
{
SymmetricSecurityBindingElement symmetricSecurity = security as SymmetricSecurityBindingElement;
secureConversation = symmetricSecurity.ProtectionTokenParameters as SecureConversationSecurityTokenParameters;
}
// If the security mode is message, then the secure session settings are the endorsing token parameters.
else if (WSFederationHttpSecurityMode.TransportWithMessageCredential == inputBinding.Security.Mode)
{
TransportSecurityBindingElement transportSecurity = security as TransportSecurityBindingElement;
secureConversation = transportSecurity.EndpointSupportingTokenParameters.Endorsing[0] as SecureConversationSecurityTokenParameters;
}
else
{
throw new NotSupportedException(String.Format("Unhandled security mode {0}.", inputBinding.Security.Mode));
}
// Replace the secure session SecurityBindingElement with the bootstrap SecurityBindingElement.
int securityIndex = outputBinding.Elements.IndexOf(security);
outputBinding.Elements[securityIndex] = secureConversation.BootstrapSecurityBindingElement;
// Return modified binding.
return outputBinding;
}
// It is a good practice to create a private constructor for a class that only
// defines static methods.
private CustomBindingCreator() { }
static void Main()
{
// Code not shown.
}
}
Компиляция кода
- Чтобы скомпилировать этот пример кода, создайте проект, ссылающийся на сборку System.ServiceModel.dll.