宣告、Azure 與 SharePoint 整合工具組第 2 部分
宣告、Azure 與 SharePoint 整合工具組第 2 部分
這是 CASI (宣告、Azure 與 SharePoint 整合) 套件的第 2 部分 (共 5 個部分)。 第 1 部分: 是整個架構與解決方案的簡介,並說明此系列嘗試執行和涵蓋的內容。 在本文中,我們將著重在此方法的模式:
1. 使用自訂 WCF 應用程式做為資料與內容的前端
2. 使其成為宣告感知
3. 進行一些額外的變更,以移動至 Windows Azure 雲端
使用 WCF
CASI 套件架構的重要先決條件是所有的應用程式資料均使用 WCF 應用程式做為前端。 就像所有的自訂應用程式一樣,這是身為開發人員的您需要建立的項目。 這個部分的專案幾乎不需要 SharePoint 的相關知識,任何可以使用 Visual Studio 建立 WCF 應用程式的 .NET 開發人員都可以完成此工作。 如果您的終極目標是在 Windows Azure 中裝載這個 WCF 服務,我強烈建議您使用 Windows Azure 開發套件下載範本以建立 Azure 應用程式,並從頭開始建立 Azure WCF 應用程式。 值得指出的是,目前的 CASI 套件版本有一個重要的限制。 CASI 套件只支援將核心 .NET 資料類型做為參數傳送至 WCF 方法。 因此您可以使用字串、布林值、整數與日期,但是沒有方法可以將自訂類別做為參數來傳遞。 不過,如果您需要這樣做,我建議您將參數建立為字串,並先將參數還原序列化成 XML 再呼叫 WCF 方法,然後再將它序列化為 WCF 程式碼中的物件執行個體。 除了這個限制,到目前為止我還沒發現任何較大的問題,但我相信在更多人採用和使用此套件後,使用者的希望清單很快就會隨之出現。 附註說明,您今天看到的套件其實是我將所有項目整合起來的第 1 版想法,它是根據我本身認為的重要元素所設計的。 毫無疑問地,此套件尚有改進的空間。
使其成為宣告感知
在建立 WCF 應用程式後,下一步就是使其成為宣告感知。 這個步驟不在我所發表的文章中,請參考共四個部分的「特優」部落格文章,這篇文章由 Office 團隊的 Eric White 所撰寫,說明如何將 SharePoint 的宣告整合至 WCF 應用程式。 假設您已經建立 WCF 服務,我將從 Eric 部落格的第二部分開始說明: https://blogs.msdn.com/b/ericwhite/archive/2010/05/13/determining-caller-identity-within-a-wcf-web-service.aspx (可能為英文網頁)。 您也「必須」繼續執行他在第 3 部分所述的步驟: https://blogs.msdn.com/b/ericwhite/archive/2010/06/18/establishing-trust-between-a-wcf-web-service-and-the-sharepoint-2010-security-token-service.aspx (可能為英文網頁) 從以下章節標題開始: 程序:在 Web 服務與 SharePoint Server 之間建立信任 (可能為英文網頁) 。 從此處開始您必須執行所有的步驟,這可有效地複製 SharePoint STS Token 簽署憑證的指紋,並將其他部分資訊複製到 WCF 應用程式的 web.config 檔案中。 我「不會」逐步遵循第 3 部分的 SSL 步驟,因為當 Windows Azure 裝載應用程式時,使用自我簽署憑證並不是非常實用。 但如果您沒有其他方法可以使用,也只好這樣做,但是整體而言,您應該計畫為您的 Windows Azure WCF 應用程式從適當的憑證授權取得適當的 SSL 憑證。 附註: 您「不」需要執行 Eric 部落格第 4 部分的步驟。 遵循上方所述的步驟後,您現在會有一個可運作的 WCF、SharePoint 宣告感知應用程式。 在本文章的最後階段,我將引導您逐步完成需要執行的額外步驟,以便向上移動到 Windows Azure 中。
使其可在 Windows Azure 中運作
既然已經有可運作的 WCF Azure 應用程式,您必須完成其他的項目才能繼續透過 Windows 身分識別架構 (Windows Identity Framework,WIF) 支援宣告驗證與 Token,並在 Windows Azure 雲端中裝載它。 讓我們在此擬定清單:
1. 設定您的 WebRole 專案 (也就是您的 WCF 專案),從而使用本機虛擬目錄進行偵錯。 我發現使用憑證比使用 VS.NET 開發伺服器更為容易。 若要變更這個設定,請按兩下 WebRole 專案屬性,然後按一下 [Web] 索引標籤。 請選取標示 [使用本機 IIS Web 伺服器] 的選項按鈕,然後按一下 [建立虛擬目錄] 按鈕。 建立虛擬目錄後,即可關閉專案屬性。
2. 在 WebRole 專案中新增 Microsoft.Identity 的參照。 您「必須」將參照變更為 Copy Local = true 與 Specific Version = false。 這是使用應用程式套件將 WIF 組件複製到雲端的必要動作。
3. 取得這個 WCF Hotfix: https://code.msdn.microsoft.com/KB981002/Release/ProjectReleases.aspx?ReleaseId=4009 (可能為英文網頁) 適用於 Win2k8 R2、 https://code.msdn.microsoft.com/KB971842/Release/ProjectReleases.aspx?ReleaseId=3228 (可能為英文網頁) 適用於 Win2k8。
4. 您「必須」將這個屬性新增至 WCF 類別: [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]。 例如,這個類別如下所示:
namespace CustomersWCF_WebRole
{
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Customers : ICustomers
{
5. 您「必須」在服務所使用的行為元素中包括下列設定資料。 它會修復在 Azure 環境中隨機連接埠指定可能會發生的問題。 若要在本機測試,您將需要取得在前面 #3 所述的 Hotfix:
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="http" port="80" />
<add scheme="https" port="443" />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
以下是我的 WCF 服務 web.config 內容的範例:
<behaviors>
<serviceBehaviors>
<behavior name="CustomersWCF_WebRole.CustomersBehavior">
<federatedServiceHostConfiguration name="CustomersWCF_WebRole.Customers"/>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="http" port="80" />
<add scheme="https" port="443" />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
</serviceBehaviors>
</behaviors>
6. 先將用於 WCF 應用程式的 SSL 憑證上傳至 Azure 開發人員入口網站。 附註: CASI 套件的基礎類別必須使用 SSL,因此,您必須在 WCF Windows Azure 應用程中實作 SSL支援。 這是在雲端服務與 SharePoint 伺服器陣列之間傳遞機密資料的預期需求。接著按兩下 WebRole 專案名稱 (在 Roles 資料夾中),將憑證新增至 Visual Studio 中的 Azure 角色屬性。 我發現也可以使用萬用字元憑證。 但您需要 PFX 憑證,並確定建立 PFX 檔案時會匯出鏈結中的所有憑證。 當您將該檔案上傳到開發人員入口網站時,Azure 將會展開它們全部。
7. 即使所有的 Azure 應用程式裝載於 cloudapp.net,您的 SSL 憑證也會適用於 someName.yourDnsName.com。 例如,我的 SSL 憑證使用萬用字元憑證 *.vbtoys.com。 在 DNS 中,我會建立名為 azurewcf.vbtoys.com 的新 CNAME 記錄,而且它會參照 myAzureApp.cloudapp.net。 因此當我連線至 https://azurewcf.vbtoys.com 時我的憑證可運作,因為我的要求與 SSL 憑證適用於 *.vbtoys.com,但是 DNS 會根據 CNAME 記錄重新導向我的要求,這將會重新導向至 myAzureApp.cloudapp.net。
8. 在您的 Azure 專案中,按兩下 WebRole 專案名稱 (在 Roles 資料夾中),然後將這些屬性設定如下:
a. [設定] 索引標籤: 取消核取 [啟動瀏覽器對象]: HTTP 與 HTTPS 端點
b. [憑證] 索引標籤: 新增您的服務要使用的 SSL 憑證。 例如,在我的實驗室中,我使用的是由我的網域針對所有網頁伺服器所發出的萬用字元憑證,因此我會在這裡新增萬用字元憑證。
c. [端點] 索引標籤: 同時核取 HTTP 與 HTTPS 方塊 (名稱應該分別是 HttpIn 與 HttpsIn)。 在 HTTPS 區段中,SSL 憑證名稱下拉式清單現在應該包含您在步驟 b 中新增的 SSL 憑證。
9. 如果您具有傳回指令碼的 WCF 方法,則指令碼標籤必須包括 DEFER 屬性,才能在使用 CASI 套件隨附的網頁組件時正常運作,或除非您自己的 JavaScript 函數指派該屬性給 innerHTML 標籤。 例如,您的指令碼標記看起來應該如下: <script defer language='javascript'>
10. 如果您的 WCF 方法會傳回包括其他格式設定標籤的內容 (例如 <style>),則需要將這些標籤封裝在 <pre> 標籤中,否則使用 CASI 套件隨附的網頁組件時將無法正確處理它們,或除非您自己的 JavaScript 函數指派該屬性給 innerHTML 標籤。 例如,您使用樣式標籤傳回的內容應該如下:<pre><style>.foo {font-size:8pt;}</style></pre>
這些是設定要在 Azure 中裝載 WCF 應用程式所需的步驟;視您的實作而定,以下秘訣在某些情況下可能非常有用,甚至是不可或缺:
1. 建立使用服務的端點位址時,請使用全名,例如 machineName.foo.com,而不只是 machineName。 這最不會在轉換為 Windows Azure 裝載的最終格式時發生問題,而且也會清除 SSL 憑證設計為使用全名網域名稱時所發生的錯誤。
2. 如果您想要在 SSL 上取得 WSDL,您「可能」要新增此屬性:將 httpsGetEnabled="true" 新增至此元素:<serviceMetadata httpGetEnabled="true" />。 不過,目前 SharePoint Designer 中的錯誤將使您無法使用使用 SSL 取得 WSDL。
3. 如需偵錯與資料連線秘訣,請參閱我的文章: https://blogs.technet.com/b/speschka/archive/2010/09/19/azure-development-tips-for-debugging-and-connection-strings.aspx (可能為英文網頁)。
4. 在大多數的情況下,您應該假設 WCF 服務命名空間是 https://tempuri.org。 如需如何變更命名空間的說明,您可以閱讀以下網址的文章: https://blogs.infosupport.com/blogs/edwinw/archive/2008/07/20/WCF_3A00_-namespaces-in-WSDL.aspx (可能為英文網頁)。
完成的 WCF 服務
如果您遵循上述的所有設定步驟並將 WCF 應用程式部署到 Windows Azure,這時當使用者從 SharePoint 網站呼叫 WCF 服務時,您也會取得他或她的整個使用者 Token,以及與該 Token 關聯的所有宣告。 即使進行變更,WCF 服務也可以在內部部署中運作,因此如果將應用程式推入雲端之前您想嘗試其他漸進式變更,您也可以立即進行測試。 擁有該使用者 Token 可讓您在 WCF 服務中進行一些很有趣的事情。 例如,在 WCF 服務中,您可以列舉所有的使用者宣告,並根據該 Token 來決定任何類型的微調權限。 以下是針對使用者宣告集使用 LINQ 的範例,可判斷目前的使用者是否為系統管理員。因為如果他或她是系統管理員,則會在要求中傳回額外的詳細資料層次:
//look for the claims identity
IClaimsIdentity ci =
System.Threading.Thread.CurrentPrincipal.Identity as IClaimsIdentity;
if (ci != null)
{
//see if there are claims present before running through this
if (ci.Claims.Count > 0)
{
//look for a group claim of domain admin
var eClaim = from Microsoft.IdentityModel.Claims.Claim c in ci.Claims
where c.ClaimType ==
"https://schemas.microsoft.com/ws/2008/06/identity/claims/role" &&
c.Value == "Domain Admins"
select c;
//see if we got a match
if (eClaim.Count() > 0)
//there’s a match so this user has the Domain Admins claim
//do something here
}
}
更棒的是您也可以直接在 WCF 方法上設定權限需求。 例如,假設您的 WCF 方法會查詢資料儲存區,並傳回客戶 CEO 的清單。 但您希望只有 Sales Manager (不是所有員工) 可以存取這些資訊。 有一種方法可以輕鬆且巧妙地實作這項作業:在方法中使用 PrincipalPermission 需求,如下所示:
//the customer CEO list should not be shared with everyone,
//so only show it to people in the Sales Manager role
[PrincipalPermission(SecurityAction.Demand, Role = "Sales Managers")]
public string GetCustomerCEOs()
{
//your code goes here
}
現在,假設有任何人嘗試呼叫這個方法,如果他們沒有 “Sales Managers” 的宣告,且如果他們執行嘗試呼叫此方法的程式碼,將會收到拒絕存取的訊息。 是不是很棒!
請務必瞭解這個步驟非常重要。 例如,您不能只在實驗室建立自己的網域,然後新增帳戶至其中,並為您新增的帳戶建立 Sales Manager 角色。 這種方式不能運作的原因要回溯到您在閱讀 Eric White 的部落格時所執行的步驟 (在上述標題為<使其成為宣告感知>的小節中)。 回想一下,您新增了 SharePoint STS 所使用的 Token 簽署憑證指紋。 這表示當宣告進入 WCF 應用程式時,它會尋找 SharePoint STS 的公開金鑰所簽署的 Token。 只有 SharePoint STS 可以使用公開金鑰簽署它,因為它是唯一具有 Token 簽署憑證私密金鑰的實體。 這會確保只有向 SharePoint 伺服器陣列驗證的人可以使用 WCF 服務,而且使用者只會擁有登入時授與他們的宣告。 不過,有趣的是,它不僅包括他們向使用者目錄驗證時授與他們的宣告,「同時」也包括所有透過任何自訂宣告提供者在 SharePoint 中的宣告增強所提供給他們的額外宣告。 因此這是真正整合的端對端解決方案。
下一個步驟
在下一篇的文章中,我將開始說明自訂基礎類別以及 CASI 套件隨附的網頁組件,這將可讓您快速且輕鬆地連線至新的 Azure WCF 應用程式。 現在,我將使用我為 CASI 套件所撰寫的 WCF 服務來示範這些功能。 我在本文章中附加了用於此服務的 .cs 檔案。 您無法直接使用它,但您可從此檔案暸解不同方法、包含的資料類型,以及為此套件所實作的某些功能。 在下列文章中,您會看到我主要使用:a) GetAllCustomersHtml、b) GetCustomerCEOs 以及 c) GetAllCustomers 方法。 這些方法很有趣,因為它們會 a) 傳回 HTML (這實際上是網頁組件中顯示資料的慣用傳回類型)、b) 使用 PrincipalPermission 需求以及 c) 顯示您如何從 WCF 應用程式傳回自訂類別類型,並在從 SharePoint 與 CASI 套件取回資料之後使用相同的豐富類別類型。
這是翻譯後的部落格文章。英文原文請參閱 The Claims, Azure and SharePoint Integration Toolkit Part 2