gpt4 book ai didi

node.js - 我应该如何在 Node.js 和 Redis 中实现基于 token 的授权 API?

转载 作者:太空宇宙 更新时间:2023-11-03 22:16:31 25 4
gpt4 key购买 nike

我正在一个处理来自 Mongo 数据库的资源的网络应用程序中工作,对于这些资源,我想提供一个 API,以便 future 的移动应用程序可以捕获它或从原始客户端使用它。

但是我想让 Web 应用程序使用相同的 API,在这里我对如何正确实现它感到有点困惑。

这是我到目前为止所做的:

API 认证:

app.route('/api/auth/')
.post(function (request,response) {

var email = request.body.email;
var password = request.body.password;
var login = new Account({"local.email":email,"local.password":password});

Account.findOne({"local.email":email}, function (err,user) {
if (err) {
response.send(500);
}

if (!user) {
response.send(404);
}

else {

user.validPassword(password, function (err,matched) {
if (err) {
response.send(500);
}

if (matched) {
var uuidToken = uuid.v4();
redisClient.set(uuidToken,user._id,redis.print);
redisClient.expire(user._id,100);
response.send(uuid);
}

else {
response.send(403);
}
});
}
});
});

所以基本上我收到消费者的用户名和密码,我对数据库进行身份验证,如果匹配,我回复一个 token ,(实际上是一个 UUID )。该 token 与数据库中的用户 ID 配对存储在 Redis 中。 future 对任何 API 路由的每个请求都将验证此类 token 是否存在。

在这里我想知道:
  • 我应该如何管理 token TTL,并根据 future 的请求续订?
  • 如何控制每个时间窗口的请求限制?
  • 我正在采取的方法中是否有任何安全警告?

  • 网站授权:

    基本上我对数据库执行相同的用户名密码身份验证,然后我:

    1. 启动一个新的服务器 session 。

    2. 自然地,提供一个带有 session ID 的 cookie。

    3. 然后我创建 Redis UUID 和用户 ID 记录,API 将检查哪个记录。我想这没关系,因为请求 POST /api/auth 有任何意义再次认证。

    在这里我想知道:
  • 这是最好的方法吗?
  • 我是否应该包含任何 token 盐来区分纯 API 消费请求和来自 Web 应用程序的请求?
  • 我正在采取的方法中是否有任何安全警告?
  • 我应该包含更多 token 吗?

  • 这是 POST /login 的示例:
    app.route('/login')

    .post(function (request,response,next) {

    var email = request.body.email;
    var password = request.body.password;

    var login = new Account({"local.email":email,"local.password":password});

    Account.findOne({"local.email":email}, function (err,user) {

    if (err) {
    response.redirect('/error');
    }

    if (!user) {

    var cookie = request.cookies.userAttempts;

    if (cookie === undefined) {

    response.cookie('userAttempts',1);
    }

    else {

    response.cookie('userAttempts',(++cookie));
    }

    response.redirect('/');
    }

    else {

    user.validPassword(password, function (err,matched) {

    if (err) {

    // Redirect error site or show err message.
    response.redirect('/error');
    }

    if (matched) {

    var session = request.session;
    session.userid = user._id;
    var uuidToken = uuid.v4();
    redisClient.set(uuidToken,user._id,redis.print);
    redisClient.expire(uuidToken,900);
    response.cookie('email',email);
    response.redirect('/start');
    }

    else {

    var cookie = request.cookies.passwordAttemps;

    if (cookie === undefined)

    response.cookie('passwordAttemps',1);

    else {
    var attemps = ++request.cookies.attemps
    response.cookie('passwordAttemps', attemps)
    }

    response.redirect('/');
    }

    });
    }


    });
    })

    我想我可以摆脱使用和编写典型的 session 实现,并以某种方式依赖于 API 具有的类似基于 token 的身份验证。

    最佳答案

    您所拥有的一切都在正确的轨道上,并且基本上取代了 cookie 的一些功能。不过,有一些事情需要考虑,并且您已经触及了其中的一些。

  • 虽然使用 UUID(我猜是 v4?)是好的,因为它是不确定的和“随机的”,但 token 本身是毫无值(value)的。如果 redis 丢失数据,则 token 不再具有任何上下文。如果没有 redis 的帮助,你也不能强制过期。将此与 JWT 进行比较它可以自己携带上下文,任何人都可以使用正确的 key 解密,可以处理过期,并且可以强制执行进一步的常见应用程序级别约束(发行者、受众等)。
  • 速率限制。 There are a number of ways to handle this除了您可能会使用 token 作为在速率限制器中跨请求识别用户的 key 这一事实之外,它们中很少有直接与您选择的 token 方案相关联。
  • 在 Web 应用程序和其他客户端(移动应用程序、桌面应用程序等)中透明地传递 token 可能是一个巨大的痛苦。为了访问私有(private)资源,用户需要在请求中的某处传递 token ,可能是 header ,对于 Web 应用程序,这意味着您需要手动干预以将 token 包含在每个请求中。这意味着对所有经过身份验证的请求进行手动编码的 ajax 请求。虽然这可能很烦人,但至少可以这样做,而且如果您正在编写单页应用程序,那么您很可能还是会这样做。任何移动或桌面客户端都可以这样说。既然您已经必须直接在代码中发出 HTTP 请求,那么这有什么关系呢?现在想象一个返回 html 页面的 HTTP GET 端点只能通过适当的身份验证访问的场景。对于网络应用程序,用户很可能会通过浏览器重定向或直接在 URL 栏中输入来访问它。 How is the token added to the request?除了使用 cookie(由于移动和桌面客户端未实现它们而明确不使用它们)之外,这实际上是不可能的。但是,如果您的 API 客户端始终可以修改 HTTP 请求结构,这并不是真正的问题。

  • 现在来个无耻的插件, our team has a library we use for this .它主要在内部使用,因此对其依赖项(express,redis)非常固执己见,但希望它可以在这里对您有所帮助。事实上,这个库几乎只是一个 JWT 包装器,围绕着你已有的东西。如果您决定使用它并发现任何问题或缺陷,请随时在 github 上提交任何问题。否则,npm 上还有一大堆其他基于 JWT 的 session 管理模块看起来很有希望。我会检查这些,因为那里很可能有比我们更好的模块。同样,我们在内部使用并且来自一组非常特定的用例,因此它捕获您所有的机会非常渺茫。另一方面,听起来您正在使用类似的堆栈,所以鞋子可能适合。

    如果您确实使用我们的,那么该模块上的 API 表面存在一个拆分可能看起来很奇怪,因为您可以选择将数据直接存储在 JWT 声明中或 redis 中。这是经过深思熟虑的,我认为您的示例说明了双方的良好用例。通常我们所做的是将用户的电子邮件和姓名存储在 JWT 声明中,然后将更多动态 session 数据存储在他们 session 的 redis 中。例如,在登录时,您需要将颁发者、受众和用户的电子邮件添加到 JWT 声明中,但保留与“userAttempts”相关的任何内容。然后,在尝试失败时,您将在与该 JWT 相关的 redis 中存储的 session 数据上添加或修改“userAttempts”。一旦设置了 JWT,就无法在不生成新内容的情况下修改其内容,因此请注意,如果您决定在 JWT 中保留相对动态的数据,您将在服务器和客户端之间不断交换新旧 JWT .

    关于node.js - 我应该如何在 Node.js 和 Redis 中实现基于 token 的授权 API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26894597/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com