首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >websocket-rails gem和身份验证

websocket-rails gem和身份验证
EN

Stack Overflow用户
提问于 2013-02-24 14:25:57
回答 1查看 3.3K关注 0票数 1

在websocket-rails的wiki上,有以下使用CanCan gem的示例。

这是如何工作的呢?对于普通的http请求,发送的cookie具有标识用户的令牌,但是对于websockets,发送的是原始数据,没有发送cookie,那么服务器如何识别CanCan gem中的用户呢?

代码语言:javascript
复制
class AuthorizationController < WebsocketRails::BaseController
  def authorize_channels
    # The channel name will be passed inside the message Hash
    channel = Channel.find_by_name message[:channel]
    if can? :subscribe, channel
      accept_channel current_user
    else
      deny_channel {:message => 'authorization failed!'}
    end
  end
end

编辑:

在下面的示例中,当创建dispatcher时,应该发送一个包含Upgrade: websocket以及cookie的http请求。但是在下一行中,subscribe_private不会创建websocket连接,因此它不是http请求,因此可能无法自动访问cookie。

代码语言:javascript
复制
// connect to server like normal
var dispatcher = new WebSocketRails('localhost:3000/websocket');

// subscribe to the channel
var private_channel = dispatcher.subscribe_private('channel_name');
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-01 16:06:28

它不完全是原始数据,它是http协议的升级,它是一个保持连接打开的套接字,如果你查看wikipedia上的文档,在创建连接时关于握手请求,有一个从客户端发送的信息流,以及一个来自服务器的应答。

因此,websocket连接请求的示例如下

代码语言:javascript
复制
GET /mychat HTTP/1.1
Host: server.example.com 
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

其作为字节流通过套接字发送,但是相同的事情发生在普通的http请求中,然而,

如果您检查使用rails-websocket创建的请求,当您在js上运行时,代码

代码语言:javascript
复制
var dispatcher = new WebSocketRails('localhost:3000/websocket');

您将看到通过网络进行连接的请求是

代码语言:javascript
复制
GET /websocket HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,es-ar;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://localhost:3000
Sec-WebSocket-Key: dRpM9EesBFdk3SOH2QL/Tw==
Cookie: __utma=111872281.1938357651.1354053248.1355759500.1357797379.3; __utmz=111872281.1354053248.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); hblid=T1PaqE0vcRC9zDYrpFoBo5RD91766581; olfsk=olfsk5917359536568161; remember_admin_user_token=BAhbB1sGaQlJIiIkMmEkMTAkV0VhZzJaeXg3SzZFQWMzVUdPLktaTwY6BkVU--f84238cbbcb767e075117603de67f56a7150eb97; _stack_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFRkkiJTg0NGIwNzZmNWUyZjFiNTMwZDkwMWUyMGFiODMxOGE3BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMWxIS1FHUjg1b2pDbjFybFY4RW8yemtzRWtVQUdHY1BxTGxtdzBWOFdBN009BjsARkkiE3VzZXJfcmV0dXJuX3RvBjsARiIZL2hvbWUvcHJpdmF0ZV9hY3Rpb24%3D--e4823c74756cf70af0675323fb752b1f87064f09
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

因此,cookies正在发送,最重要的是,在您的AuthorizationController上:

代码语言:javascript
复制
class AuthorizationController < WebsocketRails::BaseController
  def authorize_channels
    # The channel name will be passed inside the message Hash
    channel = Channel.find_by_name message[:channel]
    if can?(:subscribe, channel)
      accept_channel current_user
    else
      deny_channel({:message => 'authorization failed!'})
    end
  end
end

如果您在authorize_channels方法上设置了断点,您将看到您拥有所有的cookies,就好像它是一个普通的http请求一样。

有关websocket工作内容和工作方式的更多信息,您可以阅读RFC,但这里重要的是,当创建连接时,在握手时,客户端发送cookies以及其他信息,例如它是否是某种http请求,服务器接收websocket请求,通过检查cookies对用户进行身份验证,然后它要么打开作为全双工通信套接字打开的连接,要么因为凭据无效而关闭连接。

我不确定我是否理解了你的问题。公共页面请求和web套接字之间的主要区别在于,web套接字是用户用于开始连接的http握手的套接字。

在您的代码中,这些行发送带有cookie的http请求,服务器接受该连接。

代码语言:javascript
复制
// connect to server like normal
var dispatcher = new WebSocketRails('localhost:3000/websocket');

因此,在这一点上,您拥有了一个全双工套接字(这意味着服务器或客户端都可以通过它发送数据而不会发生冲突)。任何任意数据。

然后在下一段代码中:

代码语言:javascript
复制
// subscribe to the channel
var private_channel = dispatcher.subscribe_private('channel_name');

客户端请求服务器(通过活动的连接,通过websocket)订阅私有通道。

现在,最重要的是要理解的是,如果你订阅了一个频道,你不会打开一个新的连接,你仍然会使用你现在要求订阅私有频道的同一个Websocket,这就是你在开始连接时发送cookie的那个websocket。

现在,如果您偶然可以在websocket-rails gem上设置断点,而不是在方法路由( dispatcher.rb )上设置断点,那么您将注意到,在幕后,websocket-rails使用faye websocket -ruby来处理websocket连接,并且在请求中,您可以访问在websocket握手时发送的cookie。

该路由将请求路由到websocket-rails控制器AuthorizationController,在大多数情况下,它的代码如下:

代码语言:javascript
复制
if can?(:subscribe, message[:channel])
  accept_channel current_user
else
  deny_channel({:message => 'authorization failed!'})
end

而且因为它可以访问与普通rails控制器相同的辅助方法,所以cancan?方法将调用current_user帮助器,并且此方法将具有对cookies的完全访问权限。

所以通道不是websocket RFC中描述的东西,websocket只是一个可以用来发送任何数据的套接字,在这种情况下,公共和私有通道只是gem websocket-rails的作者开发的一种通信行为,用于创建通信通道并向不同的客户端广播消息。

如果您深入研究websocket-rails问题,您会注意到甚至有创建单向安全通道的请求:https://github.com/DanKnox/websocket-rails/issues/52

所以这不像是有人可以发送subscribe_to_private通道流并访问通道,在他们可以发送订阅流之前,他们必须通过http请求创建websocket连接,然后,通过该websocket连接,他们必须发送字节流,请求ruby gem订阅该通道,当他们这样做时,在rails服务器上,您可以自动访问该websocket的cookies,这些cookies是在创建连接时发送的。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15049262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档