Windows Azure Platform AppFabric

Windows Azure Platform AppFabric 是Windows Azure云端运算服务的一部分，亦为平台即服务(PaaS)的一种类型，它是Windows Azure上的应用程序服务器 (Application Server) 平台，作为开发身份验证，存取控制以及服务总线 (Service Bus) 应用程序之用。它本身也是奠基于 Windows Azure 操作系统之上，并且以 WCF (Windows Communication Foundation) 为核心开发的。

## 概观

Windows Azure Platform AppFabric 一开始命名是.NET Service，要作为在 Windows Azure 上的 .NET Framework 特殊服务的一种服务平台，原始的规划中包含了存取控制 (Access Control)，服务总线以及工作流程引擎 (Workflow Engine)，但到了 2009 年的 PDC，正式发表 AppFabric SDK 1.0 时，工作流程引擎被抽掉，原因可能是微软在开发 Workflow Engine 时，尚未解决因云端运算特性所导致的分散式运算与状态整合与管理的问题，因此在 AppFabric 1.0 版中这项服务被抽掉了。

在 AppFabric 中，每一项服务都有一个服务命名空间 (service namespace)，这个命名空间会作为应用程序呼叫 AppFabric 时所使用的 URL 的一部分。

## 服务

AppFabric 目前包含两种服务：存取控制以及服务总线，作为开发企业服务导向架构 (SOA) 应用程序的基础平台，同时可与其他不同的验证服务整合，形成邦联化验证与存取控制服务 (Federated Access Control)。

在2010年10月28日举办的PDC 2010中，微软宣布将会在 Windows Azure Platform AppFabric 中加入像 Cache, Integration 与 Composite Applications 等功能，让 Windows Azure AppFabric 在云端应用程序上的作为中介应用程服务器的角色更明确。

### 存取控制

存取控制是 AppFabric 中作为应用程序使用者身份验证的数据库，并作为服务总线服务与其他 AppFabric 上的身份验证服务。

#### v1.0

Access Control v1.0 遵循 OAuth Web Resource Authorization Protocol (WRAP)v0.9 的规格，可作为企业的单一签入 (Single Sign On) 服务的资料储存地，当使用者在系统中发出登入指令时，要求会先送到 AppFabric，由 AppFabric 验证身份后，回传以安全符记服务 (Security Token Service; STS) 协定格式传回身份验证的资料后，再由应用程序转送给授权程式，检查符记的资料内容 (会包含部分授权资讯) 后，授予使用者系统存取权限。

存取控制是由四个部分组成：

- Token Policy (符记原则)：这是验证的根资讯，有了它，才可以建立范围资讯。
- Scope (范围)：在这里会要求记录应用程序或服务的 URL，以作为授权凭据之一。
- Issuer (使用者)：这是使用者账户与密码的组成，IssuerName 是使用者名称，Key 则是密码，算法目前支援 SHA256 杂凑算法，以及使用凭证的 X.509 算法。
- Rule (规则)：这是 Scope 和 Issuer 组合的配对规则，以登录使用者是否具有存取指定范围的权利。

应用程序开发人员要利用 AppFabric SDK 中的 acm.exe 或是 AppFabric Management Services 将应用程序存取控制的四个部分都建立起来后，再改写 Web 应用程序，将验证资讯送到 AppFabric 中验证：

```csharp
private static string GetTokenFromACS()
{
    WebClient acsClient = new WebClient();
    acsClient.BaseAddress = "https://myservice.accesscontrol.windows.net";
    NameValueCollection values = new NameValueCollection();
    values.Add("wrap_name", "myserviceconsumer");
    values.Add("wrap_password", "jC1n221++AXhzvvZtzQZO7ohsqKR6491N51B6A0UHZE=");
    values.Add("wrap_scope", "http://localhost/myservice");

    byte[] acsResponseInBytes = acsClient.UploadValues("WRAPv0.9", values);
    string acsResponse = Encoding.UTF8.GetString(acsResponseInBytes);
}
```

当 AppFabric 验证后传回 STS 授权资讯，再由应用程序将它转给应用程序内的验证与授权单元进行分析与授权即可。

#### v2.0

