用于设置Cookie的存储钩子
# config/initializers/warden_hooks.rb
Warden::Manager.after_set_user do |user,auth,opts|
scope = opts[:scope]
auth.cookies.signed["#{scope}.id"] = user.id
auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
end
Warden::Manager.before_logout do |user, auth, opts|
scope = opts[:scope]
auth.cookies.signed["#{scope}.id"] = nil
auth.cookies.signed["#{scope}.expires_at"] = nil
end
用于认证的连接父类。这样可以正常工作并记录连接。
# application_cable/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
USER_CLASSES = ['admin', 'agent', 'tech', 'client']
def find_verified_user
user_class = USER_CLASSES.find { |klass| cookies.signed["#{klass}.id"] }
user_id = cookies.signed["#{user_class}.id"]
verified_user = User.find_by(id: user_id)
if verified_user && cookies.signed["#{user_class}.expires_at"] > Time.now
verified_user
else
reject_unauthorized_connection
end
end
end
end
用于建立连接和发送消息的客户端代码。
// channels/conversations.js
$(document).on('turbolinks:load', function() {
var messages = $('#messages');
var projectId = messages.data('project-id');
var button = $('#new_message input[type=submit]');
var subscription = { channel: "ConversationsChannel", id: projectId };
App.conversation = App.cable.subscriptions.create(subscription, {
connected: function() {
console.log('Upgraded to websocket connection.');
},
disconnected: function() {
console.log('Websocket not connected.');
},
received: function(data) {
messages.append(data['message']);
},
sendMessage: function(message, project_id) {
return this.perform('send_message', {
message: message,
project_id: projectId
});
}
});
$('#message_body').on('keyup', function(e) {
var message = e.target.value;
if ($.trim(message).length > 0) {
button.prop('disabled', false);
} else {
button.prop('disabled', true);
}
});
$('#new_message').submit(function(e) {
e.preventDefault();
var textarea = $('#message_body');
App.conversation.sendMessage(textarea.val(), projectId);
textarea.val('');
button.prop('disabled', true);
});
});
连接已在服务器上注册
,但是客户端上ActionCable.Connection
的状态永远不会设置为打开,这会导致Connection.send
方法失败,因为this.isOpen()
返回false(因此,客户端永远不会订阅频道)-ActionCable source
如果我在send
内的chrome中放置一个断点,并将数据传递给webSocket.send
方法,则订阅成功。
如果要发送消息,我必须重复一遍,因为即使成功建立订阅后,连接状态仍未设置为打开。
current_user
中的Connection#connect