Федерация

В этом разделе представлен краткий обзор концепции федеративной безопасности. В нем также описывается поддержка Windows Communication Foundation (WCF) для развертывания федеративных архитектур безопасности. Пример приложения, демонстрирующего федерацию, см. в примере федерации.

Определение федеративной безопасности

Федеративная безопасность обеспечивает чистое разделение между службой, к ней обращается клиент и связанные процедуры проверки подлинности и авторизации. Федеративная безопасность также обеспечивает совместную работу между несколькими системами, сетями и организациями в разных областях доверия.

WCF обеспечивает поддержку создания и развертывания распределенных систем, использующих федеративную безопасность.

Элементы федеративной архитектуры безопасности

Федеративная архитектура безопасности содержит три ключевых элемента, как описано в следующей таблице.

Элемент Описание
Домен или область Единая единица администрирования безопасности или доверия. Типичный домен может включать одну организацию.
Федерация Коллекция доменов, которые установили доверие. Уровень доверия может отличаться, но обычно включает проверку подлинности и почти всегда включает авторизацию. Типичная федерация может включать ряд организаций, которые установили доверие для общего доступа к набору ресурсов.
Служба маркеров безопасности (STS) Веб-служба, которая выдает токены безопасности; то есть, она делает утверждения на основе доказательств, которым доверяет и кому доверяют ей. Это служит основой для посредничества в доверии между доменами.

Пример сценария

На следующем рисунке показан пример федеративной безопасности:

Схема, показывающая типичный федеративный сценарий безопасности.

Этот сценарий включает в себя две организации: A и B. Организация B имеет веб-ресурс (веб-службу), который некоторые пользователи в организации A находят ценные.

Замечание

В этом разделе используются термины ресурса, службы ивеб-службы взаимозаменяемо.

Как правило, для организации B требуется, чтобы пользователь из организации A предоставил действительную форму проверки подлинности перед доступом к службе. Кроме того, организации также может потребоваться, чтобы пользователь мог получить доступ к конкретному ресурсу. Один из способов решения этой проблемы, позволяющий пользователям организации A получить доступ к ресурсу в организации B, следующий:

  • Пользователи из организации A регистрируют свои учетные данные (имя пользователя и пароль) в организации B.

  • Во время доступа к ресурсам пользователи из организации A представляют свои учетные данные организации B и проходят проверку подлинности перед доступом к ресурсу.

Этот подход имеет три существенных недостатка:

  • Организация B должна управлять учетными данными для пользователей из организации A, а также управлять учетными данными своих локальных пользователей.

  • Пользователи в организации A должны поддерживать дополнительный набор учетных данных (т. е. запомнить дополнительное имя пользователя и пароль) помимо учетных данных, которые они обычно используют для получения доступа к ресурсам в организации A. Обычно это рекомендует использовать одно и то же имя пользователя и пароль на нескольких сайтах служб, что является слабой мерой безопасности.

  • Архитектура не справляется с масштабированием, так как больше организаций считают ресурс в организации B ценным.

Альтернативный подход, который устраняет ранее упомянутые недостатки, заключается в использовании федеративной безопасности. В этом подходе организации A и B устанавливают отношения доверия и используют службу маркеров безопасности (STS), чтобы облегчить посредничество в установленном доверии.

В федеративной архитектуре безопасности пользователи из организации A знают, что если они хотят получить доступ к веб-службе в организации B, то они должны представить действительный маркер безопасности из службы безопасности в организации B, которая проходит проверку подлинности и авторизует доступ к определенной службе.

При обращении к STS B пользователи получают еще один уровень косвенности от политики, связанной с STS. Они должны представить действительный маркер безопасности из stS A (т. е. области доверия клиента), прежде чем stS B может выдать им маркер безопасности. Это следствие установленного отношения доверия между двумя организациями и подразумевает, что организации B не нужно управлять удостоверениями для пользователей из организации A. На практике STS B обычно имеет пустое значение issuerAddress и issuerMetadataAddress. Дополнительные сведения см. в разделе "Практическое руководство. Настройка локального издателя". В этом случае клиент обращается к локальной политике, чтобы найти STS A. Эта конфигурация называется федерацией домашней области и лучше масштабируется, так как stS B не требуется поддерживать сведения о STS A.

