pythonauthenticationip-addressxml-rpcsimplexmlrpcserver

Python SimpleXMLRPCServer: get user IP and simple authentication


I am trying to make a very simple XML RPC Server with Python that provides basic authentication + ability to obtain the connected user's IP. Let's take the example provided in http://docs.python.org/library/xmlrpclib.html :

import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer

def is_even(n):
    return n%2 == 0

server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(is_even, "is_even")
server.serve_forever()

So now, the first idea behind this is to make the user supply credentials and process them before allowing him to use the functions. I need very simple authentication, for example just a code. Right now what I'm doing is to force the user to supply this code in the function call and test it with an if-statement.

The second one is to be able to get the user IP when he calls a function or either store it after he connects to the server.

Moreover, I already have an Apache Server running and it might be simpler to integrate this into it.

What do you think?


Solution

  • This is a related question that I found helpful:

    IP address of client in Python SimpleXMLRPCServer?

    What worked for me was to grab the client_address in an overridden finish_request method of the server, stash it in the server itself, and then access this in an overridden server _dispatch routine. You might be able to access the server itself from within the method, too, but I was just trying to add the IP address as an automatic first argument to all my method calls. The reason I used a dict was because I'm also going to add a session token and perhaps other metadata as well.

    from xmlrpc.server import DocXMLRPCServer
    from socketserver import BaseServer
    
    class NewXMLRPCServer( DocXMLRPCServer):
    
        def finish_request( self, request, client_address):
            self.client_address = client_address
            BaseServer.finish_request( self, request, client_address)
    
        def _dispatch( self, method, params):
            metadata = { 'client_address' : self.client_address[ 0] }
            newParams = ( metadata, ) + params
            return DocXMLRPCServer._dispatch( self, method, metadata)
    

    Note this will BREAK introspection functions like system.listMethods() because that isn't expecting the extra argument. One idea would be to check the method name for "system." and just pass the regular params in that case.