服务资源时的外部请求数

Ben*_*aum 10 session server-side

所以,我有一个Web应用程序,它向服务器发出大量数据请求.项目要求是具有非常快的服务器响应时间.服务器托管在基于云的平台上.

该应用程序使用会话来记录用户身份验证后的用户身份验证.由于它托管在云提供商上,我使用缓存来备份会话存储(在我的情况下,它是Auzre缓存,但如果您不熟悉认为Redis)

目前的流程如下:

  • 用户访问资源
  • 尝试通过缓存基于会话ID获取会话.这是一个缓存请求.
  • 用户通过会话状态进行身份验证(如果已登录).
  • 通常通过缓存发送数据请求.
  • 数据将返回给用户.

这种方法的问题在于它会两次触发缓存.完全删除会话导致显着的速度提升(约50%).

我正在考虑一次点击缓存,询问用户需要的密钥和SessionID来保存额外的往返行程.但是,我之前从未见过这种方法,它需要"滚动我自己的会话",因为我必须生成会话ID等.我觉得可能有一种更简单,更简单的方法.

那么,为用户提供资源并对其进行身份验证的最有效方法是什么?


注意:我正在使用带有C#的ASP.NET MVC/WebAPI,但我发现这个问题与这个问题没有关系,因此我将语言和平台排除在外.

kev*_*vin 2

您可能希望将身份验证和资源请求步骤合并到一个请求中。这不仅比您的实施更快,而且更安全。考虑以下场景:

  1. 用户向服务器进行身份验证。结果就是成功。
  2. 身份验证已更改。(例如用户更改密码、管理员决定锁定用户帐户等)
  3. 用户使用步骤 1 中的 sessionID 发出请求。

为了确保用户没有被授予访问资源的权限,您需要在步骤 3 中精确验证用户的身份。但这没有意义,您之前已经在步骤 1 中验证了该用户的身份...

HTTP 的核心就是为此而设计的。有多种方法可以随请求一起传递身份验证信息,例如:

  1. 在内容中写入身份验证信息(愚蠢,但有效)
  2. 在 url 中包含身份验证,例如 example.com/pic/123?sessionID=abc (更好,但会使您的 url 又丑又长)
  3. 将会话信息存储在cookie中(更好,但是如果客户端不支持cookie怎么办?cookie过期怎么办?)
  4. 验证 HTTP 标头(我个人的最佳建议)

HTTP 本身有一个身份验证标头,旨在与“基本身份验证”兼容(它定义良好,如果您感兴趣,请查找它)。但您可以实现自己的自定义标头。

任何缓存查找都必然会很慢(与计算相比),因此您应该完全忽略身份验证部分的缓存。你的服务器应该是无状态的;即不跟踪登录会话。如何知道sessionID是否有效?在上面贴上时间戳。为了避免其他人伪造 sessionID,请对其进行签名。

因此,您的 HTTP 请求将如下所示(伪代码):

var request = new HttpRequest();
request.url = "example.com/pic/123";
request.Headers["CustomAuth"] = "id=abc&t=123456789&s=01de45890a";
Run Code Online (Sandbox Code Playgroud)

实现您自己的签名方法,有点像哈希函数(您可以使用 HMAC),并将密钥安全地保存在服务器上。如果签名匹配,您就知道您之前在登录时已经对此进行了签名,并且它必须来自您的服务器。时间戳可以帮助您检测会话过期并防止重放攻击。

现在在您的服务器中,执行如下操作:

public void Get(){
    var authHeader = Request.Headers["CustomAuth"];
    if(!validate(authHeader)){
        Response.StatusCode = 404;
        Response.End();
    }else{
        //something else
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您需要在一个请求中执行登录+会话身份验证+资源请求,那么只有两种身份验证方式。用户可以提供用户名/密码组合或会话密钥。想想这个场景,它来自我开发的一个 API:

  1. 用户使用用户名/密码组合注册
  2. 服务器响应注册成功/失败(例如用户名已被占用)
  3. 如果成功,用户现在使用用户名/密码组合登录
  4. 服务器返回会话令牌

如果我们这样做不是更简单(也更快)吗:

  1. 用户使用用户名/密码组合注册
  2. 如果成功,则回复“reg success”和“sessionToken=xxxxxx”。如果失败,则回复“reg failure”。

我希望这能给你一些想法。