Затем пользователи обращаются к stS в организации A и получают маркер безопасности, предоставляя учетные данные проверки подлинности, которые обычно используются для получения доступа к любому другому ресурсу в организации A. Это также устраняет проблему, связанную с тем, что пользователи могут поддерживать несколько наборов учетных данных или использовать один и тот же набор учетных данных на нескольких сайтах служб.

Когда пользователи получают маркер безопасности из STS A, они представляют маркер в stS B. Организация B продолжает выполнять авторизацию запросов пользователей и выдает маркер безопасности пользователям из собственного набора маркеров безопасности. Затем пользователи могут представить свой токен ресурсу в организации B и получить доступ к службе.

Поддержка федеративной безопасности в WCF

WCF обеспечивает поддержку развертывания федеративных архитектур безопасности с помощью <wsFederationHttpBinding>.

Элемент <wsFederationHttpBinding> обеспечивает безопасную, надежную, совместимую привязку, которая влечет за собой использование HTTP в качестве базового механизма транспорта для стиля обмена запросами и ответами, используя текст и XML в качестве формата передачи данных для кодирования.

Использование <wsFederationHttpBinding> в федеративном сценарии безопасности можно разделить на два логически независимых этапа, как описано в следующих разделах.

Этап 1. Этап разработки

На этапе разработки клиент использует средство служебной программы метаданных ServiceModel (Svcutil.exe) для чтения политики, которую предоставляет конечная точка службы, и для сбора требований к проверке подлинности и авторизации службы. Соответствующие прокси-серверы создаются для создания следующего федеративного шаблона связи безопасности на клиенте:

  • Получите токен безопасности из STS в области доверия клиента.

  • Предоставьте маркер в STS в царстве доверия службы.

  • Получите маркер безопасности из STS в домене доверия службы.

  • Представьте маркер службе для доступа.

Этап 2. Этап Run-Time

На этапе выполнения клиент создает экземпляр класса клиента WCF и совершает вызов, используя этот клиент WCF. Базовая платформа WCF обрабатывает описанные ранее шаги в федеративном шаблоне связи безопасности и позволяет клиенту легко использовать службу.

Пример реализации с помощью WCF

На следующем рисунке показан пример реализации федеративной архитектуры безопасности с использованием собственной поддержки WCF.

Схема, показывающая пример реализации безопасности федерации.

Пример MyService

Служба MyService предоставляет единственную конечную точку через MyServiceEndpoint. На следующем рисунке показан адрес, привязка и контракт, связанный с конечной точкой.

Схема, на которой показаны сведения о MyServiceEndpoint.

Конечная точка MyServiceEndpoint службы использует <wsFederationHttpBinding> и требует допустимого маркера языка разметки утверждений безопасности (SAML) с утверждением, выданным accessAuthorized STS B. Это декларативно указано в конфигурации службы.

<system.serviceModel>
  <services>
    <service type="FederationSample.MyService"
        behaviorConfiguration='MyServiceBehavior'>
        <endpoint address=""
            binding=" wsFederationHttpBinding"
            bindingConfiguration='MyServiceBinding'
            contract="Federation.IMyService" />
   </service>
  </services>

  <bindings>
    <wsFederationHttpBinding>
    <!-- This is the binding used by MyService. It redirects
    clients to STS-B. -->
      <binding name='MyServiceBinding'>
        <security mode="Message">
           <message issuedTokenType=
"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
           <issuer address="http://localhost/FederationSample/STS-B/STS.svc" />
            <issuerMetadata
           address=
"http://localhost/FederationSample/STS-B/STS.svc/mex" />
         <requiredClaimTypes>
            <add claimType="http://tempuri.org:accessAuthorized" />
         </requiredClaimTypes>
        </message>
      </security>
      </binding>
    </wsFederationHttpBinding>
  </bindings>

  <behaviors>
    <behavior name='MyServiceBehavior'>
      <serviceAuthorization
operationRequirementType="FederationSample.MyServiceOperationRequirement, MyService" />
       <serviceCredentials>
         <serviceCertificate findValue="CN=FederationSample.com"
         x509FindType="FindBySubjectDistinguishedName"
         storeLocation='LocalMachine'
         storeName='My' />
      </serviceCredentials>
    </behavior>
  </behaviors>
