kopia lustrzana https://github.com/Yakifo/amqtt
rodzic
15cea7e9fa
commit
61cdc1a0d2
|
@ -636,25 +636,26 @@ class Broker:
|
|||
def authenticate(self, session: Session, listener):
|
||||
"""
|
||||
This method call the authenticate method on registered plugins to test user authentication.
|
||||
User is considered authenticated if at least one plugin returns True.
|
||||
User is considered authenticated if all plugins called returns True.
|
||||
Plugins authenticate() method are supposed to return :
|
||||
- True if user is authentication succeed
|
||||
- False if user authentication fails
|
||||
- None if authentication can't be achieved (then plugin result is then ignored)
|
||||
:param session:
|
||||
:param listener:
|
||||
:return:
|
||||
"""
|
||||
returns = yield from self.plugins_manager.map_plugin_coro("authenticate", session=session)
|
||||
if not returns:
|
||||
self.logger.debug("Authentication plugin results: %r" % returns)
|
||||
return True
|
||||
else:
|
||||
for res in returns:
|
||||
if res:
|
||||
# Consider authentication succeed if at least one plugin returns True
|
||||
return True
|
||||
# If all plugins returned False, authentications is failed
|
||||
return True
|
||||
|
||||
# TODO : Handle client authentication here
|
||||
return True
|
||||
auth_result = True
|
||||
for plugin in returns:
|
||||
res = returns[plugin]
|
||||
if res is False:
|
||||
auth_result = False
|
||||
self.logger.debug("Authentication failed due to '%s' plugin result: %s" % (plugin.name, res))
|
||||
else:
|
||||
self.logger.debug("'%s' plugin result: %s" % (plugin.name, res))
|
||||
# If all plugins returned True, authentication is success
|
||||
return auth_result
|
||||
|
||||
def retain_message(self, source_session, topic_name, data, qos=None):
|
||||
if data is not None and data != b'':
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#
|
||||
# See the file license.txt for copying permission.
|
||||
import logging
|
||||
import asyncio
|
||||
from passlib.apps import custom_app_context as pwd_context
|
||||
|
||||
|
||||
|
@ -25,6 +26,7 @@ class AnonymousAuthPlugin(BaseAuthPlugin):
|
|||
def __init__(self, context):
|
||||
super().__init__(context)
|
||||
|
||||
@asyncio.coroutine
|
||||
def authenticate(self, *args, **kwargs):
|
||||
authenticated = super().authenticate(*args, **kwargs)
|
||||
if authenticated:
|
||||
|
@ -72,14 +74,18 @@ class FileAuthPlugin(BaseAuthPlugin):
|
|||
else:
|
||||
self.context.logger.debug("Configuration parameter 'password_file' not found")
|
||||
|
||||
@asyncio.coroutine
|
||||
def authenticate(self, *args, **kwargs):
|
||||
authenticated = super().authenticate(*args, **kwargs)
|
||||
if authenticated:
|
||||
session = kwargs.get('session', None)
|
||||
hash = self._users.get(session.username, None)
|
||||
if not hash:
|
||||
authenticated = False
|
||||
self.context.logger.debug("User '%s' unknown" % session.username)
|
||||
if session.username:
|
||||
hash = self._users.get(session.username, None)
|
||||
if not hash:
|
||||
authenticated = False
|
||||
self.context.logger.debug("No hash found for user '%s'" % session.username)
|
||||
else:
|
||||
authenticated = pwd_context.verify(session.password, hash)
|
||||
else:
|
||||
authenticated = pwd_context.verify(session.password, hash)
|
||||
return None
|
||||
return authenticated
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import logging
|
||||
import asyncio
|
||||
import os
|
||||
from hbmqtt.broker import Broker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -19,6 +20,11 @@ config = {
|
|||
},
|
||||
},
|
||||
'sys_interval': 0,
|
||||
'auth': {
|
||||
'allow-anonymous': False,
|
||||
'password-file': os.path.join(os.path.dirname(os.path.realpath(__file__)), "passwd")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
broker = Broker(config)
|
||||
|
|
|
@ -45,7 +45,7 @@ def test_coro():
|
|||
@asyncio.coroutine
|
||||
def test_coro2():
|
||||
try:
|
||||
future = yield from C.connect('mqtt://localhost:1883/')
|
||||
future = yield from C.connect('mqtt://test:test@localhost:1883/')
|
||||
future.add_done_callback(disconnected)
|
||||
yield from asyncio.wait([asyncio.async(C.publish('a/b', b'TEST MESSAGE WITH QOS_1', qos=0x01))])
|
||||
logger.info("messages published")
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# Test user with 'test' password encrypted with sha-512
|
||||
test:$6$l4zQEHEcowc1Pnv4$HHrh8xnsZoLItQ8BmpFHM4r6q5UqK3DnXp2GaTm5zp5buQ7NheY3Xt9f6godVKbEtA.hOC7IEDwnok3pbAOip.
|
1
setup.py
1
setup.py
|
@ -41,6 +41,7 @@ setup(
|
|||
# 'event_logger_plugin = hbmqtt.plugins.logging:EventLoggerPlugin',
|
||||
'packet_logger_plugin = hbmqtt.plugins.logging:PacketLoggerPlugin',
|
||||
'auth_anonymous = hbmqtt.plugins.authentication:AnonymousAuthPlugin',
|
||||
'auth_file = hbmqtt.plugins.authentication:FileAuthPlugin',
|
||||
],
|
||||
'hbmqtt.client.plugins': [
|
||||
'packet_logger_plugin = hbmqtt.plugins.logging:PacketLoggerPlugin',
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import unittest
|
||||
import logging
|
||||
import os
|
||||
import asyncio
|
||||
from hbmqtt.plugins.manager import BaseContext
|
||||
from hbmqtt.plugins.authentication import AnonymousAuthPlugin, FileAuthPlugin
|
||||
from hbmqtt.session import Session
|
||||
|
@ -14,6 +15,9 @@ logging.basicConfig(level=logging.DEBUG, format=formatter)
|
|||
|
||||
|
||||
class TestAnonymousAuthPlugin(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
def test_allow_anonymous(self):
|
||||
context = BaseContext()
|
||||
context.logger = logging.getLogger(__name__)
|
||||
|
@ -25,7 +29,8 @@ class TestAnonymousAuthPlugin(unittest.TestCase):
|
|||
s = Session()
|
||||
s.username = ""
|
||||
auth_plugin = AnonymousAuthPlugin(context)
|
||||
self.assertTrue(auth_plugin.authenticate())
|
||||
ret = self.loop.run_until_complete(auth_plugin.authenticate(session=s))
|
||||
self.assertTrue(ret)
|
||||
|
||||
def test_disallow_anonymous(self):
|
||||
context = BaseContext()
|
||||
|
@ -38,7 +43,8 @@ class TestAnonymousAuthPlugin(unittest.TestCase):
|
|||
s = Session()
|
||||
s.username = ""
|
||||
auth_plugin = AnonymousAuthPlugin(context)
|
||||
self.assertFalse(auth_plugin.authenticate(session=s))
|
||||
ret = self.loop.run_until_complete(auth_plugin.authenticate(session=s))
|
||||
self.assertFalse(ret)
|
||||
|
||||
def test_allow_nonanonymous(self):
|
||||
context = BaseContext()
|
||||
|
@ -51,10 +57,14 @@ class TestAnonymousAuthPlugin(unittest.TestCase):
|
|||
s = Session()
|
||||
s.username = "test"
|
||||
auth_plugin = AnonymousAuthPlugin(context)
|
||||
self.assertTrue(auth_plugin.authenticate(session=s))
|
||||
ret = self.loop.run_until_complete(auth_plugin.authenticate(session=s))
|
||||
self.assertTrue(ret)
|
||||
|
||||
|
||||
class TestFileAuthPlugin(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
def test_allow(self):
|
||||
context = BaseContext()
|
||||
context.logger = logging.getLogger(__name__)
|
||||
|
@ -67,7 +77,8 @@ class TestFileAuthPlugin(unittest.TestCase):
|
|||
s.username = "user"
|
||||
s.password = "test"
|
||||
auth_plugin = FileAuthPlugin(context)
|
||||
self.assertTrue(auth_plugin.authenticate(session=s))
|
||||
ret = self.loop.run_until_complete(auth_plugin.authenticate(session=s))
|
||||
self.assertTrue(ret)
|
||||
|
||||
def test_wrong_password(self):
|
||||
context = BaseContext()
|
||||
|
@ -81,7 +92,8 @@ class TestFileAuthPlugin(unittest.TestCase):
|
|||
s.username = "user"
|
||||
s.password = "wrong password"
|
||||
auth_plugin = FileAuthPlugin(context)
|
||||
self.assertFalse(auth_plugin.authenticate(session=s))
|
||||
ret = self.loop.run_until_complete(auth_plugin.authenticate(session=s))
|
||||
self.assertFalse(ret)
|
||||
|
||||
def test_unknown_password(self):
|
||||
context = BaseContext()
|
||||
|
@ -95,4 +107,5 @@ class TestFileAuthPlugin(unittest.TestCase):
|
|||
s.username = "some user"
|
||||
s.password = "some password"
|
||||
auth_plugin = FileAuthPlugin(context)
|
||||
self.assertFalse(auth_plugin.authenticate(session=s))
|
||||
ret = self.loop.run_until_complete(auth_plugin.authenticate(session=s))
|
||||
self.assertFalse(ret)
|
||||
|
|
Ładowanie…
Reference in New Issue