클라우드 시대의 피아식별: Access Control #3

지난번 글에 이어서 Access Control을 실제 ASP.NET 응용프로그램에 연동하는 방법을 살펴보도록 하겠습니다. Access Control을 연동하기 위해서는 .NET의 경우 Windows Identity Foundation이라는 새로운 기술을 필요로 합니다. Windows Identity Foundation은 여러 버전의 런타임으로 나누어져 있으며, Windows Server 2003부터 Windows Server 2012까지 지원되지만, 보통은 Windows Server 2008 이후의 OS를 사용하는 것이 구성이나 배포가 단순합니다.


이 글에서는 Visual Studio 2010과 WIF 3.5를 사용하는 것을 기준으로 가이드를 쓰려고 합니다. 역시 나중에 기회가 되면 Visual Studio 2012와 WIF 4.5기준의 업데이트를 한 번 더 소개하겠습니다.


글에 있는 내용을 따라서 시작하기 전에 ACS를 이용하는 웹 사이트를 배포할 서버와 개발자 컴퓨터에 다음의 런타임을 버전에 맞추어 선택적으로 미리 설치하여 구성하셔야 합니다.


운영 체제 버전 별 런타임 설치하기



개발 도구 (SDK) 설치하기


개발 도구의 경우 한국 Microsoft 홈페이지에는 3.5 버전의 SDK만 게시되어있는데, .NET Framework 3.5가 아닌 4.0을 타겟으로 하는 경우에는 영어 홈페이지로 이동해서 직접 다운로드해야 합니다. 아래는 패키지 파일 다운로드 경로를 직접 걸어놓은 것으로 필요한 패키지를 골라 설치하면 됩니다.



SDK 또한 Windows Server 2003 SP2 부터 설치가 가능합니다.


Windows 8 및 Windows Server 2012에서 WIF 3.5 런타임 설치하기


Windows Identity Foundation 4.5 대신 3.5 버전을 사용해야 할 경우 아래 절차를 거쳐 설치할 수 있습니다.


제어판의 프로그램 및 기능 – 또는 – 프로그램 빠른 검색이나 Windows + R 단축키로 사용 가능한 실행 대화 상자에서 appwiz.cpl 제어판 애플릿을 시작합니다.



그 다음 Windows 기능 켜기/끄기 마법사를 시작합니다.



여러 항목들 중에서 Windows Identity Foundation 3.5 항목을 체크하고 확인 버튼을 클릭합니다.



잠시 기다리면 아래와 같이 완료 대화 상자가 나타납니다.



이제 여기에 WIF SDK 3.5 – 또는 – 4.0 버전을 설치하면 됩니다.


Visual Studio 2008 및 Visual Studio 2010의 경우 – FEDUTIL.EXE 사용하기


런타임의 경우 Windows Identity Foundation의 실행을 위한 클래스 라이브러리 및 네이티브 구성 요소들을 배포하기 위한 목적으로 사용하는 것이고, 기존에 만든 응용프로그램의 환경 설정 파일을 변경하거나 클래스 라이브러리 도움말 등을 포함하는 것이 SDK의 구성입니다. 그리고 부가적으로 SDK의 경우에는 Visual Studio와 연동하는 기능도 제공합니다만 이 기능은 제대로 설치가 될 수도 있고 그렇지 않을 수도 있어서 신경쓸 필요는 없는 부분입니다. SDK에서 진짜 중요한 부분은 FEDUTIL.EXE 라는 마법사형 프로그램으로 이 프로그램을 사용하여 여러분의 asp.net 응용프로그램을 WIF, ACS와 연결시킬 때 필요한 복잡한 설정을 자동화할 수 있습니다.


시스템 사용 환경에 따라 FedUtil.exe 파일의 설치 위치에 다소 차이가 있지만 아래와 같이 요약할 수 있습니다.



  • 32비트 버전 설치 시: %programfiles%Windows Identity Foundation SDKv4.0FedUtil.exe

  • 64비트 버전 설치 시: %programfiles(x86)%Windows Identity Foundation SDKv4.0FedUtil.exe