</system.serviceModel>

Замечание

Следует отметить тонкий момент об утверждениях, необходимых для MyService. Второй рисунок показывает, что MyService нужен токен SAML с требованием accessAuthorized. Точнее, это указывает тип утверждения, требуемый MyService. Полное имя этого типа утверждения — http://tempuri.org:accessAuthorized (а также связанное пространство имен), которое используется в файле конфигурации службы. Значение этого утверждения указывает на его наличие, и предполагается, что оно установлено на true системой STS B.

Во время выполнения эта политика применяется классом MyServiceOperationRequirement, реализованным как часть MyService.

using System.Collections.Generic;
using System.IdentityModel.Claims;
using System.IdentityModel.Policy;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
Imports System.Collections.Generic
Imports System.IdentityModel.Claims
Imports System.IdentityModel.Policy
Imports System.IdentityModel.Tokens
Imports System.Security.Cryptography.X509Certificates
Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Security.Tokens
Imports System.Text
public class myServiceAuthorizationManager : ServiceAuthorizationManager
{
    // Override the CheckAccess method to enforce access control requirements.
    public override bool CheckAccess(OperationContext operationContext)
    {
        AuthorizationContext authContext =
        operationContext.ServiceSecurityContext.AuthorizationContext;
        if (authContext.ClaimSets == null) return false;
        if (authContext.ClaimSets.Count != 1) return false;
        ClaimSet myClaimSet = authContext.ClaimSets[0];
        if (!IssuedBySTS_B(myClaimSet)) return false;
        if (myClaimSet.Count != 1) return false;
        Claim myClaim = myClaimSet[0];
        if (myClaim.ClaimType ==
          "http://www.tmpuri.org:accessAuthorized")
        {
            string resource = myClaim.Resource as string;
            if (resource == null) return false;
            if (resource != "true") return false;
            return true;
        }
        else
        {
            return false;
        }
    }

    // This helper method checks whether SAML Token was issued by STS-B.
    // It compares the Thumbprint Claim of the Issuer against the
    // Certificate of STS-B.
    private bool IssuedBySTS_B(ClaimSet myClaimSet)
    {
        ClaimSet issuerClaimSet = myClaimSet.Issuer;
        if (issuerClaimSet == null) return false;
        if (issuerClaimSet.Count != 1) return false;
        Claim issuerClaim = issuerClaimSet[0];
        if (issuerClaim.ClaimType != ClaimTypes.Thumbprint)
            return false;
        if (issuerClaim.Resource == null) return false;
        byte[] claimThumbprint = (byte[])issuerClaim.Resource;
        // It is assumed that stsB_Certificate is a variable of type
        // X509Certificate2 that is initialized with the Certificate of
        // STS-B.
        X509Certificate2 stsB_Certificate = GetStsBCertificate();
        byte[] certThumbprint = stsB_Certificate.GetCertHash();
        if (claimThumbprint.Length != certThumbprint.Length)
            return false;
        for (int i = 0; i < claimThumbprint.Length; i++)
        {
            if (claimThumbprint[i] != certThumbprint[i]) return false;
        }
        return true;
    }
Public Class myServiceAuthorizationManager
    Inherits ServiceAuthorizationManager

    ' Override the CheckAccess method to enforce access control requirements.
    Public Overloads Overrides Function CheckAccess(ByVal operationContext As OperationContext) As Boolean
        Dim authContext = operationContext.ServiceSecurityContext.AuthorizationContext
        If authContext.ClaimSets Is Nothing Then
            Return False
        End If

        If authContext.ClaimSets.Count <> 1 Then
            Return False
        End If

        Dim myClaimSet = authContext.ClaimSets(0)
        If Not IssuedBySTS_B(myClaimSet) Then
            Return False
        End If
        If myClaimSet.Count <> 1 Then
            Return False
        End If
        Dim myClaim = myClaimSet(0)
        If myClaim.ClaimType = "http://www.tmpuri.org:accessAuthorized" Then
            Dim resource = TryCast(myClaim.Resource, String)
            If resource Is Nothing Then
                Return False
            End If
            If resource <> "true" Then
                Return False
            End If
            Return True
        Else
            Return False
        End If
    End Function

