2009-07-18 150 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