FedUtil.exe 프로그램을 실행시키고 잠시 기다리면 아래와 같이 마법사가 시작됩니다.



UI 언어는 환경에 따라 한국어가 나올 수도, 영어가 나올 수도 있습니다. 응용프로그램 설정 파일의 위치를 묻는 부분에는 여러분이 WIF를 적용하려는 ASP.NET 웹 프로젝트의 기본 web.config 파일 경로를 지정하는 곳이며, Visual Studio로 해당 프로젝트를 편집 중에 있더라도 안전하게 적용할 수 있습니다.


노트: Visual Studio와 연동된다는 것은 이 유틸리티를 프로젝트 실행 도중 즉시 호출할 수 있도록 “STS 추가 마법사”라는 이름으로 솔루션 탐색기 컨텍스트 메뉴에 추가하는 정도의 편의 제공이기 때문에 이 유틸리티를 직접 호출해도 무방합니다.


그리고 Application URI에는 지난번 글에서 소개했던 것과 같이 Ad-hoc 서버의 포트 번호를 확인하여 얻을 수 있는 localhost 주소를 이곳에 기재해야 합니다. 프로덕션 환경에서 적용하려면 당연히 이 부분이 실제 프로덕션 웹 사이트의 주소가 되어야 합니다.


Application URI에 HTTPS대신 HTTP 주소를 지정할 경우 아래와 같은 경고 메시지가 나타나지만, Access Control 테스트를 위한 것이므로 지금은 무시하고 넘어갑니다.



계속 진행하면 보안 토큰 서비스의 주소를 물어보는 단계가 나타납니다. 이 단계에서 실제로 Azure Access Control Service의 웹 서비스 주소를 지정하여 WIF와 ACS간에 연동을 이루게 됩니다.



여기에 어떤 주소를 넣어야 할까요? 다시 Azure Access Control 관리자 웹 서비스로 되돌아가봅니다. 관리자 웹 서비스 페이지 좌측 제일 하단의 응용프로그램 통합 링크를 클릭하면 페이지 하단에 STS 서비스를 위한 WS-Federation Metadata Endpoint URL이 보이는데 이 주소를 그대로 Copy & Paste합니다.



다음 단계로 진행하면 ACS 서비스가 제시한 인증서가 올바른 인증서가 아니라는 오류를 표시합니다. 이전에 언급한대로 Azure ACS가 프로덕션 환경에서 제대로 작동하려면 정식 서버 인증서를 필요로 합니다. 여기서는 마법사가 기본으로 제안하는 인증서 체인 검사 비활성화를 선택하고 진행하겠습니다.



토큰 암호화에 대한 설정을 지정하는 페이지가 나타납니다. ACS 설정에서 토큰 암호화에 대한 부분을 구성하였다면 이 단계에서도 호환 가능한 설정을 같이 지정해야 합니다.



웹 서비스가 던져줄 수 있는 클레임의 종류에 대한 설명이 열거됩니다. 다음 버튼을 클릭합니다.



이제 마침 버튼을 눌러 web.config 파일을 업데이트합니다.



별다른 이상이 없다면 아래와 같이 성공 메시지 상자가 나타나고 FedUtil.exe 프로그램이 종료될 것입니다.



NOTE: Visual Studio를 실행 중이었다면 web.config 파일을 열어둔 상태였을 경우 파일이 변경되었음을 감지하고 다시 읽어들일 것인지 물어볼 수 있습니다. 이 경우 꼭 바뀐 파일 내용을 다시 읽도록 해주어야 하며, 편집기 버퍼에 남아있는 컨텐츠를 저장하면 FedUtil.exe로 변경한 내용이 소실되므로 유의해야 합니다. 편집기 버퍼에서 바꾼 내용이 FedUtil.exe 실행 전에 많이 존재한다면 변경된 web.config 파일을 별도로 백업받아놓고 두 파일을 적절하게 병합해야 합니다.


