【问题标题】:SailsJS in production mode, API routes give forbidden errorSailsJS 在生产模式下,API 路由给出禁止错误
【发布时间】:2019-06-24 07:02:08
【问题描述】:

一段时间以来一直在从事 Sails Web 应用程序的工作。

到目前为止,通过努力阅读、反复试验克服了所有问题。

最近不得不在客户端的 ec2 免费试用实例上安装该应用以进行封闭 Beta 测试,它在开发模式下运行良好。

该应用位于 nginx 代理后面,该代理侦听 80 端口并重定向到 http://server_IP:1337

CORS 和 CSRF 已启用,allowOrigins 和 onlyAllowOrigins 设置为 production.js 和 security.js 和 sockets.js 中的服务器 IP、Web 域和 localhost。

但是当切换到生产模式时,除了 GET 之外的所有 API 请求,都会给出 403 禁止。

尝试了我在 Google 上可以找到的所有内容,它根本不适用于生产,但它完全适用于开发。

如果有人能分享一点这方面的信息,将不胜感激。

编辑:

使用 debug silly 运行应用程序,显示如下:

允许连接套接字,但无法加载会话。创建一个空的一次性会话以用于此套接字连接的生命周期。 此日志经常显示,因为来自先前电梯的客户端套接字或另一个 Sails 应用程序正在尝试重新连接(例如,从打开的浏览器选项卡),但其 cookie 指示的会话不再存在 - 因为此应用程序当前未使用像 Redis 这样的持久会话存储,或者会话条目已从会话存储中删除(例如,通过计划的作业或因为它自然过期)。 细节: 错误:无法加载会话。 在 Immediate._onImmediate (/var/www/allscubashops.com/node_modules/sails/lib/hooks/session/index.js:543:42) 在 processImmediate (internal/timers.js:445:19)

然后我删除了旧的浏览器cookie并得到了这个:

无法获取会话,因为连接套接字的握手中没有 cookie。 生成了一次性 cookie: sails.sid=s%3APlHbdXvOZRo5yNlKPdFKkaPgVTNaNN8i.DwZzwHPhb1%2Fs9Am49lRxRTFjRqUzGO8UN90uC7rlLHs 并将其保存在套接字握手中。

这意味着套接字以空会话开始,即 (req.session === {}) 该“匿名”会话只会持续到套接字断开连接。要解决此问题, 确保套接字在最初连接时发送cookie 标头或查询参数。 (这通常是由于使用了非浏览器客户端,例如原生 iOS/Android 应用程序, React Native、Node.js 脚本或其他一些连接的设备。它也可能出现在 尝试在浏览器中连接跨域套接字,特别是对于 Safari 用户。 要解决此问题,请手动提供 cookie,或忽略此消息并使用 会话以外的方法 - 例如身份验证令牌。)

也没有设置新的 cookie。

显而易见的结论是,在生产模式下,设置会话有问题。

编辑 2:

最新发现是,如果我在没有 nginx 代理的情况下运行应用程序,我没有禁止 API 请求问题,但我仍然有与未创建会话相关的问题。

我确定 nginx 代理设置没问题,但现在我正在考虑实现 redis 方式来存储会话而不是默认内存,看看会发生什么

编辑 3:

我已经实现了适用于开发和生产模式的 Redis 会话。

同样的情况,没有 nginx 代理的 ec2 实例在生产模式下工作,而具有 nginx 代理的 ec2 实例上的相同文件(git 复制)在生产模式下不起作用(API 请求 403 被禁止)但在开发中工作得很好模式。

X-CSRF 令牌已发送,screenshot 我在生产中收到的sails错误消息(除了GET之外的所有请求的网络403禁止错误)是:

允许连接套接字,但无法加载会话。创建一个空的一次性会话以用于此套接字连接的生命周期。 此日志经常显示,因为来自先前电梯的客户端套接字或另一个 Sails 应用程序正在尝试重新连接(例如,从打开的浏览器选项卡),但其 cookie 指示的会话不再存在 - 因为此应用程序当前未使用像 Redis 这样的持久会话存储,或者会话条目已从会话存储中删除(例如,通过计划的作业或因为它自然过期)。 细节: 错误:无法加载会话。 在 /var/www/example.com/node_modules/sails/lib/hooks/session/index.js:543:42 在 Command.callback (/var/www/example.com/node_modules/@sailshq/connect-redis/lib/connect-redis.js:148:25) 在 normal_reply (/var/www/example.com/node_modules/machinepack-redis/node_modules/redis/index.js:714:21) 在 RedisClient.return_reply (/var/www/example.com/node_modules/machinepack-redis/node_modules/redis/index.js:816:9) 在 JavascriptRedisParser.returnReply (/var/www/example.com/node_modules/machinepack-redis/node_modules/redis/index.js:188:18) 在 JavascriptRedisParser.execute (/var/www/example.com/node_modules/redis-parser/lib/parser.js:574:12) 在套接字。 (/var/www/example.com/node_modules/machinepack-redis/node_modules/redis/index.js:267:27) 在 Socket.emit (events.js:193:13) 在 addChunk (_stream_readable.js:296:12) 在 readableAddChunk (_stream_readable.js:277:11) 在 Socket.Readable.push (_stream_readable.js:232:10) 在 TCP.onStreamRead (internal/stream_base_commons.js:150:17)

因此我假设套接字已连接但未创建会话。

Redis 工作正常,我在开发时看到了其中的会话。

【问题讨论】:

  • 编辑:nginx 还使用 Let's Encrypt 证书监听 SSL,并且 webapp 在 HTTPS 上运行 OK,除了我无法使用 GET 访问我的 API 路由,

标签: sails.js


【解决方案1】:

您是否公开了 csrf 端点并且在发出进一步请求之前是否首先调用该端点以获取令牌?这给了我一次小费。

【讨论】:

  • 嘿 wouter,感谢您的帮助!这个应用程序是使用网络开关构建的;如文档中所述,令牌工作流程由sails以这种方式管理。令我困惑的是为什么它在 dev 中有效但在 prod 中无效,在 dev 中访问相同的路由没有任何问题,只是在 prod 中它们不起作用(GET 除外)。还是我在这里遗漏了什么?
  • 当您说 web swich 时,您是在谈论设置项目时的 web 应用程序选项吗?请记住,生产模式使您的应用程序以非常严格的方式运行,所以不要假设因为某些东西在 dev 中有效,它在 prod 中也有效。
  • 是的,我指的是网络应用选项。我已经阅读了链接的帖子,将尝试使用 allowCredentials true 或添加隐藏的输入并在此处报告是否有效。谢谢wouter!
  • 尝试添加隐藏输入,但没有奏效,我也没有预料到,因为 Cloud SDK 无论如何都会发送令牌,而我没有明确发送它。设置 allowCredentials=true 也不起作用。即使将 CSRF 设置为 false 通常或为每条路由都不起作用;我的意思是它不会停止到禁止的错误,它显然访问 API 但返回 304 错误,它实际上什么都不做,没有调用动作,这是我需要调查的事情。所以,目前我必须在开发模式下运行应用程序,这是它工作的唯一方式。非常令人沮丧。
猜你喜欢
  • 2023-02-16
  • 2013-12-28
  • 2010-09-13
  • 2019-08-08
  • 1970-01-01
  • 2012-05-03
  • 2021-09-04
  • 1970-01-01
  • 2013-09-04
相关资源
最近更新 更多