    ' This helper method checks whether SAML Token was issued by STS-B.     
    ' It compares the Thumbprint Claim of the Issuer against the 
    ' Certificate of STS-B. 
    Private Function IssuedBySTS_B(ByVal myClaimSet As ClaimSet) As Boolean
        Dim issuerClaimSet = myClaimSet.Issuer
        If issuerClaimSet Is Nothing Then
            Return False
        End If
        If issuerClaimSet.Count <> 1 Then
            Return False
        End If
        Dim issuerClaim = issuerClaimSet(0)
        If issuerClaim.ClaimType <> ClaimTypes.Thumbprint Then
            Return False
        End If
        If issuerClaim.Resource Is Nothing Then
            Return False
        End If
        Dim claimThumbprint() = CType(issuerClaim.Resource, Byte())
        ' It is assumed that stsB_Certificate is a variable of type 
        ' X509Certificate2 that is initialized with the Certificate of 
        ' STS-B.
        Dim stsB_Certificate = GetStsBCertificate()
        Dim certThumbprint() = stsB_Certificate.GetCertHash()
        If claimThumbprint.Length <> certThumbprint.Length Then
            Return False
        End If
        For i = 0 To claimThumbprint.Length - 1
            If claimThumbprint(i) <> certThumbprint(i) Then
                Return False
            End If
        Next i
        Return True
    End Function

STS B

На следующем рисунке показан STS B. Как уже было упомянуто, служба маркеров безопасности (STS) также является веб-сервисом и может иметь связанные конечные точки, политику и так далее.

Схема, на которой показана служба маркеров безопасности B.

STS B предоставляет одну конечную точку, которая STSEndpoint может использоваться для запроса токенов безопасности. В частности, STS B выдает токены SAML с accessAuthorized утверждением, которые можно использовать на сайте службы MyService для доступа к услуге. Однако STS B требует, чтобы пользователи предъявляли действительный токен SAML, выданный STS A, который содержит заявление userAuthenticated. Это декларативно указано в конфигурации STS.

<system.serviceModel>
  <services>
    <service type="FederationSample.STS_B" behaviorConfiguration=
     "STS-B_Behavior">
    <endpoint address=""
              binding="wsFederationHttpBinding"
              bindingConfiguration='STS-B_Binding'
      contract="FederationSample.ISts" />
    </service>
  </services>
  <bindings>
    <wsFederationHttpBinding>
    <!-- This is the binding used by STS-B. It redirects clients to
         STS-A. -->
      <binding name='STS-B_Binding'>
        <security mode='Message'>
          <message issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
          <issuer address='http://localhost/FederationSample/STS-A/STS.svc' />
          <issuerMetadata address='http://localhost/FederationSample/STS-A/STS.svc/mex'/>
          <requiredClaimTypes>
            <add claimType='http://tempuri.org:userAuthenticated'/>
          </requiredClaimTypes>
          </message>
        </security>
    </binding>
   </wsFederationHttpBinding>
  </bindings>
  <behaviors>
  <behavior name='STS-B_Behavior'>
    <serviceAuthorization   operationRequirementType='FederationSample.STS_B_OperationRequirement, STS_B' />
    <serviceCredentials>
      <serviceCertificate findValue='CN=FederationSample.com'
      x509FindType='FindBySubjectDistinguishedName'
       storeLocation='LocalMachine'
       storeName='My' />
     </serviceCredentials>
   </behavior>
  </behaviors>
</system.serviceModel>

Замечание

Опять же, утверждение userAuthenticated — это тип утверждения, который требуется для STS B. Полное имя этого типа утверждения — http://tempuri.org:userAuthenticated, а также связанное с ним пространство имен, используется в файле конфигурации STS. Значение этого утверждения указывает на наличие этого утверждения и предполагается, что оно задано true stS A.

Во время выполнения STS_B_OperationRequirement класс применяет эту политику, которая реализуется как часть STS B.

public class STS_B_AuthorizationManager : ServiceAuthorizationManager
{

