application 和 actioncable 不会共享 cookie

Posted

技术标签:

【中文标题】application 和 actioncable 不会共享 cookie【英文标题】:application and actioncable won't share cookie 【发布时间】:2016-03-30 22:33:42 【问题描述】:

我正在使用设计进行身份验证,但是当我实施您的方法时,我得到“未经授权的连接尝试被拒绝”

经过几个小时的搜索,我发现:

cookies.signed['user.id']

返回零。在下面的代码块中。

def find_verified_user
  if verified_user = User.find_by(id: cookies.signed['user.id'])
    verified_user
  else
    reject_unauthorized_connection
  end
end

我检查了,肯定有一个 cookie,但它不包含 Devise 设置的 cookie 数据。

要检查是否真的设置了“user.id”,我在视图中提出它。例外情况,这会返回用户 ID

Signed in as @#cookies.signed[:username].
- raise(cookies.signed['user.id'].inspect)
%br/
%br/
#messages
%br/
%br/
= form_for :message, url: messages_path, remote: true, id: 'messages-form' do |f|
 = f.label :body, 'Enter a message:'
 %br/
 = f.text_field :body
 %br/
 = f.submit 'Send message'

我的问题/问题:

好像 cookie 在 actioncable 服务器上不可用。 有没有办法将 Devise 设置的 cookie 共享给有线服务器?

https://github.com/stsc3000/actioncable-chat.git

【问题讨论】:

这是我用来创建 actioncable 的示例 可能想看看这个:rubytutorial.io/actioncable-devise-authentication @Kkulikovskis 感谢您的回复!但我已经试过了。我不确定为什么这对我不起作用。如前所述,似乎 cookie 在 actioncable 服务器上不可用。而它在应用程序的浏览器中可用。 【参考方案1】:

检查连接到 Action Cable 服务器的客户端 javascript 文件。有些教程把它放在 'app/assets/javascripts/application_cable.coffee' 和其他的 'app/assets/javascripts/channels/index.coffee' 但看起来像这样:

#= require cable

@App = 
App.cable = Cable.createConsumer("ws://cable.example.com:28080")

您需要 WebSocket 地址指向您的 Cable 服务器,并且该地址需要与您的应用程序的其余部分共享一个 cookie 命名空间。您很可能指向错误的地方,例如,如果您在本地处理此问题,则需要进行更改:

App.cable = Cable.createConsumer("ws://cable.example.com:28080")

App.cable = Cable.createConsumer("ws://localhost:28080")

当然假设您的 Cable 服务器在端口 28080 上运行(在 bin/cable 可执行文件中指定)。 还要确保清除浏览器缓存,以便更新的文件是浏览器正在使用的文件。

【讨论】:

【参考方案2】:

不确定您现在是否可以运行它,但我在 Rails 5.0.0.beta3 上遇到了同样的问题。我没有更改为以下行:

App.cable = Cable.createConsumer("ws://localhost:3000")

我保持原来的样子

 @App ||= 
 App.cable = ActionCable.createConsumer()

但我所做的更改与 Cookie 有关。 无论如何。我的 user_id 的 cookie 不会显示。所以我做了一个工作。我得到了 cookie 来保存用户名,然后我终于能够在 find_verified_user 函数调用中看到它。

用户登录后(Sessions#create),我调用了一个辅助函数:

sessions_helper.rb
 def set_cookie(user)
    the_username = user.username.to_s
    cookies.permanent.signed[:username] = the_username
  end

新的 find_verified_user

  def find_verified_user
    if current_user = User.find_by_username(cookies.signed[:username])
      current_user
    else
      reject_unauthorized_connection
    end
  end

这可能是也可能不是最好的解决方案,但经过数小时的困惑和挫折之后,这对我的情况有效。我希望这可以帮助某人

【讨论】:

您是否还想实现一种在退出时销毁 cookie 的方法? 是的,当您注销时只需销毁 cookie。【参考方案3】:

我发现的问题是:我有2个不同的用户登录。一个在127.0.0.1登录,另一个在localhost登录。 所以当我使用 127.0.0.1:3000 访问我的网站时,但我的电缆配置为在 localhost 上运行,如下所示:

  config.action_cable.url = "ws://localhost:3000/cable"

在 config/environments/development.rb 中

在 127.0.0.1 登录的用户向 "ws://localhost:3000/cable" 发出电缆请求(根据配置),但这样会发送为 localhost 保存的 cookie,即使我正在发出请求来自 127.0.0.1,这是不同的用户(或根本没有用户)。

所以底根其实就是上面Pwnrar所指的,有线地址配置和你访问网站的方式。

因此,要解决此问题,请始终使用为您的电缆配置的服务器地址访问您的网站,否则 cookie 会混入其中。

【讨论】:

【参考方案4】:

需要在config/initializers/session_store.rb中配置

# using cookie store
if Rails.env.production?
#  to share across subdomains
    Rails.application.config.session_store :cookie_store, 
                      key: '_app_name_session', domain: ".example.com"
else
# to share with any domain
    Rails.application.config.session_store :cookie_store, 
                      key: '_app_name_session', domain: :all, tld_length: 2
end

#for redis store
elsif Rails.env.production?
#  to share across subdomains
    Rails.application.config.session_store :redis_store, 
       servers: [
         host: YourRedisHost, port: YourRedisPort,
      ],
      key: '_app_name_session',
      expire_after: 1.day,
      domain: '.example.com'
    

else
# to share with any domain
    Rails.application.config.session_store :redis_store, 
       servers: [
         host: YourRedisHost, port: YourRedisPort,
      ],
      key: '_app_name_session',
      expire_after: 1.day,
      domain: :all, 
      tld_length: 2
    
end 

【讨论】:

以上是关于application 和 actioncable 不会共享 cookie的主要内容,如果未能解决你的问题,请参考以下文章

让AuthLogic使用ActionCable

helper_method 不适用于 ActionCable

Rails 4 和 ActionCable

如何在 minitest 中模拟和验证 ActionCable 传输?

如何在生产中使用 Nginx 和 Unicorn 配置 ActionCable?

如何使用 ActionCable 作为 API