一直以来都是使用的阿里云的物联网云平台,由于种种原因(主要是改版+收钱),而我只需要使用一些简单的功能,所以实际上个把月以前就用EMQX这个玩意搭建了自己的MQTT通信平台,今天终于抽空实现了HTTP的认证,主要是实现设备连接MQTT平台时进行认证,非平台设备不让进行连接。ACL等认证功能还是没做,当然实现方法类似。
EMQ关于HTTP认证的文档,说实话写的比较简单,感觉信息量比较大,一个细节没注意,导致浪费了很多时间,所以说文档还是要好好看的,当然其还支持很多其他的认证,这里不做一一实现。
由于我以前已经创建了一个Django的服务,所以这次还是在之前的基础上进行功能添加。顺手做了个设备管理相关api。
python manager startapp DeviceManager
INSTALLED_APPS = [
。。。
# 添加上述命令创建的新应用
'DeviceManager'
]
MIDDLEWARE = [
。。。。。
# 注释掉csrf这个,否则会导致post时403 forbidden错误
# 'django.middleware.csrf.CsrfViewMiddleware',
。。。。。
]
# models.py文件
from django.db import models
from django.db.models.lookups import FieldGetDbPrepValueIterableMixin
# Create your models here.
class DeviceInfo(models.Model):
# 设备信息
nickname = models.CharField(max_length=100)
detail = models.CharField(max_length=1000)
# 认证相关
clientid = models.CharField(max_length=256)
username = models.CharField(max_length=255)
password = models.CharField(max_length=255)
# 所属产品
product = models.CharField(max_length=100)
# 节点类型
nodetype = models.IntegerField()
# 更新创建在线时间
datecreate = models.DateTimeField(auto_now=True)
lasttime = models.DateTimeField(auto_now=True)
class ProductInfo(models.Model):
nickname = models.CharField(max_length=100)
detail = models.CharField(max_length=1000)
nodetype = models.IntegerField()
productkey = models.CharField(max_length=20)
datecreate = models.DateTimeField(auto_now=True)
# serializers.py文件
from DeviceManager.models import DeviceInfo,ProductInfo
from rest_framework import serializers
class DeviceInfoSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = DeviceInfo
fields = ['nickname', 'detail', 'clientid', 'username', 'password', 'product', 'nodetype','datecreate', 'lasttime']
class ProductInfoSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ProductInfo
fields = ['nickname', 'detail', 'nodetype', 'productkey', 'datecreate']
# views.py最重要的文件
from rest_framework.response import Response
from rest_framework import viewsets
from DeviceManager.serializers import DeviceInfoSerializer, ProductInfoSerializer
from DeviceManager.models import DeviceInfo, ProductInfo
from rest_framework.views import APIView
from rest_framework import permissions
# Create your views here.
class DeviceInfoViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = DeviceInfo.objects.all()
serializer_class = DeviceInfoSerializer
permission_classes = [permissions.IsAuthenticated]
class ProductInfoViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = ProductInfo.objects.all()
serializer_class = ProductInfoSerializer
permission_classes = [permissions.IsAuthenticated]
# 设备登录api
class DeviceLogin(APIView):
def post(self, request):
# 实际上这个返回值压根没用,EMQ看的是状态码(status code)
ret = {'code':1000, 'msg':None}
username = request.data.get('username')
password = request.data.get('password')
print(username)
obj = DeviceInfo.objects.filter(username=username,password=password).first()
if not obj:
ret['code'] = 1001
ret['msg'] = '用户名或者密码错误'
# 不成功,状态码4XX
return Response(ret, status=401)
ret['msg'] = '登录成功'
# 登陆成功,状态码200就行了
# 返回信息倒是不重要
return Response(ret, status=200)
最重要的三个文件就修改完了。
创建完了API,还是要测试一下的,本来没打算写,但是我的postman不知道为什么不能用了,也懒得重装一下,所以顺便看了下vscode中那个restclient插件怎么使,还挺香。

这里主要是更改配置文件 emqx_auth_http.conf
,正常情况下路径应该是 /etc/emqx/plugins/emqx_auth_http.conf
。修改内容如下:


上述配置文件修改完后,就可以启动插件了,登录EMQ自带的后台管理页面,点击插件,找到对应插件启动即可。