如何为 RPyC 服务器实现用户名密码验证器
How to implement username password authenticator for RPyC server
我正在尝试通过用户名和密码保护我的 RpyC 服务器连接。文档确实显示了 example,但它太简短了。没有详细说明密码是如何从客户端传递的。有人知道怎么做吗?提前致谢。
回答我自己的问题:
我不得不在客户端覆盖 RPyC 的一些内部方法以实现所需的行为。我不知道是否存在更清洁的解决方案,但这似乎是一个合理的解决方案。
服务器:
import rpyc
from rpyc.utils.authenticators import AuthenticationError
def magic_word_authenticator(sock):
if sock.recv(5).decode() != "Ma6ik":
raise AuthenticationError("wrong magic word")
return sock, None
class SecuredService(rpyc.Service):
def exposed_secured_op(self):
return 'Secret String'
rpyc.ThreadedServer(
service=SecuredService, hostname='localhost',
port=18812, authenticator=magic_word_authenticator
).start()
客户:
import rpyc
import traceback
class AuthSocketStream(rpyc.SocketStream):
@classmethod
def connect(cls, *args, authorizer=None, **kwargs):
stream_obj = super().connect(*args, **kwargs)
if callable(authorizer):
authorizer(stream_obj.sock)
return stream_obj
def rpyc_connect(host, port, service=rpyc.VoidService, config={}, ipv6=False, keepalive=False, authorizer=None):
s = AuthSocketStream.connect(
host, port, ipv6=ipv6, keepalive=keepalive,
authorizer=authorizer
)
return rpyc.connect_stream(s, service, config)
print('With correct authorizer')
conn1 = rpyc_connect(
'localhost', 18812, authorizer=lambda sock: sock.send('Ma6ik'.encode())
)
print(conn1.root.secured_op())
print('With wrong authorizer')
conn2 = rpyc_connect(
'localhost', 18812, authorizer=lambda sock: sock.send('Invalid'.encode())
)
try:
conn2.root
except Exception:
print(traceback.format_exc())
print('With no authorizer')
conn3 = rpyc_connect(
'localhost', 18812
)
try:
conn3.root
except Exception:
print(traceback.format_exc())
客户端控制台日志:
With correct authorizer
Secret String
With wrong authorizer
Traceback (most recent call last):
File "/home/client.py", line 40, in <module>
conn2.root
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 507, in root
self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 474, in sync_request
return self.async_request(handler, *args, timeout=timeout).value
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 101, in value
self.wait()
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 48, in wait
self._conn.serve(self._ttl)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 387, in serve
data = self._channel.poll(timeout) and self._channel.recv()
File "/usr/lib/python3.10/site-packages/rpyc/core/channel.py", line 55, in recv
header = self.stream.read(self.FRAME_HEADER.size)
File "/usr/lib/python3.10/site-packages/rpyc/core/stream.py", line 260, in read
raise EOFError("connection closed by peer")
EOFError: connection closed by peer
With no authorizer
Traceback (most recent call last):
File "/home/client.py", line 52, in <module>
conn3.root
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 507, in root
self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 474, in sync_request
return self.async_request(handler, *args, timeout=timeout).value
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 101, in value
self.wait()
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 48, in wait
self._conn.serve(self._ttl)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 387, in serve
data = self._channel.poll(timeout) and self._channel.recv()
File "/usr/lib/python3.10/site-packages/rpyc/core/channel.py", line 55, in recv
header = self.stream.read(self.FRAME_HEADER.size)
File "/usr/lib/python3.10/site-packages/rpyc/core/stream.py", line 260, in read
raise EOFError("connection closed by peer")
EOFError: connection closed by peer
我正在尝试通过用户名和密码保护我的 RpyC 服务器连接。文档确实显示了 example,但它太简短了。没有详细说明密码是如何从客户端传递的。有人知道怎么做吗?提前致谢。
回答我自己的问题:
我不得不在客户端覆盖 RPyC 的一些内部方法以实现所需的行为。我不知道是否存在更清洁的解决方案,但这似乎是一个合理的解决方案。
服务器:
import rpyc
from rpyc.utils.authenticators import AuthenticationError
def magic_word_authenticator(sock):
if sock.recv(5).decode() != "Ma6ik":
raise AuthenticationError("wrong magic word")
return sock, None
class SecuredService(rpyc.Service):
def exposed_secured_op(self):
return 'Secret String'
rpyc.ThreadedServer(
service=SecuredService, hostname='localhost',
port=18812, authenticator=magic_word_authenticator
).start()
客户:
import rpyc
import traceback
class AuthSocketStream(rpyc.SocketStream):
@classmethod
def connect(cls, *args, authorizer=None, **kwargs):
stream_obj = super().connect(*args, **kwargs)
if callable(authorizer):
authorizer(stream_obj.sock)
return stream_obj
def rpyc_connect(host, port, service=rpyc.VoidService, config={}, ipv6=False, keepalive=False, authorizer=None):
s = AuthSocketStream.connect(
host, port, ipv6=ipv6, keepalive=keepalive,
authorizer=authorizer
)
return rpyc.connect_stream(s, service, config)
print('With correct authorizer')
conn1 = rpyc_connect(
'localhost', 18812, authorizer=lambda sock: sock.send('Ma6ik'.encode())
)
print(conn1.root.secured_op())
print('With wrong authorizer')
conn2 = rpyc_connect(
'localhost', 18812, authorizer=lambda sock: sock.send('Invalid'.encode())
)
try:
conn2.root
except Exception:
print(traceback.format_exc())
print('With no authorizer')
conn3 = rpyc_connect(
'localhost', 18812
)
try:
conn3.root
except Exception:
print(traceback.format_exc())
客户端控制台日志:
With correct authorizer
Secret String
With wrong authorizer
Traceback (most recent call last):
File "/home/client.py", line 40, in <module>
conn2.root
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 507, in root
self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 474, in sync_request
return self.async_request(handler, *args, timeout=timeout).value
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 101, in value
self.wait()
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 48, in wait
self._conn.serve(self._ttl)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 387, in serve
data = self._channel.poll(timeout) and self._channel.recv()
File "/usr/lib/python3.10/site-packages/rpyc/core/channel.py", line 55, in recv
header = self.stream.read(self.FRAME_HEADER.size)
File "/usr/lib/python3.10/site-packages/rpyc/core/stream.py", line 260, in read
raise EOFError("connection closed by peer")
EOFError: connection closed by peer
With no authorizer
Traceback (most recent call last):
File "/home/client.py", line 52, in <module>
conn3.root
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 507, in root
self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 474, in sync_request
return self.async_request(handler, *args, timeout=timeout).value
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 101, in value
self.wait()
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 48, in wait
self._conn.serve(self._ttl)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 387, in serve
data = self._channel.poll(timeout) and self._channel.recv()
File "/usr/lib/python3.10/site-packages/rpyc/core/channel.py", line 55, in recv
header = self.stream.read(self.FRAME_HEADER.size)
File "/usr/lib/python3.10/site-packages/rpyc/core/stream.py", line 260, in read
raise EOFError("connection closed by peer")
EOFError: connection closed by peer