    // Override AccessCheck to enforce access control requirements.
    public override bool CheckAccess(OperationContext operationContext)
    {
        AuthorizationContext authContext =
        operationContext.ServiceSecurityContext.AuthorizationContext;
        if (authContext.ClaimSets == null) return false;
        if (authContext.ClaimSets.Count != 1) return false;
        ClaimSet myClaimSet = authContext.ClaimSets[0];
        if (!IssuedBySTS_A(myClaimSet)) return false;
        if (myClaimSet.Count != 1) return false;
        Claim myClaim = myClaimSet[0];
        if (myClaim.ClaimType == "http://www.tmpuri.org:userAuthenticated")
        {
            string resource = myClaim.Resource as string;
            if (resource == null) return false;
            if (resource != "true") return false;
            return true;
        }
        else
        {
            return false;
        }
    }

    // This helper method checks whether SAML Token was issued by STS-A.
    // It compares the Thumbprint Claim of the Issuer against the
    // Certificate of STS-A.
    private bool IssuedBySTS_A(ClaimSet myClaimSet)
    {
        ClaimSet issuerClaimSet = myClaimSet.Issuer;
        if (issuerClaimSet == null) return false;
        if (issuerClaimSet.Count != 1) return false;
        Claim issuerClaim = issuerClaimSet[0];
        if (issuerClaim.ClaimType != ClaimTypes.Thumbprint) return false;
        if (issuerClaim.Resource == null) return false;
        byte[] claimThumbprint = (byte[])issuerClaim.Resource;
        // It is assumed that stsA_Certificate is a variable of type X509Certificate2
        // that is initialized with the Certificate of STS-A.
        X509Certificate2 stsA_Certificate = GetStsACertificate();

        byte[] certThumbprint = stsA_Certificate.GetCertHash();
        if (claimThumbprint.Length != certThumbprint.Length) return false;
        for (int i = 0; i < claimThumbprint.Length; i++)
        {
            if (claimThumbprint[i] != certThumbprint[i]) return false;
        }
        return true;
    }
Public Class STS_B_AuthorizationManager
    Inherits ServiceAuthorizationManager

    ' Override AccessCheck to enforce access control requirements.
    Public Overloads Overrides Function CheckAccess(ByVal operationContext As OperationContext) As Boolean
        Dim authContext = operationContext.ServiceSecurityContext.AuthorizationContext
        If authContext.ClaimSets Is Nothing Then
            Return False
        End If
        If authContext.ClaimSets.Count <> 1 Then
            Return False
        End If
        Dim myClaimSet = authContext.ClaimSets(0)
        If Not IssuedBySTS_A(myClaimSet) Then
            Return False
        End If
        If myClaimSet.Count <> 1 Then
            Return False
        End If
        Dim myClaim = myClaimSet(0)
        If myClaim.ClaimType = "http://www.tmpuri.org:userAuthenticated" Then
            Dim resource = TryCast(myClaim.Resource, String)
            If resource Is Nothing Then
                Return False
            End If
            If resource <> "true" Then
                Return False
            End If
            Return True
        Else
            Return False
        End If
    End Function

    ' This helper method checks whether SAML Token was issued by STS-A. 
    ' It compares the Thumbprint Claim of the Issuer against the 
    ' Certificate of STS-A.
    Private Function IssuedBySTS_A(ByVal myClaimSet As ClaimSet) As Boolean
        Dim issuerClaimSet = myClaimSet.Issuer
        If issuerClaimSet Is Nothing Then
            Return False
        End If
        If issuerClaimSet.Count <> 1 Then
            Return False
        End If
        Dim issuerClaim = issuerClaimSet(0)
        If issuerClaim.ClaimType <> ClaimTypes.Thumbprint Then
            Return False
        End If
        If issuerClaim.Resource Is Nothing Then
            Return False
        End If
        Dim claimThumbprint() = CType(issuerClaim.Resource, Byte())
        ' It is assumed that stsA_Certificate is a variable of type X509Certificate2
        ' that is initialized with the Certificate of STS-A.
        Dim stsA_Certificate = GetStsACertificate()

