使用RESTful WCF进行用户/通过身份验证& Windows窗体

时间:2008-12-28 05:47:58

标签: .net wcf restful-authentication ws-security

对于与IIS托管的RESTful WCF服务进行通信的Windows窗体应用程序实施授权/身份验证的最佳方法是什么?

我问的原因是我非常困惑,在筛选出不同的文章和帖子后,表达了不同的方法并最终在WCF安全最佳实践中找到了约650页的文档“(http://www.codeplex.com/WCFSecurityGuide)我只是不确定哪个根据我的情况,方法是最好的,如何开始实施。

我开始阅读本文“使用WCF 3.5设计和构建RESTful Web服务的指南”(http://msdn.microsoft.com/en-us/library/dd203052.aspx)和关于RESTful WCF服务的PDC视频,这非常棒,并帮助我实现了我的第一个REST友好WCF服务,

在我使用该服务之后,我返回实施安全性,请参阅。 “安全注意事项”(页面下方四分之一)并尝试按照说明实现HTTP Authorization标头,但是我发现代码不完整(请参阅“UserKeys”变量从未声明的方式)。这是我试图研究如何做到这一点的更多点(使用带有“授权”HTTP标头的HMAC哈希,但在谷歌上找不到多少?)它引导我阅读有关消息级安全性的其他文章,形成auth和自定义验证器,坦率地说,我不确定哪种方法最好,最合适。

所有这些都说了(感谢收听到现在为止!),我想我的主要问题是,

- 我应该使用哪种安全措施?

   - 有没有办法避免每次WCF呼叫都发送用户名/密码?如果在开始时建立了连接,我宁愿不发送这些额外的字节,这将在登录后允许进行后续调用之前发送。

   - 如果我使用SSL,我是否真的应该关注纯文本以外的任何内容?

如上所述,.NET 3.5 win表单应用程序,IIS托管的WCF服务,但重要的是我希望任何和所有WCF服务都需要此授权程序(但它应该是,session,http header或其他)as我不希望任何人能够从网上获得这些服务。

我知道上面的帖子很大但我必须表达我已经失败的路线以及我需要完成的任务,我们非常感谢所有的帮助。

PS:我也知道这篇文章How to configure secure RESTful services with WCF using username/password + SSL如果社区建议我从REST转移到WCF服务,我可以这样做,但是我开始这样做是为了保持任何公共API的一致性

我认为重要的是我说明了我如何访问我的WCF服务(联系服务正在运行,但验证凭据的最佳方法是什么 - 然后返回Member对象?):

WebChannelFactory<IMemberService> cf = new WebChannelFactory<IMemberService>(
                new Uri(Properties.Settings.Default.MemberServiceEndpoint));
            IMemberService channel = cf.CreateChannel();
            Member m = channel.GetMember("user", "pass");

代码是从MS文章(以及我自己的一些用于测试)实现的一半:

 public Member GetMember(string username, string password)
    {
        if (string.IsNullOrEmpty(username))
            throw new WebProtocolException(HttpStatusCode.BadRequest, "Username must be provided.", null);
        if (string.IsNullOrEmpty(password))
            throw new WebProtocolException(HttpStatusCode.BadRequest, "Password must be provided.", null);

        if (!AuthenticateMember(username))
        {
            WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
            return null;
        }

        return new Member() { Username = "goneale" };
    }

4 个答案:

答案 0 :(得分:17)

好吧,我对WCF的REST功能没有任何经验,但我确实在理解my WCF security question中安全性选择的含义时进行了很多努力。正如你所注意到的那样,WCF在Web上的文档确实缺乏,而且我的REST体验有限,所以请耐心等待我的答案:

我应该使用哪种安全实施?

如果我使用SSL,我是否真的应该关注纯文本以外的任何内容?

基于SSL的基本身份验证很好 - 毕竟,这是大量现有网站对用户进行身份验证的方式。 (当您登录到您的亚马逊购物帐户时,他们只是在您通过SSL连接键入时发送您的用户名和密码。)我理解文章中关于安全和字典攻击的内容,但是等等等等等等,请保持简单并先获得一些工作。 UPS的普通旧XML API会在每次调用时询问用户名和密码,FedEx的POX API也是如此,PayPal的SOAP API和Cyber​​Source的SOAP API也是如此 - 这似乎足以满足现实世界的使用。

有没有办法避免每次WCF呼叫都发送用户名/密码?如果在开始时建立了连接,我宁愿不发送这些额外的字节,这将在登录后允许进行后续调用之前。

这是我可以更自信地回答的问题。通常,我们尝试将面向公众的WCF服务设计为无状态。这样,我们的WCF服务很容易扩展;只是在问题上抛出更多的硬件和更多的服务器和负载均衡器,我们不必担心粘性会话或在某处维护会话状态。这意味着如果我们想“让用户登录”,那么服务器上就不会发生这种情况。

我最终做的是将我的网站视为受信任的子系统。它使用预共享X509证书对WCF服务进行身份验证,如果客户通过表单身份验证登录到网站,则会向服务发送客户用户名标头; WCF服务上的自定义端点行为将查找此标头,查看它是否由受信任的子系统安装,并继续模拟该用户,而无需为数据库提供或验证用户的密码。

由于您使用的是REST,因此您可以在客户端使用cookie来维护状态。如果您使用ASP.NET兼容模式,我认为您甚至可以直接使用表单身份验证,但我不太了解这种方法,因为我的WCF服务不是IIS托管。

简而言之,您将不得不向每个请求发送某些内容以识别用户,无论是用户名和密码,只是用户名,还是存储在的某些散列值饼干。如果是最后一个选项,我猜你必须在服务上使用某种Login()方法或其他东西,这会发送一个“好吧,如果你将这个哈希值传递给将来的请求,你就会被记录“。但并非所有REST客户端都希望接收cookie,只需要简单的GET / PUT / POST / DELETE请求,而不需要任何状态。

如果这些是我的鞋子,我要么采用可信子系统方法(提供用户名标题以及子系统的预共享凭证),要么我需要在每次调用时进行身份验证。如果所有这些重复请求都成为问题,该服务可能会获得一些高性能的身份验证缓存机制。

希望有所帮助。

答案 1 :(得分:7)

使用基本身份验证:

WebHttpBinding binding = new WebHttpBinding();
binding.SendTimeout = TimeSpan.FromSeconds(25);
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

Uri address = new Uri("http://localhost:3525/WcfRestWeb/Quotes.svc");

WebChannelFactory<IQuoteService> factory =
             new WebChannelFactory<IQuoteService>(binding, address);

factory.Credentials.UserName.UserName = "tan";
factory.Credentials.UserName.Password = "wani";

IQuoteService proxy = factory.CreateChannel();

var response = proxy.GenerateQuote(GetQuoteRequest());
Console.WriteLine("Quote Amount: " + response.QuoteAmount);

答案 2 :(得分:3)

感谢您的回答。退一步,看清楚,不偏不倚地解决整个问题(换句话说,忽略了我投入的4个多小时调查RESTful服务)我试图让这个东西在没有REST的情况下工作,以及我试图遵循的参考资料现在是这些: -

这似乎适合我想要的。

lextm 我听到了这个消息,在我撰写帖子后,我仔细检查了WCF安全指南并根据他们希望您考虑的选项记录了我的所有要求每个宗旨。

我选择了:
- 转移安全模式:运输安全
- Auth。选项:基本安全
- 绑定:wsHttpBinding
- 使用用户名验证器进行自定义验证

根据为每个示例提供的示例并查看具有WCF服务的Windows窗体的用例,它似乎是最好的方法。

Nicholas:同意,将服务设计为无国籍可能是一种更好的方法。

因此,根据我得到时间的文章,它将使用X509证书。这是我的新手(了解你正在使用这个尼古拉斯)这将是好的,因为这个客户端应用程序可以从互联网上下载并安装在任何人的PC上,我的网站上有一个帐户?

为你的所有帮助干杯, 格雷厄姆

PS:I think this is the closest use case to my scenario(除了我希望使用传输安全性),我是否应该考虑实施此项,因为它不需要使用证书?从我读的报价中我可能需要证书。 as“WCF需要X509证书加密,因为客户端凭据(用户名/密码)在SOAP消息中以明文形式传递。” - 但是,根据我所学到的和我们所说的内容,如果我使用SSL,这一点可能没有实际意义吗?

答案 3 :(得分:1)