【问题标题】:How to limit Autobahn python subscriptions on a per session basis如何在每个会话的基础上限制 Autobahn python 订阅
【发布时间】:2014-11-04 17:10:28
【问题描述】:

我在服务器端使用带有扭曲(wamp)的 autobahnpython,在浏览器中使用 autobahnjs。是否有一种直接的方式来允许/限制每个会话的订阅?例如,客户端不应该能够订阅与其他用户相关的主题。

虽然我没有使用 crossbar.io,但我尝试使用本页末尾的“示例”部分中显示的 Python 代码http://crossbar.io/docs/Authorization/,其中首先使用 RPC 调用向客户端授予授权。当然,我使用的是我自己的授权逻辑。一旦此授权成功,我想授予客户端订阅仅与此客户端相关的主题的权限,例如“com.example.user_id”。我的问题是,即使身份验证通过,但是,我还没有找到一种方法来限制 ApplicationSession 类中的订阅请求,这是授权发生的地方。如何防止使用 user_id=user_a 授权的客户端订阅“com.example.user_b”?

【问题讨论】:

    标签: python websocket twisted autobahn


    【解决方案1】:

    您可以通过创建自己的路由器来进行授权。为此,继承 Router() 并覆盖(至少)authorize() 方法:

    def authorize(self, session, uri, action):
        return True
    

    这个方法非常简单,如果你返回一个 True 则会话被授权做它正在尝试的任何事情。您可以制定一个规则,所有订阅必须以“com.example.USER_ID”开头,因此,您的 python 代码将拆分 uri,获取第三个字段,并将其与当前会话 id 进行比较,如果它们匹配则返回 True,false否则。这就是事情变得有点奇怪的地方。我有做类似事情的代码,这是我的 authorize() 方法:

    @inlineCallbacks
    def authorize(self, session, uri, action):
        authid = session._authid
        if authid is None:
            authid = 1
        log.msg("AuthorizeRouter.authorize: {} {} {} {} {}".format(authid,
            session._session_id, uri, IRouter.ACTION_TO_STRING[action], action))
        if authid != 1:
            rv = yield self.check_permission(authid, uri, IRouter.ACTION_TO_STRING[action])
        else:
            rv = yield True
    
        log.msg("AuthorizeRouter.authorize: rv is {}".format(rv))
    
        if not uri.startswith(self.svar['topic_base']):
            self.sessiondb.activity(session._session_id, uri, IRouter.ACTION_TO_STRING[action], rv)
    
        returnValue(rv)
    
        return
    

    请注意,我潜入会话以获取 _authid,这是不好的业力(我认为),因为我不应该查看这些私有变量。不过,我不知道还能从哪里得到它。

    另外,值得注意的是,这与身份验证密切相关。在我的实现中,_authid 是经过身份验证的用户 id,类似于 unix 用户 id(正唯一整数)。我很确定这可以是任何东西,比如一个字符串,所以如果你愿意的话,你应该可以将你的 'user_b' 作为 _auth_id。

    -g

    【讨论】:

    • 不管怎样,@inlineCallbacks def foo(): return bar 实际上是一个语法错误。任何用@inlineCallbacks 修饰的函数必须在其主体的某处有一个yield 表达式。
    • FWIW,AutobahnPython(自 0.9.4 起)不再支持答案中概述的方法(创建自定义路由器)。应用程序开发人员不需要创建自定义路由器。前进的道路(使用 Crossbar.io 作为 WAMP 路由器时)确实在此处描述 crossbar.io/docs/Authorization - “动态/自定义授权”。
    【解决方案2】:

    我找到了一个使用 Node 来宾的相对简单的解决方案。代码如下:

        // crossbar setup
    var autobahn = require('autobahn');
    
    var connection = new autobahn.Connection({
            url: 'ws://127.0.0.1:8080/ws',
            realm: 'realm1'
        }
    );
    
    // Websocket to Scratch setup
    // pull in the required node packages and assign variables for the entities
    var WebSocketServer = require('websocket').server;
    var http = require('http');
    
    var ipPort = 1234; // ip port number for Scratch to use
    
    // this connection is a crossbar connection
    connection.onopen = function (session) {
    
        // create an http server that will be used to contain a WebSocket server
        var server = http.createServer(function (request, response) {
            // We are not processing any HTTP, so this is an empty function. 'server' is a wrapper for the
            // WebSocketServer we are going to create below.
        });
    
        // Create an IP listener using the http server
        server.listen(ipPort, function () {
            console.log('Webserver created and listening on port ' + ipPort);
        });
    
        // create the WebSocket Server and associate it with the httpServer
        var wsServer = new WebSocketServer({
            httpServer: server
        });
    
        // WebSocket server has been activated and a 'request' message has been received from client websocket
        wsServer.on('request', function (request) {
            // accept a connection request from Xi4S
            //myconnection is the WS connection to Scratch
            myconnection = request.accept(null, request.origin); // The server is now 'online'
    
            // Process Xi4S messages
            myconnection.on('message', function (message) {
    
                console.log('message received: ' + message.utf8Data);
                session.publish('com.serial.data', [message.utf8Data]);
    
                // Process each message type received
                myconnection.on('close', function (myconnection) {
                    console.log('Client closed connection');
                    boardReset();
                });
            });
        });
    };
    
    connection.open();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 2020-12-06
      • 2016-11-07
      • 2011-05-10
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      相关资源
      最近更新 更多