        Dim certThumbprint() = stsA_Certificate.GetCertHash()
        If claimThumbprint.Length <> certThumbprint.Length Then
            Return False
        End If
        For i = 0 To claimThumbprint.Length - 1
            If claimThumbprint(i) <> certThumbprint(i) Then
                Return False
            End If
        Next i
        Return True
    End Function

Если проверка доступа пройдена успешно, STS B выдает токен SAML с утверждением accessAuthorized.

// Create the list of SAML Attributes.
List<SamlAttribute> samlAttributes = new List<SamlAttribute>();

// Add the accessAuthorized claim.
List<string> strList = new List<string>();
strList.Add("true");
samlAttributes.Add(new SamlAttribute("http://www.tmpuri.org",
"accessAuthorized",
strList));

// Create the SAML token with the accessAuthorized claim. It is assumed that
// the method CreateSamlToken() is implemented as part of STS-B.
SamlSecurityToken samlToken = CreateSamlToken(
    proofToken,
    issuerToken,
    samlConditions,
    samlSubjectNameFormat,
    samlSubjectEmailAddress,
    samlAttributes);
' Create the list of SAML Attributes.
Dim samlAttributes As New List(Of SamlAttribute)()

' Add the accessAuthorized claim.
Dim strList As New List(Of String)()
strList.Add("true")
samlAttributes.Add(New SamlAttribute("http://www.tmpuri.org", "accessAuthorized", strList))

' Create the SAML token with the accessAuthorized claim. It is assumed that 
' the method CreateSamlToken() is implemented as part of STS-B.
Dim samlToken = CreateSamlToken(proofToken, _
                                issuerToken, _
                                samlConditions, _
                                samlSubjectNameFormat, _
                                samlSubjectEmailAddress, _
                                samlAttributes)

STS A

На следующем рисунке показан STS A.

федерации

Аналогично STS B, STS A также является веб-службой, которая выдает токены безопасности и предоставляет единую конечную точку для этой цели. Однако он использует другую привязку (wsHttpBinding) и требует от пользователей представления действительного CardSpace с утверждением emailAddress. В ответ он выдает токены SAML с утверждением userAuthenticated . Это декларативно указано в конфигурации службы.

<system.serviceModel>
  <services>
    <service type="FederationSample.STS_A" behaviorConfiguration="STS-A_Behavior">
      <endpoint address=""
                binding="wsHttpBinding"
                bindingConfiguration="STS-A_Binding"
                contract="FederationSample.ISts">
       <identity>
       <certificateReference findValue="CN=FederationSample.com"
                       x509FindType="FindBySubjectDistinguishedName"
                       storeLocation="LocalMachine"
                       storeName="My" />
       </identity>
    </endpoint>
  </service>
</services>

<bindings>
  <wsHttpBinding>
  <!-- This is the binding used by STS-A. It requires users to present
   a CardSpace. -->
    <binding name='STS-A_Binding'>
      <security mode='Message'>
        <message clientCredentialType="CardSpace" />
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

<behaviors>
  <behavior name='STS-A_Behavior'>
    <serviceAuthorization operationRequirementType=
     "FederationSample.STS_A_OperationRequirement, STS_A" />
      <serviceCredentials>
  <serviceCertificate findValue="CN=FederationSample.com"
                     x509FindType='FindBySubjectDistinguishedName'
                     storeLocation='LocalMachine'
                     storeName='My' />
      </serviceCredentials>
    </behavior>
  </behaviors>
</system.serviceModel>

Во время выполнения класс STS_A_OperationRequirement обеспечивает соблюдение этой политики, которая реализована как часть STS A.


public class STS_A_AuthorizationManager : ServiceAuthorizationManager
{
    // Override AccessCheck to enforce access control requirements.
    public override bool CheckAccess(OperationContext operationContext)
    {
        AuthorizationContext authContext =
        operationContext.ServiceSecurityContext.AuthorizationContext;
        if (authContext.ClaimSets == null) return false;
        if (authContext.ClaimSets.Count != 1) return false;
        ClaimSet myClaimSet = authContext.ClaimSets[0];
        if (myClaimSet.Count != 1) return false;
        Claim myClaim = myClaimSet[0];
        if ((myClaim.ClaimType ==
        @"http://schemas.microsoft.com/ws/2005/05/identity/claims:EmailAddress") &&
        (myClaim.Right == Rights.PossessProperty))
        {
            string emailAddress = myClaim.Resource as string;
            if (emailAddress == null) return false;
            if (!IsValidEmailAddress(emailAddress)) return false;
            return true;
        }
        else
        {
            return false;
        }
    }

