我正在使用 ASP.Net WebAPI 和 WPF 开发客户端/服务器应用程序。 现在我正在考虑通过 https 使用基本身份验证对客户端进行身份验证。您可以提出更好的解决方案,但 Windows 身份验证和服务器端 session 对我不起作用。
对于基本身份验证,我需要在客户端上以纯文本 (base64) 的形式在每次请求时通过网络发送密码,对吧?
但我不希望用户在每次请求时都重新输入密码,所以我在应用程序启动时有一个登录窗口。
WPF PasswordBox 使用 SecureString 并且未绑定(bind)到 View 模型。但至少在请求之前,我必须将密码作为普通字符串进行编码以将其编码为 base64。 所以无论我做什么,密码迟早都会以纯文本形式存在于 RAM 中。
为以后的请求保留密码的最佳做法是什么?
- 缓存密码框
- 缓存 SecureString
- 缓存一个纯文本字符串,因为无论哪种方式它都会在 RAM 中
- 缓存 base64 编码的字符串,因为至少它是模糊的 ;)
- ...?
那么我该如何以一种合理安全的方式处理这个问题呢? 大玩家(MS、Google、Apple 等)的其他应用程序不会在每次通话时都要求我提供密码,因此必须有办法。
最佳答案
您应该阅读身份验证 token ,这是一种常用的方法,asp.net-web-api 框架提供了 OWin 提供的许多功能。
基本上流程如下:
- 在您的网络 API 上进行身份验证。
- 返回一个 token
- 在每个后续 web-api/http 请求的 header 中使用此标记
好处:
- 不将用户名和密码存储在内存中(好吧,仅用于一次调用)
- token 可以在服务器端失效
- 开箱即用的 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 客户端:
HttpClient
https://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...
}
注意:
要使基于 token 的安全性发挥作用,您需要 https,否则 token 可能会被拦截。知道 token 的每个人都可以代表相应的用户调用 web-api。因此,问题基本上从保护密码转移到保护 token 。 token 的好处是它的生命周期应该比密码短得多,这就是它更安全的原因。然而,将 token 存储在 SecureString
中是有争议的。
同时在服务器端
如果用户可以选择自己的密码,那么在服务器上使用单向加密机制来存储密码是一种很好的做法(如果不这样做甚至是不道德的)。
这可以通过使用(强加密)随机salt
和使用该salt
的非对称hash
加密来实现。
要验证用户,只需使用存储的 salt 加密传入的密码,然后检查它是否为您提供存储的哈希值。在这种情况下,您的服务器上不会存储任何实际密码,也无法检索用户密码(....嗯,排除了一些技术细节)。
关于c# - WebAPI 的 WPF 客户端 - 如何处理身份验证密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35719642/