在客户端和服务器之间保护用户名/密码的最佳实践

Run*_*sen 8 .net c# xml sql-server encryption

有一个应用程序(C#WPF),需要"回家"并从家庭服务器获取更新的东西.理论上,可能有成千上万的客户,需要通过公共互联网进行通信.

每个用户将首先注册用户名和密码.然后,当应用程序运行时,它将不时地调用home,以获取有关新版本,新闻,注释,用户消息以及其他特定于应用程序的内容的信息.这不是"每个人"的应用程序,但如上所述,仍然可能有相当多的用户 - 因此安全性是一个优先事项.我希望它非常非常难以打破,但如果不可能是一个选项,我也会这样做.:)

只需要支持几个基本操作;

  • 初次注册新用户
  • 验证用户名和密码
  • "自[TIMESTAMP]以来有什么新消息?" 手术
  • 客户发布评论,消息或其他允许的用户生成内容

服务器端的东西将在带有IIS7的Win2008服务器上.我没有几乎所需的WCF知识来实现​​这个项目的时间,所以我将来回使用XML文件做一些ASP.NET MVC 2魔术.如果你只有一把锤子..

我正在寻找的是如何在不使用它的情况下尽可能安全地做到这一点的建议.客户端的配置将保留在XML文件中.在服务器端,大多数东西都将存在于SQL服务器中.

我意识到这在某种程度上是一个意见问题,但我也相信它应该有可能达到某种最佳实践,我可以在晚上睡觉而不用担心客户端< - >服务器通信和用户有帐户被劫持等

  • 在客户端,密码应该存储为哈希我猜?或加密,有办法取回它?
  • 我在想客户端和服务器之间的HTTPS是一个很好的默认安全层.馊主意?没有?
  • 是否有必要使用此模型"登录"?是否应该与每个请求一起发送用户名/密码组合?
  • 如果我选择https,那么那是否足够安全?或者我还应该加密一些身份验证的东西?
  • 是否有一点指向服务器提供某种加密"令牌",它可以用作盐(我不太熟悉这里的术语)来进一步加密用户名/密码?
  • 基本上,我如何保护这个系统到客户端或服务器机器外面没有人可以窃取帐户信息的程度?我当然意识到,如果坏人得到一个正确的配置文件,那么该帐户就会受到损害.当然,该系统绝不允许使用此通信进行任何关键操作,所有这些都将在服务器上发生; 但是,我认为帐户黑客行为是一件非常非常糟糕的事情,我应该采取一切可能的措施来避免.

有什么好主意吗?

谢谢!

Rem*_*anu 5

您有两个不同的问题:验证注册用户和配置新用户帐户.

验证用户

这是简单的部分.你有几个选择:

  • HTTP身份验证(基本摘要).基本是一个笑话,所以它真的只留下Digest作为一个严肃的选择.
  • HTTP NTLM/Kerberos身份验证(也称为Windows集成身份验证)是防弹的,前提是您的客户端已加入NT域(不太可能).
  • SSL/TLS相互认证
  • HTTP"表单"身份验证.微不足道.
  • 通过安全通道进行基本或表单身份验证(HTTPS)

因此,剩下的实际选项是Digest,SSL mutual或基于加密通道的Basic/Forms.

HTTP摘要是很容易在客户端来实现,简单的用户名/密码添加到CredentialCache使用的WebRequest,你就大功告成了.在调用之间重用CredentialCache实例以从预身份验证中受益.不幸的是,服务器端的情况并不乐观:只有在与AD集成时才能正确支持摘要式身份验证,请参阅配置摘要式身份验证.

SSL/TLS客户端和服务器都支持相互身份验证,但是,只有在与AD集成时,服务器端才真正支持它,而不是真正的选项(请参阅配置客户端证书映射身份验证).

这就是为什么我认为在公司环境中不打算在VPN上使用的应用程序的唯一现实选项是通过安全通道(HTTPS)使用基本或表单身份验证.对于Basic,您必须提供密码din明文,并且对于Forms(在其通用的,未修改的版本中)也是如此,因此客户端必须能够访问明文密码,服务器也是如此.一种方式散列不起作用,您需要适当的加密安全存储.

现在确实,你可以"增强"表单身份验证方案来做相当复杂的事情,基本上在HTTP表单交换中设计一个Digest等价物,但我相信这超出了本讨论的范围.如果你冒险沿着这条路走下去,你应该真的知道自己在做什么,或者使用完善的解决方案(我不知道).

存储密码:对于Basic/Digest/Forms,客户端不存储密码,因为密码实际上是由用户提供的.最多可以保存密码以避免重新键入,这应该像存储在客户端上的任何用户特定秘密一样,通过ProtectedData类使用DPAPI加密.在服务器端,如果使用用户表,则密码应存储为单向散列.对于Basic和Form,任何哈希方案都可以使用(最好是盐腌).但是对于Digest,散列必须是摘要方案中的HA1散列:md5(username:realm:password)这样服务器就可以完成身份验证握手.虽然这样做需要对ASP附带的开箱即用成员资格提供程序进行一些非常有侵略性的重写,但它仍然是我推荐的方式.

供应用户

这有点棘手,因为它涉及建立初始信任.如果您查看上面提到的所有方案,您将看到除了基本/表格通过HTTPS之外的任何方案都可以在带内执行此操作:任何其他解决方案都需要通过带外方式初始部署用户帐户(带外指的是使用的方案).相互SSL需要证书配置,NTLM/Kerberos需要AD用户配置,Digest需要配置用户密码.对于Basic/Forms和Digest,有一个方便的"带外"解决方案:提交帐户创建表单的安全HTTPS通道.对于SSL/TLS证书和AD,事情更复杂.

的OpenID/OAuth的

一种完全不同的方法是委派身份验证.将OpenID与Google或Yahoo和OAuth等提供商与Facebook或Twitter等提供商一起使用.这对于web应用程序非常有用(StackOverflow本身使用这样的方案,你可能已经注意到OpenID,One Year Later).有一些库和集成提供程序可以让它像3点击和一行代码一样简单,比如JanRain.

OpenID和OpenAuth的唯一问题是这是一个交互式方案.它仅在用户积极参与登录/身份验证过程时才有效,从而消除所有自动化解决方案.如果您的应用程序正在进行任何类型的后台操作(例如,作为服务运行),或者如果在没有用户参与的情况下使用应用程序ID进行"电话回家",则OpenID/OAuth不起作用.