使用 RESTful WCF 和 Windows 窗体的用户/通过身份验证
Posted
技术标签:
【中文标题】使用 RESTful WCF 和 Windows 窗体的用户/通过身份验证【英文标题】:User/Pass Authentication using RESTful WCF & Windows Forms 【发布时间】:2010-09-28 14:17:37 【问题描述】:为与 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哈希,但在谷歌上找不到很多?)它引导我阅读其他关于消息级安全性的文章,形成身份验证和自定义验证器,坦率地说,我不确定现在采用哪种方法是最好和最合适的。
说了这么多(感谢您到现在为止的聆听!),我想我的主要问题是,
- 我应该使用哪种安全实施方式? - 有什么方法可以避免在每次 WCF 调用时发送用户名/密码?如果一开始就建立了连接,我不希望发送这些额外的字节,这将是在登录后允许进行后续调用之前。 - 如果我使用 SSL,我是否真的应该关心纯文本以外的任何内容?
如前所述,.NET 3.5 win 表单应用程序、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" ;
【问题讨论】:
您能否通过“...关于 RESTful WCF 服务的 PDC 视频...”的视频链接?谢谢。 在我的博客上 - goneale.wordpress.com/2008/12/28/… 非常感谢 :) 我确实发现了关于 TL35 的信息,我什至下载了高质量的 WMV 电影,但你有更多链接 ;) 【参考方案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
【讨论】:
【参考方案2】:好吧,我对 WCF 的 REST 功能没有任何经验,但我确实在理解my WCF security question 中安全选择的含义方面做了很多努力。正如您所注意到的,Web 上确实缺乏关于 WCF 的文档,而且我的 REST 经验有限,因此请谨慎回答:
我应该使用哪种安全实现?
和
如果我使用 SSL,我真的应该关心纯文本以外的任何内容吗?
基于 SSL 的基本身份验证很好——毕竟,大量现有网站就是这样对用户进行身份验证的。 (当您登录您的亚马逊购物账户时,他们只是在您通过 SSL 连接输入用户名和密码时传输您的用户名和密码。)我理解这篇文章中关于安全性和字典攻击的内容,但是等等等等,请保持简单并首先得到一些工作。 UPS 的 Plain Old XML API 在每次调用时都要求提供用户名和密码,FedEx 的 POX API 也是如此,PayPal 的 SOAP API 和 CyberSource 的 SOAP API 也是如此——这对于现实世界的使用来说似乎已经足够了。
有什么方法可以避免每次 WCF 调用都发送用户名/密码?如果一开始就建立了连接,我不希望发送这些额外的字节,这将是在登录后允许进行后续调用之前。
这是一个我可以更自信地回答的问题。通常,我们尝试将面向公众的 WCF 服务设计为无状态的。这样,我们的 WCF 服务就可以轻松扩展;只需在问题上投入更多的硬件、更多的服务器和负载平衡器,我们就不必担心粘滞会话或在某处维护会话状态。所以这意味着如果我们想“让用户保持登录状态”,那么这不会发生在服务器上。
我最终将我的网站视为一个受信任的子系统。它使用预共享的 X509 证书针对 WCF 服务进行身份验证,如果客户通过表单身份验证登录到网站,那么它将向服务发送客户用户名标头; WCF 服务上的自定义终结点行为将查找此标头,查看它是由受信任的子系统安装的,然后继续模拟该用户,而无需提供用户密码或针对数据库进行验证。
由于您使用的是 REST,因此您可能可以在客户端使用 cookie 来维护状态。如果您使用 ASP.NET 兼容模式,我认为您甚至可以直接使用表单身份验证,但我对这种方法了解不多,因为我的 WCF 服务不是 IIS 托管的。
不过,简而言之,您必须在每个请求中发送一些东西来识别用户,无论是用户名和密码,只是用户名,还是存储在饼干。如果是最后一个选项,我猜你必须在服务上有某种Login()
方法或其他东西,它会发送一个“好的,如果你在未来的请求中传递这个哈希值,你就会被记录”。但并非所有 REST 客户端都希望接收 cookie,只是没有任何状态的简单 GET/PUT/POST/DELETE 请求。
如果那是我的鞋子,我会选择受信任的子系统方法(其中提供用户名标头以及子系统的预共享凭据),或者我会要求每次调用都进行身份验证。如果所有这些重复请求都成为问题,该服务可能会获得一些高性能的身份验证缓存机制。
希望能有所帮助。
【讨论】:
部分“如果客户通过表单身份验证登录到网站,那么它将向服务发送客户用户名标头;WCF 服务上的自定义端点行为将查找此标头,看到它是由受信任的子系统安装的,然后继续模拟该用户,而无需提供用户密码或针对数据库进行验证..”正是我想要做的,但我不知道如何做。你能帮我拼一下吗? [piasecki.name/skiviez-crap/WCF-Trusted-Subsystem.zip](Here 是我前段时间为某人整理的示例。)使用 Windows 窗体作为示例客户端,但很容易转换为 ASP.NET——查看 UserNameMessageInspector 中的 cmets班级。没有保证,可能是疯狂的代码等,但希望它能让你到达某个地方! 好吧,搞砸了链接:piasecki.name/skiviez-crap/WCF-Trusted-Subsystem.zip 不过你明白了。 嗨@nicholas。我尝试下载你提供但不可用的那些 zip 文件。你能帮我拿那些 zip 文件吗?谢谢【参考方案3】:感谢您的回答。退后一步,清晰而公正地看待整个问题(换句话说,忽略我投入研究 RESTful 服务的 4 个多小时)我正试图让事情在没有 REST 的情况下工作,并且我试图遵循的参考资料现在是这些:-
http://blogs.msdn.com/pedram/archive/2007/10/05/wcf-authentication-custom-username-and-password-validator.aspx http://www.devatwork.nl/index.php/2007/05/31/wcf-username-authentication/这似乎适用于我想要的。
lextm:我听到你的意见,在我写完这篇文章后,我仔细浏览了 WCF 安全指南,并根据他们希望你考虑的选项记录了我的所有要求每个原则。
我选择了: - 传输安全模式:传输安全 - 授权。选项:基本安全 - 绑定:wsHttpBinding - 使用用户名验证器进行自定义身份验证
根据为每个示例提供的示例,并查看带有 WCF 服务的 Windows 窗体的用例,这似乎是最好的方法。
Nicholas:同意,将服务设计为无状态可能是更好的方法。
因此,根据我有空时将关注的文章,它使用了 X509 证书。我对它很陌生(知道你正在使用这个 Nicholas),因为这个客户端应用程序可以从互联网上下载并安装在任何拥有我网站帐户的人的 PC 上,这会很好吗?
为您的帮助干杯, 格雷厄姆
PS:I think this is the closest use case to my scenario(除了我希望使用传输安全性),我是否应该考虑实施它,因为它不需要证书?从我读到的报价中,我可能需要证书。作为“WCF 需要 X509 证书加密,因为客户端凭据(用户名/密码)在 SOAP 消息中以明文形式传递。” - 但是根据我所学到的和我们所说的,如果我使用 SSL,这一点可能没有实际意义?
【讨论】:
说的是同一件事,只是措辞更复杂。 SSL 证书是您的 X509 证书(X509 只是一个容器规范),WCF 将使用它来保护和信任传输层。因此,您可以在消息中传递您想要的任何内容,而不必担心消息级加密。 ... 所以,在基本用户名/密码验证中,您告诉服务器要使用什么证书,并且客户端有几个选项可以设置信任连接上的证书。但是客户端本身不使用自己的客户端证书进行身份验证,它使用用户名/密码。 ...这很令人困惑,因为在这两种情况下都使用证书,但是当客户端在客户端和服务器上都安装了 X509 证书并使用它进行身份验证时,WCF 导致 X509 证书身份验证的原因。您将只有一个服务器证书来保护连接。 HTH!【参考方案4】:使用基本身份验证:
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);
【讨论】:
以上是关于使用 RESTful WCF 和 Windows 窗体的用户/通过身份验证的主要内容,如果未能解决你的问题,请参考以下文章
用于支持 HTTP 和 HTTPS 的 WebHttpBinding(Restful) 的 WCF 配置