    // This helper method performs a rudimentary check for whether
    //a given email is valid.
    private static bool IsValidEmailAddress(string emailAddress)
    {
        string[] splitEmail = emailAddress.Split('@');
        if (splitEmail.Length != 2) return false;
        if (!splitEmail[1].Contains(".")) return false;
        return true;
    }
}
Public Class STS_A_AuthorizationManager
    Inherits ServiceAuthorizationManager

    ' Override AccessCheck to enforce access control requirements.
    Public Overloads Overrides Function CheckAccess(ByVal operationContext As OperationContext) As Boolean
        Dim authContext = operationContext.ServiceSecurityContext.AuthorizationContext
        If authContext.ClaimSets Is Nothing Then
            Return False
        End If
        If authContext.ClaimSets.Count <> 1 Then
            Return False
        End If
        Dim myClaimSet = authContext.ClaimSets(0)
        If myClaimSet.Count <> 1 Then
            Return False
        End If
        Dim myClaim = myClaimSet(0)
        If myClaim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims:EmailAddress" AndAlso myClaim.Right = Rights.PossessProperty Then
            Dim emailAddress = TryCast(myClaim.Resource, String)
            If emailAddress Is Nothing Then
                Return False
            End If
            If Not IsValidEmailAddress(emailAddress) Then
                Return False
            End If
            Return True
        Else
            Return False
        End If
    End Function

    ' This helper method performs a rudimentary check for whether 
    'a given email is valid.
    Private Shared Function IsValidEmailAddress(ByVal emailAddress As String) As Boolean
        Dim splitEmail() = emailAddress.Split("@"c)
        If splitEmail.Length <> 2 Then
            Return False
        End If
        If Not splitEmail(1).Contains(".") Then
            Return False
        End If
        Return True
    End Function
End Class

Если доступ true имеется, STS A выдает токен SAML с претензией userAuthenticated.

// Create the list of SAML Attributes.
List<SamlAttribute> samlAttributes = new List<SamlAttribute>();
// Add the userAuthenticated claim.
List<string> strList = new List<string>();
strList.Add("true");
SamlAttribute mySamlAttribute = new SamlAttribute("http://www.tmpuri.org",
     "userAuthenticated", strList);
samlAttributes.Add(mySamlAttribute);
// Create the SAML token with the userAuthenticated claim. It is assumed that
// the method CreateSamlToken() is implemented as part of STS-A.
SamlSecurityToken samlToken = CreateSamlToken(
    proofToken,
    issuerToken,
    samlConditions,
    samlSubjectNameFormat,
    samlSubjectEmailAddress,
    samlAttributes);
' Create the list of SAML Attributes.
Dim samlAttributes As New List(Of SamlAttribute)()
' Add the userAuthenticated claim.
Dim strList As New List(Of String)()
strList.Add("true")
Dim mySamlAttribute As New SamlAttribute("http://www.tmpuri.org", _
                                         "userAuthenticated", _
                                         strList)
samlAttributes.Add(mySamlAttribute)
' Create the SAML token with the userAuthenticated claim. It is assumed that 
' the method CreateSamlToken() is implemented as part of STS-A.
Dim samlToken = CreateSamlToken(proofToken, issuerToken, samlConditions, _
                                samlSubjectNameFormat, _
                                samlSubjectEmailAddress, _
                                samlAttributes)

Клиент в организации A

На следующем рисунке показан клиент в организации A, а также шаги, связанные с вызовом MyService службы. Другие функциональные компоненты также включены для полноты.

Схема, показывающая шаги в вызове службы MyService.

Сводка

Федеративная безопасность обеспечивает чистое разделение ответственности и помогает создавать безопасные, масштабируемые архитектуры служб. В качестве платформы для создания и развертывания распределенных приложений WCF обеспечивает встроенную поддержку реализации федеративной безопасности.

См. также