Rails Action Cable:如何授权传入连接?
Rails Action Cable: How to authorize incoming connection?
我正在尝试在 websocket 连接上实现授权 (rails 5.2.1)
继 rubyonrails guideline 之后,我创建了 connection.rb 如下:
#app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = User.find_by(id: cookies.encrypted[:user_id])
verified_user
else
reject_unauthorized_connection
end
end
end
end
很遗憾,所有的websocket连接请求都被拒绝了。 (我发现 cookies.encrypted[:user_id] 返回 nil。)
Started GET "/cable" for ::1 at 2018-10-07 21:33:46 +0300
Started GET "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."is_active" = AND "users"."id" IS NULL LIMIT [["is_active", true], ["LIMIT", 1]]
↳ app/channels/application_cable/connection.rb:12
An unauthorized connection attempt was rejected
Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
Finished "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
能否指导我如何访问 app/channels/application_cable/connection.rb 中的当前用户信息?
为了从 Devise 获得 current_user
,您需要按如下方式更改 connection.rb
:
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.email
end
protected
def find_verified_user # this checks whether a user is authenticated with devise
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
我遇到了确切的问题。我解决它的方法是在用户通过 SessionsController < Devise::SessionsController
登录时添加一个 cookie。
代码如下所示:
class Users::SessionsController < Devise::SessionsController
# POST /resource/sign_in
def create
super
cookies[:user_id] = current_user.id
end
end
您可以通过 运行 代码从设计中获取 SessionsController
:
rails generate devise:controllers [scope]
在我的例子中,范围是用户。
Rails 6:
cookies.encrypted[:user_id]
Rails 5:
cookies.signed[:user_id]
我正在尝试在 websocket 连接上实现授权 (rails 5.2.1)
继 rubyonrails guideline 之后,我创建了 connection.rb 如下:
#app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = User.find_by(id: cookies.encrypted[:user_id])
verified_user
else
reject_unauthorized_connection
end
end
end
end
很遗憾,所有的websocket连接请求都被拒绝了。 (我发现 cookies.encrypted[:user_id] 返回 nil。)
Started GET "/cable" for ::1 at 2018-10-07 21:33:46 +0300
Started GET "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."is_active" = AND "users"."id" IS NULL LIMIT [["is_active", true], ["LIMIT", 1]]
↳ app/channels/application_cable/connection.rb:12
An unauthorized connection attempt was rejected
Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
Finished "/cable/" [WebSocket] for ::1 at 2018-10-07 21:33:46 +0300
能否指导我如何访问 app/channels/application_cable/connection.rb 中的当前用户信息?
为了从 Devise 获得 current_user
,您需要按如下方式更改 connection.rb
:
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.email
end
protected
def find_verified_user # this checks whether a user is authenticated with devise
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
我遇到了确切的问题。我解决它的方法是在用户通过 SessionsController < Devise::SessionsController
登录时添加一个 cookie。
代码如下所示:
class Users::SessionsController < Devise::SessionsController
# POST /resource/sign_in
def create
super
cookies[:user_id] = current_user.id
end
end
您可以通过 运行 代码从设计中获取 SessionsController
:
rails generate devise:controllers [scope]
在我的例子中,范围是用户。
Rails 6:
cookies.encrypted[:user_id]
Rails 5:
cookies.signed[:user_id]