변경된 web.config 파일 내용 살펴보기


이제 FedUtil.exe 프로그램에서 어떤 일을 해주었는지 살펴볼 차례입니다. 우선 여러분의 웹 프로젝트 디렉터리에 새로운 디렉터리와 파일들이 나타나는데, 아래와 같습니다. 



FederationMetadata 폴더에 ACS 서비스와 상호대조를 위한, ACS로부터 복제한 메타데이터 파일이 들어있습니다. 실제 서비스가 제대로 작동하기 위해서는 이 파일이 개발자 환경이나 프로덕션 서버로 정확하게 배포되어야 합니다. 버전 관리 시스템을 사용하는 경우 이 파일이 버전 관리 대상에 포함될 수 있도록 해야 합니다.


그리고 web.config 파일이 변경된 것과 더불어 이전 파일에 대한 백업도 들어있습니다. 백업 파일은 확인 후 필요없으면 삭제해도 무방합니다.


그렇다면 web.config 파일은 어떻게 바뀌었는지 한 번 살펴보도록 할까요?우선 파일을 열었을 때 가장 먼저 눈에 띄는 것은 새로운 Configuration Handler를 추가한 부분인데, 아래와 같습니다.


  <configSections>
    <section name=”microsoft.identityModel” type=”Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />
  </configSections>


새로운 Configuration Handler를 지정하고 있으므로 설정 파일 어딘가에 새로운 설정 섹션이 하나 더 추가되어있겠군요. 그리고 appSettings 태그 아래에는 메타데이터 원본 경로에 대한 설정이 들어있습니다.


  <appSettings>

    <add key=”FederationMetadataLocation” value=<A href="https://.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml”>https://<네임스페이스>.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml />

  </appSettings>


그리고 직전에 살펴본 FederationMetadata 폴더를 위한 특권이 하나 들어있습니다. 인증 세션을 거치지 않았어도 누구나 FederationMetadata 폴더는 접근할 수 있도록 열어놓았군요.


  <location path=”FederationMetadata”>
    <system.web>
      <authorization>
        <allow users=”*” />
      </authorization>
    </system.web>
  </location>


반면에 웹 응용프로그램의 모든 영역에 대해서는 보호가 걸리게 됩니다.


  <system.web>

    <authorization>
      <deny users=”?” />
    </authorization>
    <authentication mode=”None” />

    <!–Commented out by FedUtil–>
    <!–<authentication mode=”Forms”><forms loginUrl=”~/Account/LogOn” timeout=”2880″ /></authentication>–>
  </system.web>


달리 표현하면 web.config이 관할하는 모든 영역에 대해서는 ACS를 통한 로그인을 거치지 않을 경우 자동으로 ACS측 로그인 페이지로 리디렉션됨을 의미합니다. 이 부분에 대한 조율이 필요하다면 ASP.NET MVC의 경우 영역으로 별도 영역을 파티셔닝하거나, Location 태그를 적극 활용해야 합니다. 그리고 중요한 차이점이 하나 더 보이는데 WIF의 인증 체계는 기존의 ASP.NET이 제공하던 Form 인증, AD 인증, Windows 인증 및 Passport 인증 어디에도 속하지 않는다는 것입니다.


그리고 당연한 이야기이지만 어셈블리 참조가 걸려있습니다. web.config 파일 및 동적 컴파일 호출 시 유효한 대상으로 걸려있는 것이고, Visual Studio 프로젝트나 별도 컴파일 호출 시 WIF를 사용하려면 프로젝트 참조에서 Microsoft.IdentityModel 어셈블리를 직접 추가해야 합니다.


  <system.web>
    <compilation debug=”true” targetFramework=”4.0″>
      <assemblies>

        <add assembly=”Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />

      </assemblies>
    </compilation>

  </system.web>


ASP.NET 차원에서는 마지막으로 HTTP 모듈이 대체되는 부분이 있습니다. WIF가 기존 ASP.NET 인증 체계를 완전히 재정의해야 하므로 아래의 모듈이 새로 추가됩니다.


    <httpModules>
      <add name=”WSFederationAuthenticationModule” type=”Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />
      <add name=”SessionAuthenticationModule” type=”Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />
    </httpModules>


같은 설정이지만 IIS 7 이후의 서버들을 위해서는 <system.webServer> 태그 설정도 동일하게 추가됩니다.


  <system.webServer>
    <validation validateIntegratedModeConfiguration=”false” />
    <modules runAllManagedModulesForAllRequests=”true”>
      <add name=”WSFederationAuthenticationModule” type=”Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ preCondition=”managedHandler” />
      <add name=”SessionAuthenticationModule” type=”Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ preCondition=”managedHandler” />
    </modules>
  </system.webServer>


이제 끝으로 제일 서두에 언급된 새로운 설정 핸들러가 web.config 끝자락에 보입니다.


  <microsoft.identityModel>
    <service>
      <audienceUris>
        <add value=”http://localhost:50086/” />
      </audienceUris>
      <federatedAuthentication>
        <wsFederation passiveRedirectEnabled=”true” issuer=”https://rkttuacs.accesscontrol.windows.net/v2/wsfederation” realm=”http://localhost:50086/ ” requireHttps=”false” />
        <cookieHandler requireSsl=”false” />

      </federatedAuthentication>
      <applicationService>
        <claimTypeRequired>
          <!–Following are the claims offered by STS ‘https://rkttuacs.accesscontrol.windows.net/’. Add or uncomment claims that you require by your application and then update the federation metadata of this application.–>
          <claimType type=”http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name” optional=”true” />
          <claimType type=”
http://schemas.microsoft.com/ws/2008/06/identity/claims/role” optional=”true” />
          <!–<claimType type=”http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” optional=”true” />–>
          <!–<claimType type=”
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider” optional=”true” />–>
        </claimTypeRequired>
      </applicationService>
      <issuerNameRegistry type=”Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″>
        <trustedIssuers>
          <add thumbprint=”CE5BF1CE19528FEDA7FA9F3ECF87A85E3B1B6AED” name=”https://rkttuacs.accesscontrol.windows.net/” />
        </trustedIssuers>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode=”None” />
    </service>
  </microsoft.identityModel>


위의 내용들 가운데에서 굵게 강조 표시한 항목들이 변경의 여지가 있고 제어가 가능한 부분들입니다. 지금으로서는 테스트를 목적으로 하는 것이므로 따로 변경할 것은 없겠습니다.


잘 작동할까요?


워낙에 중요하고 어려운 부분들만 수정해놓은 것이라 불안하게 보입니다. 잘 작동할까요? 한 번 실행해보겠습니다. 



설정 파일에서 변경한대로 사이트에 접속하자마자 ACS 로그인 페이지로 이동합니다. 이후에 다시 살펴보겠지만 이 페이지의 디자인은 얼마든지 재정의 가능합니다. 여기서 Google ID를 시험삼아 로그인에 사용하도록 해보겠습니다.



로그인을 거치고나니 이런 오류 메시지가 나타납니다. 이 문제를 어떻게 해결해야 할까요?


WIF 3.5의 호환성 문제 해결하기


전통적인 로그인 및 사용자 인증 모델에서는 고려할 수 없었던 동작을 수행해야 하는데 안타깝게도 ASP.NET은 이러한 부분에 대해서 다소 부정적인 면모를 보입니다. 이 문제를 해결하는 방법 자체는 단순합니다. 입력 폼으로 들어오는 XML 데이터를 무시하도록 설정을 완화시키면 가능합니다. 그렇지만 그냥 그렇게 프로덕션 환경에 설정을 풀어놓은채로 올리기에는 너무 안일합니다. 뭔가 좋은 방법이 없을까요?


