Quote: https://www.jianshu.com/p/69657b7dbd62
MQTT ACL
1, ACL access control list
a, user control
b, release control
c, control subscribe
Mosca the require = var ( "Mosca"); var = new new mosca.Authorizer the auth (); // Create ACL object var = new new mosca.Server Server ({ HTTP: { Port: 3000, the bundle: to true, static: './ ' } }); server.on (' READY ', function () { the console.log (' MQTT Server Started '); server.authenticate = auth.authenticate; // Create a list of users ACL server.authorizePublish = auth.authorizePublish; // create ACL publish a list server.authorizeSubscribe = auth.authorizeSubscribe; // create ACL subscription list // add users, and can only publish and subscribe to presence information presence auth.addUser ( 'yy', '123 ', 'presence', 'Presence', function (error) { IF (error) { the console.log ( 'auth add user error:' + error); } the else { console.log("auth add user yy success"); } }) }); server.on('published', function(packet, client){ console.log('Published: ', packet.payload); }) server.on('subscribed', function(topic, client){ console.log('subscribed: ', topic); }); server.on('unSubscribed', function(topic, client){ console.log('unSubscribed: ', topic); }) server.on('clientConnected', function(client){ console.log('client connected: ', client.id); }); server.on('clientDisConnected', function(client){ console.log('client disConnected: ' + client.id + " userNumber:" + usermap.keys.length); });
Client code
var mqtt = require('mqtt'); var client = mqtt.connect('mqtt://127.0.0.1:1883',{ username: "yy", password: '123' }); client.on('connect', function () { client.subscribe('presence'); client.publish('presence', 'Hello mqtt'); }); client.on('message', function (topic, message) { // message is Buffer console.log(message.toString()); client.end(); });
// console, only the presence subscription and publication of news, no node message subscribed: presence Published: { " clientId " : " mqttjs_97f6e502 " , " Topic " : " presence " } Published: <Buffer 48 65 . 6C. 6C 6F 20 . 6D 71 is 74 74 > Published: { " clientId " : " mqttjs_97f6e502 " , " Topic " : "presence"} Published: mqttjs_97f6e502
Custom access control list
var Mosca = the require ( " Mosca " ); // access control more flexible var Users = [{ the userId: . 1 , username: ' YY1 ' , password: ' 123 ' , publishTopics: [ ' ABC ' , ' ABC / E ' ] , subscribeTopics: [ ' ABC ' , ' text ' ] }]; var userMap = new new the Map (); var authenticate = function(client, username, password, callback){ console.log("client: " + client + " username: " + username + " password:" + password ); var user = users.find(function(data){ console.log(data.toString()); if(username == data.username && password == data.password) { return data; } }) if(user){ console.log("用户验证成功"); usermap.set(client.id, { userId: user.userId, publishTopics: user.publishTopics, subscribeTopics: user.subscribeTopics }); callback(null, true); }else{ console.log("用户验证成功"); callback(null, false); } } var authorizePublish = function(client, topic, payload, callback){ console.log("authorizePublish: " + client + " topic: " + topic + " payload:" + payload ); var user = usermap.get(client.id); if(!user){ console.log('canot find user'); return; } if(user.publishTopics.indexOf(topic) < 0){ console.log('没有找到该主题: ' + topic); callback(null, false); }else{ console.log('找到该主题: ' + topic); callback(null, true); } } var authorizeSubscribe = function(client, topic, callback){ console.log("authorizeSubscribe: " + client + " topic: " + topic ); var user = usermap.get(client.id); if(!user){ console.log('canot find user'); return; } if(user.subscribeTopics.indexOf (Topic) < 0 ) { the console.log ( ' Feed: not found the topic: ' + Topic); the callback ( null , to false ); } the else { the console.log ( ' Feed: found the topic : ' + Topic); the callback ( null , to true ); } } var Settings = { HTTP: { the bundle: to true } } var Server = new new mosca.Server (Settings); server.on('ready', function(){ console.log('mqtt server started'); // 自定义权限列表 server.authenticate = authenticate; server.authorizePublish = authorizePublish; server.authorizeSubscribe = authorizeSubscribe; console.log('auth ready'); }); server.on('published', function(packet, client){ console.log('YYPublished: ', packet.payload); }) server.on('subscribed', function(topic, client){ console.log('subscribed: ', topic); }); server.on('unSubscribed', function(topic, client){ console.log('unSubscribed: ', topic); }) server.on('clientConnected', function(client){ console.log('client connected: ', client.id); }); server.on('clientDisConnected', function(client){ usermap.delete(client.id); console.log('client disConnected: ' + client.id + " userNumber:" + usermap.keys.length); });
client.js
var mqtt =require('mqtt'); var client = mqtt.connect('mqtt://localhost:1883',{ username:'yy1', password:'123' }) client.on('connect', function () { client.subscribe('abc'); // 主题 消息 内功 client.publish('abc', 'Hello node1/node2/node3'); client.subscribe('text111'); }) client.on('message', function (topic, message) { // message is Buffer console.log('receive message: ' + topic); console.log(message.toString()) client.end() }) client.on('reconnect', function(){ console.log('reconnect'); }) client.on('offline', function(){ console.log('offline'); })
Essentially is their part of the authorization to implement the interface. Specific reference may interface the author mosca.
Authorizer.js
Authorizer.prototype._authenticate = function(client, user, pass, cb) { var missingUser = !user || !pass || !this.users[user]; if (missingUser) { cb(null, false); return; } user = user.toString(); client.user = user; user = this.users[user]; hasher({ password: pass.toString(), salt: user.salt }, function(err, pass, salt, hash) { if (err) { cb(err); return; } var success = (user.hash === hash); cb(null, success); }); }; /** * An utility function to add an user. * * @api public * @param {String} user The username * @param {String} pass The password * @param {String} authorizePublish The authorizePublish pattern * (optional) * @param {String} authorizeSubscribe The authorizeSubscribe pattern * (optional) * @param {Function} cb The callback that will be called after the * insertion. */ Authorizer.prototype.addUser = function(user, pass, authorizePublish, authorizeSubscribe, cb) { var that = this; if (typeof authorizePublish === "function") { cb = authorizePublish; authorizePublish = null; authorizeSubscribe = null; } else if (typeof authorizeSubscribe == "function") { cb = authorizeSubscribe; authorizeSubscribe = null; } if (!authorizePublish) { authorizePublish = defaultGlob; } if (!authorizeSubscribe) { authorizeSubscribe = defaultGlob; } hasher({ password: pass.toString() }, function(err, pass, salt, hash) { if (!err) { that.users[user] = { salt: salt, hash: hash, authorizePublish: authorizePublish, authorizeSubscribe: authorizeSubscribe }; } cb(err); }); return this; }; /** * An utility function to delete a user. * * @api public * @param {String} user The username * @param {String} pass The password * @param {Function} cb The callback that will be called after the * deletion. */ Authorizer.prototype.rmUser = function(user, cb) { delete this.users[user]; cb(); return this; };