生成加密安全身份验证令牌

Erv*_*ter 56 c# security iphone wcf web-services

背景:

这实际上是一个一般的最佳实践问题,但有关具体情况的一些背景可能会有所帮助:

我们正在为iPhone开发一个"连接"应用程序.它将通过REST服务与后端应用程序通信.为了在每次启动应用程序时不必提示用户输入用户名和密码,我们将公开一个"登录"服务,该服务在初始启动时验证其用户名和密码,并返回可用于将来Web的身份验证令牌服务请求真实数据.令牌可能有一个到期时间,之后我们会要求他们使用他们的用户名/密码重新进行身份验证.

问题:

生成此类令牌以用于身份验证的最佳做法是什么?

例如,我们可以......

  • 散列(SHA-256等)随机字符串并将其存储在给定用户的数据库中以及过期日期.在后续请求中对令牌进行简单查找以确保其匹配.
  • 使用密钥加密用户ID和一些其他信息(时间戳等).在后续请求中解密令牌以确保它是由我们发布的.

这感觉它必须是一个解决的问题.

Erv*_*ter 29

基于这个问题的其他答案的反馈,额外的研究和离线讨论,这是我们最终做的...

很快就指出,当选中"记住我"复选框时,此处的交互模型与ASP.NET中的表单身份验证使用的模型基本完全相同.它不是发出HTTP请求的Web浏览器.我们的"票证"与表单身份验证设置的cookie等效.表单身份验证默认情况下使用"使用密钥加密某些数据"方法.

在我们的登录Web服务中,我们使用此代码创建票证:

string[] userData = new string[4];

// fill the userData array with the information we need for subsequent requests
userData[0] = ...; // data we need
userData[1] = ...; // other data, etc

// create a Forms Auth ticket with the username and the user data. 
FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
    1,
    username,
    DateTime.Now,
    DateTime.Now.AddMinutes(DefaultTimeout),
    true,
    string.Join(UserDataDelimiter, userData)
    );

// encrypt the ticket
string encryptedTicket = FormsAuthentication.Encrypt(formsTicket);
Run Code Online (Sandbox Code Playgroud)

然后,我们为WCF服务提供了一个操作行为属性,该属性添加了一个IParameterInspector,用于检查请求的HTTP头中的有效票证.开发人员将此操作行为属性放在需要身份验证的操作上.以下是该代码解析故障单的方式:

// get the Forms Auth ticket object back from the encrypted Ticket
FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket);

// split the user data back apart
string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None);

// verify that the username in the ticket matches the username that was sent with the request
if (formsTicket.Name == expectedUsername)
{
    // ticket is valid
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 我们对这种方法仍然很满意.我们确实使用SSL,因此嗅探问题不是问题.从移动设备提取的票证要求移动设备受到攻击者的攻击和/或物理攻击.那时,攻击者已经"赢了"并且游戏结束了.无论技术细节如何,如果有"记住我的密码"功能,情况总是如此.在我们的情况下,由于票证只有8小时的好处,因此攻击者使用被盗票证的时间有限,这在一定程度上得到了缓解. (2认同)
  • @RickStrahl,当然我们的令牌只使用了TLS/HTTPS连接,因此不能被截取,除非攻击者已经损害了实际的移动设备(在这种情况下,所有的希望都失去了,因为他们可能只是记录按键来获取用户的密码). (2认同)

Eri*_*ert 13

构建自己的身份验证系统始终是"最糟糕的做法".这是专门从事认证系统的专业人士最好的事情.

如果您倾向于构建自己的"登录服务即将到期的票证"架构而不是重新使用现有架构,那么至少要熟悉驱动类似系统设计的问题(如Kerberos)可能是个好主意. .这里有一个温和的介绍:

http://web.mit.edu/kerberos/dialogue.html

考虑过去20年在Kerberos(和类似系统)中发现的安全漏洞并确保不复制它们也是一个好主意.Kerberos由安全专家构建并经过数十年的仔细审查,并且仍然存在严重的算法缺陷,如下所示:

http://web.mit.edu/kerberos/www/advisories/MITKRB5-SA-2003-004-krb4.txt

从他们的错误中学习比你自己的错误要好得多.

  • 如果在iPhone应用程序和REST WCF Web服务之间存在可用的预先存在的身份验证系统,请发布链接,我会很乐意使用它而不是发明我们自己的... Baring that,我当然会看一看在你提供的kerberos链接. (13认同)

Ale*_*lds 11

Amazon.com使用HMAC SHA-1消息令牌来验证和授权请求.他们将此用于相当大的商业服务,因此我可能会相信他们的工程决策.谷歌发布的OpenSocial API有点类似.基于Google和Amazon.com使用类似且公开发布的方法来保护Web请求,我怀疑这些可能是很好的方法.