유효성 검사를 풀지 않으면서도 안전하게 WIF와 ACS 사이의 통신을 인정할 수 있는 방법으로 Custom Validation Handler를 추가하는 방법이 있습니다. 이 코드는 아래의 웹 페이지의 코드를 인용한 것입니다.
http://undefinedbroker-config.js?1344170599926


http://social.technet.microsoft.com/wiki/contents/articles/1725.windows-identity-foundation-wif-a-potentially-dangerous-request-form-value-was-detected-from-the-client-wresult-t-requestsecurityto.aspx


C# 소스 코드



//—————————————————————————–
//
// THIS CODE AND INFORMATION IS PROVIDED ‘AS IS’ WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
//—————————————————————————–


using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Helpers;
using System.Web.Util;
using Microsoft.IdentityModel.Protocols.WSFederation;


/// <summary>
/// This SampleRequestValidator validates the wresult parameter of the
/// WS-Federation passive protocol by checking for a SignInResponse message
/// in the form post. The SignInResponse message contents are verified later by
/// the WSFederationPassiveAuthenticationModule or the WIF signin controls.
/// </summary>
public class SampleRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(
        HttpContext context, string value, RequestValidationSource requestValidationSource,
        string collectionKey, out int validationFailureIndex)
    {
        validationFailureIndex = 0;


        if (requestValidationSource == RequestValidationSource.Form &&
            !String.IsNullOrEmpty(collectionKey) &&
            collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
        {
            NameValueCollection unvalidatedFormValues = Validation.Unvalidated(context.Request).Form;
            SignInResponseMessage message = WSFederationMessage.CreateFromNameValueCollection(
                WSFederationMessage.GetBaseUrl(context.Request.Url),
                unvalidatedFormValues) as SignInResponseMessage;


            if (message != null)
                return true;
        }


        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}


Visual Basic .NET 코드



‘—————————————————————————–

‘ THIS CODE AND INFORMATION IS PROVIDED ‘AS IS’ WITHOUT WARRANTY OF
‘ ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
‘ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
‘ PARTICULAR PURPOSE.

‘ Copyright (c) Microsoft Corporation. All rights reserved.


‘—————————————————————————–


Imports System
Imports System.Collections.Specialized
Imports System.Web
Imports System.Web.Helpers
Imports System.Web.Util
Imports Microsoft.IdentityModel.Protocols.WSFederation


”’ <summary>
”’ This SampleRequestValidator validates the wresult parameter of the
”’ WS-Federation passive protocol by checking for a SignInResponse message
”’ in the form post. The SignInResponse message contents are verified later by
”’ the WSFederationPassiveAuthenticationModule or the WIF signin controls.
”’ </summary>
Public Class SampleRequestValidator
    Inherits RequestValidator


    Protected Overrides Function IsValidRequestString( _
        context As HttpContext, value As String, requestValidationSource As RequestValidationSource, _
        collectionKey As String, ByRef validationFailureIndex As Integer) As Boolean


        validationFailureIndex = 0


        If requestValidationSource = Util.RequestValidationSource.Form AndAlso _
            String.IsNullOrEmpty(collectionKey) = False AndAlso _
            collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal) Then


            Dim unvalidatedFormValues As NameValueCollection = Validation.Unvalidated(context.Request).Form
            Dim message As SignInResponseMessage = TryCast(WSFederationMessage.CreateFromNameValueCollection( _
                WSFederationMessage.GetBaseUrl(context.Request.Url), _
                unvalidatedFormValues), SignInResponseMessage)


            If message IsNot Nothing Then
                Return True
            End If
        End If
        Return MyBase.IsValidRequestString(context, value, requestValidationSource, collectionKey, validationFailureIndex)
    End Function
End Class