为了实行单一签入并与社群等主要身份验证提供者 (Identity Provider, IdP) 相互介接，Access Control v2.0 开始支援 Google, Yahoo, Facebook, Windows Live ID 等支援 Open ID 或 OAuth 等主流的身份认证服务，并进一步针对企业内环境的身份认证，提供了介接 Active Directory Federation Service (ADFS) v2.0 的功能，Access Control v2.0 的使用者先在管理界面中建立桥接机制，当使用者向 IdP 要求认证通过后，会得到 IdP Token，而透过 IdP Token 可在 Access Control Service 中交换成 ACS Token 再送交用户端程式，之后的流程就和 v1.0 相同。

ACS v2.0 可支援下列协定：

- OAuth WRAP v0.9
- OAuth v1.0a
- WS-Security
- WS-Federation

虽然 ACS v2.0 只支援 Google, Yahoo, Facebook, Windows Live ID 等验证服务，但如果有新的 Open ID 认证服务，ACS v2.0 也允许由开发人员手动加入。

### 服务总线

服务总线是要让 Windows Azure 可作为企业服务应用程序前端 (显露服务与转接讯息等) 的一个服务，它本身是由 WCF 所组成，同时由于服务总线是负责处理使用者呼叫的前端界面，基于服务总线的特性，AppFabric Service Bus 会将要求讯息转送给服务应用程序，这个程序被称为 Relay，因此 AppFabric SDK 中内含了一个 Microsoft.ServiceBus.dll 组件，它封装了改写 WCF 通讯协定的各项必要元件，像是 TCP 与 HTTP 均可以透过 Service Bus 进行转传，但并不是所有的 WCF 协定都可以被转传，像是 MSMQ 以及具名管道等都不在受支援之列。

AppFabric Service Bus 由于是利用 WCF 进行通讯，因此使用它的服务应用程序也需要以 WCF 来开发。

下列程式是一个 AppFabric Service Bus 服务应用程序的简单范例：

```csharp
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Description;
using System.Text;

namespace Microsoft.ServiceBus.Samples
{

#region Service Contract

    [ServiceContract(Name = "IEchoContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/EchoV1")]

    public interface IEchoContract
    {
        [OperationContract]
        String Echo(string text);
    }

    public interface IEchoChannel : IEchoContract, IClientChannel { };

#endregion

#region Echo Service

    [ServiceBehavior(Name = "EchoService", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/EchoV1")]

    public class EchoService : IEchoContract
    {
        public string Echo(string text)
        {
            Console.WriteLine("Echoing: {0}", text);
            return text;
        }
    }

#endregion

#region Host Service

    class Program
    {
        static void Main(string[] args)
        {

            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;

            
            // Hard-code the service namespace, issuer name, and issuer secret into the application.
            // Note: The credentials are hard-coded in this sample for simplicity purposes but doing so is not considered a secure programming practice.
            string serviceNamespace = "putServiceNamespaceHere";
            string issuerName= "putIssuerNameHere";
            string issuerSecret = "putIssuerSecretHere";

            // Create the service URI based on the solution name.
            Uri address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");

           // create the credentials object for the endpoint
            TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
            sharedSecretServiceBusCredential.CredentialType = TransportClientCredentialType.SharedSecret;
            sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerName = issuerName;
            sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerSecret = issuerSecret;

            // create the service host reading the configuration
            ServiceHost host = new ServiceHost(typeof(EchoService), address);

            // create the ServiceRegistrySettings behavior for the endpoint
            IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);

            // add the Service Bus credentials to all endpoints specified in configuration
            foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
            {
                endpoint.Behaviors.Add(serviceRegistrySettings);
                endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
            }
            
            // open the service
            host.Open();

            Console.WriteLine("Service address: " + address);
            Console.WriteLine("Press [Enter] to exit");
            Console.ReadLine();

            // close the service
            host.Close();
        }
    }

    #endregion

}
```

AppFabric Service Bus 除了基本的服务通讯转送之外，它还支援了服务登录 (Service Registration)，服务搜寻 (Service Discovery) 以及讯息缓冲区 (Message Buffer，类似 queue 服务) 等功能。

### 快取服务

