【问题标题】:WPF-Client for WebAPI - how to handle password for authenticationWPF-Client for WebAPI - 如何处理身份验证密码
【发布时间】:2016-06-13 16:16:22
【问题描述】:

我正在使用 ASP.Net WebAPI 和 WPF 开发客户端/服务器应用程序。 现在我正在考虑通过 https 使用基本身份验证对客户端进行身份验证。您可以提出更好的解决方案,但 Windows 身份验证和服务器端会话对我不起作用。

对于基本身份验证,我需要客户端上的纯文本 (base64) 密码,以便在每次请求时通过网络发送,对吗?

但我不希望用户在每次请求时都重新输入密码,所以我在应用程序启动时有一个登录窗口。

WPF PasswordBox 使用 SecureString 并且未绑定到视图模型。但至少在请求之前,我必须将密码作为普通字符串将其编码为 base64。 所以不管我做什么,密码迟早都会以纯文本形式保存在 RAM 中。

为以后的请求保留密码的最佳做法是什么?

  • 缓存密码框
  • 缓存 SecureString
  • 缓存纯文本字符串,因为无论哪种方式它都会在 RAM 中
  • 缓存 base64 编码的字符串,因为至少它是模糊的 ;)
  • ...?

那么我该如何以一种相当安全的方式来处理这个问题呢? 大玩家(MS、Google、Apple 等)的其他应用程序不会在每次通话时都要求我输入密码,因此必须有办法。

【问题讨论】:

  • 您到底为什么要以 Base64 格式发送密码?这是一种简单的、未加密的编码,使用它为您做的就是使用更多的内存。 Base64 通常用于将二进制数据编码为字符串,而不是将字符串编码为较长的字符串。
  • 首先我要感谢您强调这一点,因为谈论安全主题是人们应该知道的。在这种情况下,base64 并没有真正帮助你是绝对正确的。我知道,在问这个问题之前我就知道了。这就是我写的原因:至少它是模糊的;) 但是为什么是base64?因为这就是基本身份验证与 WebAPI 一起工作的方式:see asp.net-site

标签: c# asp.net wpf authentication asp.net-web-api


【解决方案1】:

您应该阅读身份验证令牌,这是一种常用的方法,并且 asp.net-web-api 框架提供了 OWin 提供的许多功能。

基本上流程如下:

  • 在您的 web-api 上进行身份验证。
  • 返回一个令牌
  • 在每个后续 web-api/http 请求的标头中使用此令牌

好处:

  • 不将用户名和密码存储在内存中(好吧,仅用于一次调用)
  • 令牌可以在服务器端失效
  • web-api2 开箱即用的功能

你可以在这里阅读: http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

至于你的 WPF 客户端:

您可以使用以下命令为您的 http/web-api 请求创建一个 .net 客户端:

HttpClienthttps://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.118%29.aspx

一些伪代码如下所示:

public async Task<IEnumerable<DataContainer>> GetDataForTarget(string id)
{
    var requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(new Uri(Host),
        string.Format("api/Data?id={0}", id)));

        var response = await Client.SendAsync(requestMessage);

        //etc...
}

注意: 要使基于令牌的安全性工作,您需要 https,否则令牌可能会被拦截。每个知道令牌的人都可以代表相应的用户调用 web-api。因此,基本上问题从保护密码转移到保护令牌。令牌的好处是它的生命周期应该比密码短得多,这就是它更安全的原因。尽管如此,将令牌存储在SecureString 中是有争议的。

同时在服务器端

如果用户可以选择自己的密码,那么在您的服务器上使用单向加密机制来存储密码是一种很好的做法(如果不这样做,甚至是不道德的)。

这可以通过使用(加密强)随机salt 和使用salt 的非对称hash 加密来完成。

要验证用户,只需使用存储的盐对传入的密码进行加密,并检查它是否为您提供了存储的哈希值。在这种情况下,您的服务器上不会存储任何实际密码,并且无法检索用户密码(....嗯,排除了一些技术细节)。

【讨论】:

  • 谢谢,bitoftech.net 的链接已经启发了我一点。到目前为止,我认为令牌意味着服务器状态并且需要多个服务器的共享会话。但根据该站点,令牌是自包含的。所以我会读到那个。您提到第一个请求在内存中仍然有纯密码。我应该做些什么来尽快摆脱它,还是我必须把它留给 GC?
  • 嗯,例如securestring 的问题是,当您想使用它时,您需要将其转换为普通字符串,这是不安全的。因此,在这种情况下,如果您确保在继续之前清除托管字符串或文本框,这是您能做的最好的事情。
  • 另一件事:要使基于令牌的安全性工作,您需要https,否则令牌可能会被拦截。每个知道令牌的人都可以代表相应的用户调用 web-api。因此,基本上问题从保护密码转移到保护令牌。令牌的好处是它的生命周期应该比密码短得多,这就是它更安全的原因。尽管如此,将令牌存储在SecureString 中是有争议的。我会将此添加到我的答案中。
  • https 已经配置和测试,但感谢您的建议。证书固定在我的清单上。它就像一种魅力,我对此感觉很好,所以我接受了你的回答。只是一个小小的后续问题:令牌服务返回包含成员 access_token、token_type 和 expires_in 的 json。你知道是否有代表该对象的内置类?我自己做了,因为我找不到一个,当然它有效。但如果有一个内置的,我更喜欢那个
  • @alex;我知道任何提供这种数据容器的强类型。如果您使用Microsoft.Owin,则存在AuthenticationProperties,但据我所知,这使用Dictionary&lt;string,string&gt;,这与JSON 变体一样“松散”。
猜你喜欢
  • 2011-01-03
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 2014-04-05
  • 2010-11-18
  • 2016-11-15
相关资源
最近更新 更多