위의 코드가 이상 없이 컴파일이 잘 되는지 프로젝트에 클래스를 새로 하나 추가하여 확인하고, web.config으로 이동하여 아래와 같이 설정을 수정합니다.


C#의 경우



<system.web>
  …
  <httpRuntime requestValidationType=”SampleRequestValidator” />
  …
</system.web>


VB.NET의 경우



<system.web>
  …
  <httpRuntime requestValidationType=”[프로젝트 이름].SampleRequestValidator” />
  …
</system.web>


VB.NET의 경우 네임스페이스의 경로가 상대성을 가지기 때문에 정확한 것은 개체 탐색기 등을 이용하여 확인해보는 것이 필요합니다. 대개는 위와 같이 기술했을 때 문제가 없습니다.


이제 다시 로그인을 시도하면 아래 그림과 같이 인증이 통과되는 것을 볼 수 있습니다. 



한 가지 더 – 로드 밸런싱에 대응하기


아직 모든 것이 완벽하게 마무리 되지 않았는데, 로드 밸런싱에 대한 부분이 해결되지 않았습니다. 기본적으로 ASP.NET과 마찬가지로 컴퓨터 상태에 의존하여 난수를 생성하는 DPAPI (Data Protection API)를 기반으로 하므로 로드 밸런싱 환경에서는 아래와 같은 유형의 오류 메시지가 나타납니다.


Key not valid for use in specified state


위의 오류를 해결하기 위해서는 DPAPI 기반의 암호화 대신 로드 밸런싱이나 웹 팜에 참여하는 노드들 간의 키를 일치시켜야 합니다. Global.asax 파일이 없을 경우 하나 추가하여 Application_Start 메서드 혹은 이벤트 처리기에 아래의 코드 조각을 추가합니다.


C# 코드


FederatedAuthentication.ServiceConfigurationCreated += OnServiceConfigurationCreated;


VB.NET 코드


AddHandler FederatedAuthentication.ServiceConfigurationCreated, OnServiceConfigurationCreated()


이어서 추가된 이벤트 처리기의 코드 내용을 아래와 같이 프로그래밍합니다.


C# 코드



using System.Collections.Generic;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Web;
using Microsoft.IdentityModel.Web.Configuration;

    private void OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
    {
       List<CookieTransform> sessionTransforms = new List<CookieTransform>(
           new CookieTransform[] {
               new DeflateCookieTransform(),
               new RsaEncryptionCookieTransform(e.ServiceConfiguration.ServiceCertificate),
               new RsaSignatureCookieTransform(e.ServiceConfiguration.ServiceCertificate) 
           });
       SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(
          sessionTransforms.AsReadOnly());
       e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
    }


VB.NET 코드



Imports System.Collections.Generic
Imports Microsoft.IdentityModel.Tokens
Imports Microsoft.IdentityModel.Web
Imports Microsoft.IdentityModel.Web.Configuration

    Private Sub OnServiceConfigurationCreated(sender As Object, e As ServiceConfigurationCreatedEventArgs)
        Dim sessionTransforms As New List(Of CookieTransform)(New CookieTransform() { _
            New DeflateCookieTransform(), _
            New RsaEncryptionCookieTransform(e.ServiceConfiguration.ServiceCertificate), _
            New RsaSignatureCookieTransform(e.ServiceConfiguration.ServiceCertificate)
            })
        Dim sessionHandler As New SessionSecurityTokenHandler( _
            sessionTransforms.AsReadOnly)
        e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace( _
            sessionHandler)
    End Sub


마지막으로 Azure Cloud Service나 VM, 혹은 여러분의 웹 팜 환경에서 실행되는 컴퓨터에 동일한 인증서를 사용하도록 배포하면 로드밸런싱 환경에서도 안전하게 ACS 기반 인증을 처리할 수 있게 됩니다.


좀 더 많은 자료들과 글 작성에 도움이 된 자료들


댓글 남기기