简体   繁体   中英

Autobahn|Python Twisted server that checks API key and disconnects clients

I want to add a simple API key check to an Autobahn Python WebSocket server. The server should check the key in the HTTP header of a client and disconnect clients that don't have the correct key.

I have figured out a solution to this, but I'm not sure it is the best solution (see below). If anyone has suggestions, I'd appreciate it.

From the API Docs for the onConnect method:

Throw autobahn.websocket.types.ConnectionDeny when you don't want to accept the WebSocket connection request.

You can see this done on line 117 of one of the examples here .

I have tested this and it does not close the connection cleanly. However you are terminating a connection with an unauthenticated client so you should not want to go through a closing handshake.

The onClose callback takes a wasClean argument which allows you to differentiate between clean and unclean connection closures.

My solution is to check the HTTP header after the client has connected to the server and to close the connection if the client does not have a valid API key.

MY_API_KEY = u'12345'

class MyServerProtocol(WebSocketServerProtocol):

    def onConnect(self, request):
        print("Client connecting: {}".format(request.peer))

    def onOpen(self):
        # Check API Key
        if 'my-api-key' not in self.http_headers or\
            self.http_headers['my-api-key'] != MY_API_KEY:
            # Disconnect the client
            print('Missing/Invalid Key')
            self.sendClose( 4000, u'Missing/Invalid Key')

        # Register client
        self.factory.register(self)

I found that if I close the connection inside onConnect, I get an error saying that I cannot close a connection that has not yet connected. The above solution closes cleanly on the client side, but behaves oddly on the server side. The log output is

dropping connection: None
Connection to/from tcp4:127.0.0.1:51967 was aborted locally
_connectionLost: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionAborted'>: Connection was aborted locally, using.
    ]
WebSocket connection closed: None

Is the reason the close message is None on the server side that the server closed the connection and the client did not send back a reason? Is there a better way to do this?

Update: I have accepted Henry Heath's answer because it seems to be the officially supported solution, even though it does not close the connection cleanly. Using autobahn.websocket.types.ConnectionDeny , the solution becomes

from autobahn.websocket.types import ConnectionDeny
MY_API_KEY = u'12345'

class MyServerProtocol(WebSocketServerProtocol):

    def onConnect(self, request):
        print("Client connecting: {}".format(request.peer))
        # Check API Key
        if 'my-api-key' not in request.headers or\
            request.headers['my-api-key'] != MY_API_KEY:
            # Disconnect the client
            print('Missing/Invalid Key')
            raise ConnectionDeny( 4000, u'Missing/Invalid Key')

    def onOpen(self):
        # Register client
        self.factory.register(self)

Note that within onConnect, HTTP headers are accessible with request.headers whereas within onOpen, they are accessible with self.http_headers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM