我不是安全专家,所以我正在寻找人们在我设计的身份验证方案中戳出巨大的漏洞,或者为我指出一个更好的现有方案来实现相同的目标:
问题概述
我有一个接口,客户端在其中维护会话生命周期(它是 Web 服务器上的 HTTP 会话,但这并不重要)。
无状态服务器提供了一些需要对调用者进行身份验证的服务(服务器具有执行此身份验证的能力)。
但是,希望服务器不必在每次调用时都对调用者进行身份验证,例如,通过在每次调用中传递凭据。(身份验证过程可能很昂贵。)
最好不要在服务器上维护会话状态。一方面,它只是要求一个脆弱的解决方案在客户端和服务器上都有独立的会话超时(客户端上的超时无法摆脱),并且服务器超时似乎是必要的,以便拥有可靠的会话生命周期在服务器上(而不是依赖客户端在适当的时间显式结束会话)。另一方面,服务器没有设置为存储这种状态。
服务器有一个明确的authenticate
方法。那么问题来了:服务器如何验证,当调用另一个方法时,调用者之前已经使用该authenticate
方法进行了身份验证,而不在服务器上存储任何会话状态?
建议的解决方案
这是我想出的一个方案:
该authenticate
方法接受凭据作为输入参数。成功认证后,服务器返回两件事:
- 指示执行身份验证时间的时间戳。
- { username, timestamp } 元组的加密版本,用私钥加密
在进一步的方法调用中,客户端将这两个值都传递回服务器。然后服务器解密加密的 { username, timestamp } 元组。如果解密的时间戳与客户端发送的未加密值匹配,则服务器知道客户端之前已经过身份验证(因为这是获取有效加密值的唯一方法)。解密后的用户名告诉服务器哪个用户已通过身份验证。
可以通过仅允许当前时间x小时内的时间戳来强制加密密钥的有效期。这与会话超时不同,但它限制了恶意方可以使用受损时间戳的窗口。
所以
我担心这个计划在十几个方面都是幼稚的。你看到了什么弱点或糟糕的逻辑?