2009-07-18 151 views
5

我正在使用Silverlight v3 Web應用程序,並且想要保護對我用於提取數據的WCF服務的訪問。我目前有WCF工作得很好,但它不需要任何用戶憑證。WCF +用戶憑證

我對WCF的這方面並不是很有經驗,所以我的第一個想法是爲每個服務的操作添加用戶名和密碼參數。我遇到的問題是,這需要大量冗餘代碼,並且用戶名和密碼將通過純文本傳輸。

我想要的是在創建我的服務代理(我使用從「添加服務引用」自動生成的代理)後,在客戶端預先指定憑據的方式。

在Google上搜索解決方案時,我只能找到類似於我的第一個想法(使用用戶名/密碼參數)的解決方案。有人能指點我正確的方向嗎?

謝謝!

回答

7

這些用戶名和密碼來自哪裏?如果您的網站已經實現了表單身份驗證,那麼您可以自行繞過設置憑據並使用表單身份驗證Cookie。如果您的用戶已經登錄,那麼Cookie將隨着Web服務呼叫一起前往。爲了在另一邊閱讀它,你需要做一些改變。

首先你需要啓用WCF ASP.NET兼容模式在system.ServiceModel部分:

<system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
</system.serviceModel> 

一旦這樣做了,然後針對每個服務方法,你想了解ASP.NET餅乾添加[AspNetCompatibilityRequirements]屬性服務類

[ServiceContract] 
[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public class ExampleService 
{ 
} 

現在每個方法中,你可以訪問HttpContext.Current.User.Identity對象來發現用戶的身份。

如果你只希望某些方法來通過身份驗證的用戶被稱爲那麼你可以,如果你正在使用ASP.NET的角色提供那麼這些也將被填充使用這樣的PrincipalPermission

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)] 
public string Echo() 

作爲獎勵和那麼你可以使用方法來的PrincipalPermission他們限制在一個特定的角色的成員:

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Role="Administators")] 
public string NukeTheSiteFromOrbit() 

而這也顯然是工作在Silverlight2。

+0

看起來不錯;如果使用原始的httpwebrequest,你碰巧知道這個(或類似的)是否可用?我有一個自定義的RPC棧,我想以同樣的方式獲得保護(當然,如果這是一個非平凡的答案,我當然可以問一個新的queston) – 2009-07-18 09:00:12

+0

它應該是的;見http://www.silverlightshow.net/items/Cookies-in-Silverlight-Web-Requests.aspx – blowdart 2009-07-18 09:22:49

+0

Ta;我會看看; - – 2009-07-18 09:38:24

0

您可以傳入某種認證對象,並使用WCF在消息級對其進行加密。然後可以使用C#方面(http://www.postsharp.org/)來避免冗餘邏輯。它是處理它的一個非常乾淨的方式。

1

不要滾動你自己並添加顯式參數 - 這確實是太多的工作!

查看WCF安全功能 - 大量可用!你可以例如保護消息並在消息內包含憑證 - 所有開箱即用,不需要額外編碼!

檢查出WCF安全這個優秀的文章米歇爾·勒魯布斯塔曼特:http://www.devx.com/codemag/Article/33342

在你的情況,我建議信息安全與用戶名憑據 - 你需要在兩端配置此:

服務器端:

<bindings> 
    <basicHttpBinding> 
    <binding name="SecuredBasicHttp" > 
     <security mode="Message"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<services> 
    <service name="YourService"> 
    <endpoint address="http://localhost:8000/MyService" 
       binding="basicHttpBinding" 
       bindingConfiguration="SecuredBasicHttp" 
       contract="IYourService" /> 
    </service> 
</services> 

而且你需要在客戶端應用相同的設置:

<bindings> 
    <basicHttpBinding> 
    <binding name="SecuredBasicHttp" > 
     <security mode="Message"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<client> 
    <endpoint address="http://localhost:8000/MyService" 
       binding="basicHttpBinding" 
       bindingConfiguration="SecuredBasicHttp" 
       contract="IYourService" /> 
</client> 

現在你的服務器和客戶商定的安全性 - 在客戶端上,你會然後指定的用戶名和密碼才能使用這樣的:

YourServiceClient client = new YourServiceClient(); 

client.ClientCredentials.UserName.UserName = "your user name"; 
client.ClientCredentials.UserName.Password = "top$secret"; 

在服務器端,你需要設置如何驗證這些用戶憑據 - 通常是針對Windows域(Active Directory)還是針對ASP.NET成員資格提供程序模型。無論如何,如果無法根據您定義的商店驗證用戶憑證,該呼叫將被拒絕。

希望這會有所幫助 - 安全性是WCF的一大話題,有很多選項 - 它可能有點令人生畏,但最終通常它是有意義的! :-)

Marc

+6

我不確定你能做到這一點的情況,但根據我的經驗,這在WCF中是不允許的。您不能在basicHttpBinding中使用消息模式用戶名 - 憑證安全性,它不被框架使用,因爲憑證將以純文本形式傳遞。您將得到以下InvalidOperationException:「BasicHttp綁定要求BasicHttpBinding.Security.Message.ClientCredentialType與安全郵件的BasicHttpMessageCredentialType.Certificate憑證類型相同。爲UserName憑證選擇Transport或TransportWithMessageCredential安全性。」 – Grank 2009-09-11 16:33:47