Windows Azure AppFabric 的快取服务 (Caching Services)，是以微软的 Windows Server AppFabric 内的 Cache Service (研发代号为 Velocity) 为核心所组成，它是与memcached相同能力的分散式快取服务 (Distributed Cache Services)，现阶段会直接支援 ASP.NET 的快取 API (Cache API)，不过基于云端的特殊环境，它不支援所有在 Windows Server AppFabric Cache Service 上支援的快取功能，Caching Service 在2011年4月正式投入商转，并以快取容量 (Cache Capability) 为单位计费。

Caching Service 的 API 相当直觉，以 ASP.NET 来说，只要设定 Cache Provider (ASP.NET v4.0 以后的版本) 即可直接取用 Caching Service 的服务，或是如下程式码，直接以 API 来存取 Caching Service。

```csharp
// Declare array for cache host.
DataCacheServerEndpoint[] servers = new DataCacheServerEndpoint[1];
servers[0] = new DataCacheServerEndpoint("mytest.cache.int4.windows-test.net", 22233);

// Setup DataCacheSecurity configuration.
string strACSKey = "YWNzOmh0dHBzzzzvanJvdGhkb2N1bWVudGF0aW9udGVzdGluZy111WNoZS5hY2Nlc3Njb250cm9sLmlud" +
    "DMud2luZG93cy1pbnQubmV0L1dSQVB2MC45LyZvd25lciY0eDhHZTA5SlZTTUQ2VWIyWkNiaWlES1c0NXNzOFIxZjdWZVp0Y3lF" +
    "T2FFPSZodHRwOi8vSnJvdGhEb2N1bWVudGF0aW9uVGVzdGluZy5jYWNoZS5pbnQzLndpbmRvd3MtaW50Lm5ldA==";
var secureACSKey = new SecureString();
foreach (char a in strACSKey)
{
   secureACSKey.AppendChar(a);
}
secureACSKey.MakeReadOnly();
DataCacheSecurity factorySecurity = new DataCacheSecurity(secureACSKey);

// Setup the DataCacheFactory configuration.
DataCacheFactoryConfiguration factoryConfig = new DataCacheFactoryConfiguration();
factoryConfig.Servers = servers;
factoryConfig.SecurityProperties = factorySecurity;

// Create a configured DataCacheFactory object.
DataCacheFactory cacheFactory = new DataCacheFactory(factoryConfig);

// Get a cache client for the default cache.
DataCache defaultCache = cacheFactory.GetDefaultCache();

// Add and retrieve a test object from the default cache.
defaultCache.Add("testkey", "testobject");
string strObject = (string)defaultCache.Get("testkey");
```

### 整合服务

整合服务 (Integration Services) 是以 BizTalk Server 的核心引擎为主，透过 Windows Azure AppFabric Integration Services 的功能，企业可以很快的将应用程序与合作伙伴或第三方应用程序整合。

### 复合式应用程序

复合式应用程序 (Composite Application) 是 Windows Azure AppFabric 身为中间层应用程序服务器服务的最重要元件，它除了能让企业在云端上实现工作流程应用程序 (Workflow Application)，更可以整合现有在云端上的应用程序，不论是 Windows Azure 本身的或是 Windows Azure AppFabric 内的各项服务，都可以运用这个复合式应用程序模型 (Composition Model) 来发展复杂的企业应用。

## 应用程序开发支援

AppFabric 的存取控制以及 Service Bus 的必要功能，都显露了 REST API 供不同的用户端存取，开发人员只需要利用这些 API 即可存取 AppFabric 中的服务，尤其是 Access Control 在建立账户这个程序上，若利用 REST API 会较使用 acm.exe 工具快很多。

同时，AppFabric SDK 也包含了文件以及 Service Bus 所必要的组件 (即 Microsoft.ServiceBus.dll)，以供开发人员使用。

## 外部链接

- MSDN Windows Azure AppFabric Developer Center
- Windows Azure AppFabric Team Blog
- Windows Azure AppFabric Announcement Blog
- Windows Azure AppFabric SDK Documentation
- Windows Azure AppFabric Lab Enviroment
- Windows Azure AppFabric Management Portal