36

为与 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 授权标头,但是我发现代码不完整(请参阅从未声明过“UserKeys”变量的方式)。这就是我尝试更多地研究如何做到这一点(使用带有“授权”HTTP 标头的 HMAC 哈希,但在 google 上找不到太多内容?)它引导我阅读其他有关消息级安全性的文章,形成身份验证和自定义验证器,坦率地说,我不确定现在采取哪种方法是最好和最合适的。

综上所述(感谢您一直以来的聆听!),我想我的主要问题是,

- 我应该使用哪种安全实现?

- 有什么方法可以避免在每次 WCF 调用时发送用户名/密码?如果一开始就建立了连接,我不希望发送这些额外的字节,这将是在登录后允许进行后续调用之前。

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

如前所述,.NET 3.5 win forms 应用程序,IIS 托管的 WCF 服务,但重要的是我希望任何和所有 WCF 服务都需要此授权过程(但应该是会话、http 标头或其他),因为我不需要希望任何人都能够通过网络访问这些服务。

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

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

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

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

4 回答 4

17

好吧,我对 WCF 的 REST 功能没有任何经验,但我确实在理解我的 WCF 安全问题中的安全选择的含义方面做了很多努力。正如您所注意到的,Web 上确实缺乏关于 WCF 的文档,而且我的 REST 经验有限,因此请谨慎回答:

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

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

基于 SSL 的基本身份验证很好——毕竟,大量现有网站就是这样对用户进行身份验证的。(当您登录您的亚马逊购物账户时,他们只是在您通过 SSL 连接输入用户名和密码时传输您的用户名和密码。)我理解这篇文章中关于安全性和字典攻击的内容,但是等等等等,请保持简单并首先获得一些工作。UPS 的 Plain Old XML API 在每次调用时都要求提供用户名和密码,FedEx 的 POX API 也是如此,PayPal 的 SOAP API 和 Cyber​​Source 的 SOAP API 也是如此——这对于现实世界的使用来说似乎已经足够好了。

有什么方法可以避免在每次 WCF 调用中发送用户名/密码?如果一开始就建立了连接,我不希望发送这些额外的字节,这将是在登录后允许进行后续调用之前。

这是一个我可以更自信地回答的问题。通常,我们会尝试将面向公众的 WCF 服务设计为无状态的。这样,我们的 WCF 服务就可以轻松扩展;只需在问题上投入更多的硬件、更多的服务器和负载平衡器,我们就不必担心粘滞会话或在某处维护会话状态。所以这意味着如果我们想要“让用户保持登录状态”,那么这不会发生在服务器上。

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

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

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

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

希望能有所帮助。

于 2008-12-28T22:57:29.770 回答
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);
于 2010-03-31T18:16:44.310 回答
3

感谢您的回答。退后一步,清晰而公正地看待整个问题(换句话说,忽略我投入研究 RESTful 服务的 4 个多小时)我正试图让事情在没有 REST 的情况下工作,并且我试图遵循的参考资料现在是这些: -

这似乎适用于我想要的。

lextm:我听到了你的意见,在我写完这篇文章后,我仔细浏览了 WCF 安全指南,并根据他们希望你在每个原则上考虑的选项记录了我的所有要求。

我选择了:
- 传输安全模式:传输安全
- 身份验证。选项:基本安全
- 绑定:wsHttpBinding
- 使用用户名验证器的自定义身份验证

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

Nicholas:同意,将服务设计为无状态可能是更好的方法。

因此,根据我有空时将关注的文章,它使用了 X509 证书。我对它很陌生(知道你正在使用这个 Nicholas),因为这个客户端应用程序可以从互联网上下载并安装在任何拥有我网站帐户的人的 PC 上,这会很好吗?

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

PS:我认为这是与我的场景最接近的用例(除了我希望使用传输安全性),我是否应该考虑实施它,因为它不需要证书?从我读到的报价中,我可能需要证书。因为“WCF 需要 X509 证书加密,因为客户端凭据(用户名/密码)在 SOAP 消息中以明文形式传递。” - 但是根据我所学到的和我们所说的,如果我使用 SSL,这一点可能没有实际意义?

于 2008-12-29T05:24:22.813 回答
1

好吧,您真的不应该过多关注 WinForms 方面,因为 WCF 方面是关键。

顺便说一句,您是否仔细阅读了这些页面?

概念 http://www.codeplex.com/WCFSecurityGuide/Wiki/View.aspx?title=Ch%2005%20-%20Authentication,%20Authorization%20and%20Identities%20in%20WCF&referringTitle=Home

以及如何 http://www.codeplex.com/WCFSecurity/Wiki/View.aspx?title=How%20Tos&referringTitle=Home

于 2008-12-28T11:35:11.287 回答