认证鉴权

    系统默认开启匿名认证(Anonymous),通过加载认证插件可开启的多个认证模块组成认证链:

    匿名认证设置

    匿名认证是认证链条最后一个环节, etc/emqx.conf 中默认启用匿名认证,产品部署建议关闭:

    访问控制(ACL)

    EMQ X 消息服务器通过 ACL(Access Control List) 实现 MQTT 客户端访问控制。

    ACL 访问控制规则定义:

    MQTT 客户端发起订阅/发布请求时,EMQ X 消息服务器的访问控制模块,会逐条匹配 ACL 规则,直到匹配成功为止:

    image

    访问控制设置

    EMQ X 消息服务器访问控制功能在 emqx.conf 配置文件中设置:

    1. ## 当未开启认证插件、或认证请求被所有认证插件忽略时,是否允许该用户以匿名身份登录
    2. allow_anonymous = true
    3. ## 所有 ACL 规则都不匹配时是否允许访问
    4. acl_nomatch = allow
    5. ## ACL 规则文件
    6. acl_file = etc/acl.conf
    7. ## 是否开启 ACL 缓存功能
    8. enable_acl_cache = on
    9. ## ACL 最大缓存数量
    10. acl_cache_max_size = 32
    11. ## ACL 缓存清理周期
    12. acl_cache_ttl = 1m
    13. ## 配置 ACL 检查失败时的操作
    14. acl_deny_action = ignore

    ACL 规则默认从 etc/acl.conf 中获取,在 EMQ X 启动时加载到内存:

    1. %% 允许 'dashboard' 订阅 '$SYS/#'
    2. {allow, {user, "dashboard"}, subscribe, ["$SYS/#"]}.
    3. %% 允许来自 localhost 的客户端订阅所有主题
    4. {allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.
    5. %% 拒绝客户端订阅 '$SYS/#' and '#'
    6. {deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.
    7. ## 允许所有
    8. {allow, all}.

    ACL 规则修改后可通过命令行重新加载:

    1. $ ./bin/emqx_ctl acl reload
    2. reload acl_internal successfully

    EMQ X 支持 ClientId、Username、HTTP、OpenLDAP、MySQL、Redis、PostgreSQL、MongoDB、JWT 多种认证集成方式,以认证插件方式提供可同时加载多个形成认证链。

    EMQ X 认证插件配置文件,在 /etc/emqx/plugins/(RPM/DEB 安装) 或 etc/plugins/(独立安装) 目录:

    ClientID 认证插件配置

    配置文件 emqx_auth_clientid.conf,配置加密方式:

    1. ## 默认 用户列表 试例:
    2. ##auth.client.1.clientid = id
    3. ##auth.client.1.password = passwd
    4. ##auth.client.2.clientid = dev:devid
    5. ##auth.client.2.password = passwd2
    6. ##auth.client.3.clientid = app:appid
    7. ##auth.client.3.password = passwd3
    8. ##auth.client.4.clientid = client~!@#$%^&*()_+
    9. ##auth.client.4.password = passwd~!@#$%^&*()_+
    10. ## 密码 hash 方式.
    11. ##
    12. ## 值: plain | md5 | sha | sha256
    13. auth.client.password_hash = sha256

    加载 ClientId 认证插件:

    1. ./bin/emqx_ctl plugins load emqx_auth_clientid
    1. 通过 ./bin/emqx_ctl 管理命令行添加用户:

      1. ./bin/emqx_ctl clientid add \<ClientId> \<Password>
    2. 通过 HTTP API 添加用户:

      1. POST api/v3/auth_clientid
      2. {
      3. "clientid": "clientid",
      4. "password": "password"
      5. }

    Username 认证插件配置

    配置文件 emqx_auth_username.conf,配置加密方式:

    1. ## 默认 用户列表 试例:
    2. \##auth.user.1.username = admin
    3. \##auth.user.1.password = public
    4. \##auth.user.2.username = feng@emqtt.io
    5. \##auth.user.2.password = public
    6. \##auth.user.3.username = name~!@#$%^&*()_+
    7. \##auth.user.3.password = pwsswd~!@#$%^&*()_+
    8. ## 密码 hash 方式.
    9. ##
    10. ## 值: plain | md5 | sha | sha256
    11. auth.user.password_hash = sha256

    加载 Username 认证插件:

    1. ./bin/emqx_ctl plugins load emqx_auth_username

    加载插件后,可以通过以下两种方式添加用户:

    1. 通过 ./bin/emqx_ctl 管理命令行添加用户:

      1. $ ./bin/emqx_ctl users add <Username> <Password>
    2. 通过 HTTP API 添加用户:

      1. POST api/v3/auth_username
      2. {
      3. "username": "username",
      4. "password": "password"
      5. }

    OpenLDAP 认证插件配置

    配置文件 emqx_auth_ldap.conf,配置 OpenLDAP 服务器参数:

    1. ## OpenLDAP 服务器列表
    2. auth.ldap.servers = 127.0.0.1
    3. ## OpenLDAP 服务器端口
    4. auth.ldap.port = 389
    5. ## OpenLDAP 连接池大小
    6. auth.ldap.pool = 8
    7. ## OpenLDAP Bind DN.
    8. auth.ldap.bind_dn = cn=root,dc=emqx,dc=io
    9. ## OpenLDAP Bind 密码.
    10. auth.ldap.bind_password = public
    11. ## OpenLDAP 查询超时时间
    12. auth.ldap.timeout = 30s
    13. ## OpenLDAP Device DN.
    14. auth.ldap.device_dn = ou=device,dc=emqx,dc=io
    15. ## 指定的 ObjectClass
    16. auth.ldap.match_objectclass = mqttUser
    17. ## username 的属性类型
    18. auth.ldap.username.attributetype = uid
    19. ## password 的属性类型
    20. auth.ldap.password.attributetype = userPassword
    21. ## 是否开启 SSL
    22. auth.ldap.ssl = false

    加载 OpenLDAP 认证插件:

    1. ./bin/emqx_ctl plugins load emqx_auth_ldap

    配置文件 emqx_auth_http.conf,设置 HTTP 请求相关参数

    1. ## HTTP 请求超时时间,0 表示永不超时
    2. ## auth.http.request.timeout = 0
    3. ## 连接超时时间,0 表示永不超时
    4. ## auth.http.request.connect_timout = 0
    5. ## HTTP 请求重传次数
    6. auth.http.request.retry_times = 3
    7. ## HTTP 请求重传间隔
    8. auth.http.request.retry_interval = 1s
    9. ## 请求重传使用了指数退避机制, 实际重传间隔为 `interval * backoff ^ times`
    10. auth.http.request.retry_backoff = 2.0

    设置认证 URL 及其参数:

    设置超级用户 URL 及其参数:

    1. auth.http.super_req = http://127.0.0.1:8991/mqtt/superuser
    2. auth.http.super_req.method = post
    3. auth.http.super_req.params = clientid=%c,username=%u

    设置访问控制(ACL) URL 及其参数:

    1. ## 'access' parameter: sub = 1, pub = 2
    2. auth.http.acl_req = http://127.0.0.1:8991/mqtt/acl
    3. auth.http.acl_req.method = get
    4. auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t

    HTTP 认证/访问控制(ACL)服务器 API 设计:

    1. 认证/ACL 成功,API 返回 200
    2. 认证/ACL 失败,API 返回 4xx
    1. ./bin/emqx_ctl plugins load emqx_auth_http

    MySQL 认证插件配置

    配置文件 emqx_auth_mysql.conf, 默认的 MQTT 用户、ACL 库表和认证设置:

    1. CREATE TABLE `mqtt_user` (
    2. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    3. `username` varchar(100) DEFAULT NULL,
    4. `password` varchar(100) DEFAULT NULL,
    5. `salt` varchar(100) DEFAULT NULL,
    6. `is_superuser` tinyint(1) DEFAULT 0,
    7. `created` datetime DEFAULT NULL,
    8. PRIMARY KEY (`id`),
    9. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    Tip

    用户可自定义认证用户表,通过 auth_query 配置查询语句。

    MQTT 访问控制表

    1. CREATE TABLE `mqtt_acl` (
    2. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    3. `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow',
    4. `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
    5. `username` varchar(100) DEFAULT NULL COMMENT 'Username',
    6. `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
    7. `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
    8. `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
    9. PRIMARY KEY (`id`)
    10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    11. INSERT INTO `mqtt_acl` (`id`, `allow`, `ipaddr`, `username`, `clientid`, `access`, `topic`)
    12. VALUES
    13. (1,1,NULL,'$all',NULL,2,'#'),
    14. (2,0,NULL,'$all',NULL,1,'$SYS/#'),
    15. (3,0,NULL,'$all',NULL,1,'eq #'),
    16. (4,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'),
    17. (5,1,'127.0.0.1',NULL,NULL,2,'#'),
    18. (6,1,NULL,'dashboard',NULL,1,'$SYS/#');

    配置 MySQL 服务器地址

    1. ## Mysql 服务器地址
    2. auth.mysql.server = 127.0.0.1:3306
    3. ## Mysql 连接池大小
    4. auth.mysql.pool = 8
    5. ## Mysql 用户名
    6. ## auth.mysql.username =
    7. ## Mysql 密码
    8. ## auth.mysql.password =
    9. ## Mysql 数据库名
    10. auth.mysql.database = mqtt
    11. ## MySQL 查询超时
    12. ## auth.mysql.query_timeout = 5s

    配置 MySQL 认证查询语句

    1. ## 认证查询语句
    2. ##
    3. ## Variables:
    4. ## - %u: username
    5. ## - %c: clientid
    6. ## - %C: common name of client TLS cert
    7. ## - %d: subject of client TLS cert
    8. auth.mysql.auth_query = select password from mqtt_user where username = '%u' limit 1
    9. ## Password hash: plain, md5, sha, sha256, pbkdf2, bcrypt
    10. auth.mysql.password_hash = sha256
    11. ## sha256 with salt prefix
    12. ## auth.mysql.password_hash = salt,sha256
    13. ## sha256 with salt suffix
    14. ## auth.mysql.password_hash = sha256,salt
    15. ## bcrypt with salt only prefix
    16. ## auth.mysql.password_hash = salt,bcrypt
    17. ## pbkdf2 with macfun iterations dklen
    18. ## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512
    19. ## auth.mysql.password_hash = pbkdf2,sha256,1000,20
    20. ## 超级用户查询语句
    21. ##
    22. ## Variables:
    23. ## - %u: username
    24. ## - %c: clientid
    25. ## - %C: common name of client TLS cert
    26. ## - %d: subject of client TLS cert
    27. auth.mysql.super_query = select is_superuser from mqtt_user where username = '%u' limit 1

    配置 MySQL 访问控制查询语句

    1. ## ACL 查询语句
    2. ##
    3. ## Variables:
    4. ## - %a: ipaddr
    5. ## - %u: username
    6. ## - %c: clientid
    7. auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'

    加载 MySQL 认证插件

    1. ./bin/emqx_ctl plugins load emqx_auth_mysql

    PostgreSQL 认证插件配置

    配置文件 emqx_auth_pgsql.conf, 默认的 MQTT 用户、ACL 库表和认证设置:

    PostgreSQL MQTT 用户表

    1. CREATE TABLE mqtt_user (
    2. id SERIAL primary key,
    3. is_superuser boolean,
    4. username character varying(100),
    5. password character varying(100),
    6. salt character varying(100)
    7. );

    Tip

    若用户自定义认证用户表,则需要通过 auth_query 自行配置查询语句。

    PostgreSQL MQTT 访问控制表

    1. CREATE TABLE mqtt_acl (
    2. id SERIAL primary key,
    3. allow integer,
    4. ipaddr character varying(60),
    5. username character varying(100),
    6. clientid character varying(100),
    7. access integer,
    8. topic character varying(100)
    9. );
    10. INSERT INTO mqtt_acl (id, allow, ipaddr, username, clientid, access, topic)
    11. VALUES
    12. (1,1,NULL,'$all',NULL,2,'#'),
    13. (2,0,NULL,'$all',NULL,1,'$SYS/#'),
    14. (3,0,NULL,'$all',NULL,1,'eq #'),
    15. (4,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'),
    16. (5,1,'127.0.0.1',NULL,NULL,2,'#'),
    17. (6,1,NULL,'dashboard',NULL,1,'$SYS/#');

    配置 PostgreSQL 服务器地址

    1. ## PostgreSQL 服务器
    2. auth.pgsql.server = 127.0.0.1:5432
    3. ## PostgreSQL 连接池大小
    4. auth.pgsql.pool = 8
    5. ## PostgreSQL 用户名
    6. auth.pgsql.username = root
    7. ## PostgreSQL 密码
    8. ## auth.pgsql.password =
    9. ## PostgreSQL 数据库名
    10. auth.pgsql.database = mqtt
    11. ## PostgreSQL 字符编码方式
    12. auth.pgsql.encoding = utf8
    13. ## 是否开启 SSL
    14. auth.pgsql.ssl = false
    15. ## auth.pgsql.ssl_opts.keyfile =
    16. ## auth.pgsql.ssl_opts.certfile =
    17. ## auth.pgsql.ssl_opts.cacertfile =
    1. ## 认证查询语句
    2. ##
    3. ## Variables:
    4. ## - %u: username
    5. ## - %c: clientid
    6. ## - %C: common name of client TLS cert
    7. ## - %d: subject of client TLS cert
    8. auth.pgsql.auth_query = select password from mqtt_user where username = '%u' limit 1
    9. ## Password hash: plain, md5, sha, sha256, pbkdf2, bcrypt
    10. auth.pgsql.password_hash = sha256
    11. ## sha256 with salt prefix
    12. ## auth.pgsql.password_hash = salt,sha256
    13. ## sha256 with salt suffix
    14. ## auth.pgsql.password_hash = sha256,salt
    15. ## bcrypt with salt prefix
    16. ## auth.pgsql.password_hash = salt,bcrypt
    17. ## pbkdf2 with macfun iterations dklen
    18. ## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512
    19. ## auth.pgsql.password_hash = pbkdf2,sha256,1000,20
    20. ## 超级用户查询语句
    21. ##
    22. ## Variables:
    23. ## - %u: username
    24. ## - %c: clientid
    25. ## - %C: common name of client TLS cert
    26. ## - %d: subject of client TLS cert
    27. auth.pgsql.super_query = select is_superuser from mqtt_user where username = '%u' limit 1

    配置 PostgreSQL 访问控制语句

    1. ## ACL 查询语句
    2. ##
    3. ## Variables:
    4. ## - %a: ipaddress
    5. ## - %u: username
    6. ## - %c: clientid
    7. auth.pgsql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'

    加载 PostgreSQL 认证插件

    Redis 认证插件配置

    配置文件 emqx_auth_redis.conf:

    配置 Redis 服务器地址

    1. ## Redis 服务器集群类型
    2. auth.redis.type = single
    3. ## Redis 服务器列表
    4. auth.redis.server = 127.0.0.1:6379
    5. ## Redis Sentinel
    6. ## auth.redis.server = 127.0.0.1:26379
    7. ## Redis Sentinel 集群名称
    8. ## auth.redis.sentinel = mymaster
    9. ## Redis 连接池大小
    10. auth.redis.pool = 8
    11. ## Redis 数据库名
    12. auth.redis.database = 0
    13. ## Redis 密码
    14. ## Redis 查询超时
    15. ## auth.redis.query_timeout = 5s

    配置认证查询命令

    1. ## Variables: %u = username, %c = clientid
    2. ## 认证查询命令
    3. ##
    4. ## Variables:
    5. ## - %u: username
    6. ## - %c: clientid
    7. ## - %C: common name of client TLS cert
    8. ## - %d: subject of client TLS cert
    9. auth.redis.auth_cmd = HGET mqtt_user:%u password
    10. ## Password hash: plain, md5, sha, sha256, pbkdf2, bcrypt
    11. auth.redis.password_hash = plain
    12. ## sha256 with salt prefix
    13. ## auth.redis.password_hash = salt,sha256
    14. ## sha256 with salt suffix
    15. ## auth.redis.password_hash = sha256,salt
    16. ## bcrypt with salt prefix
    17. ## auth.redis.password_hash = salt,bcrypt
    18. ## pbkdf2 with macfun iterations dklen
    19. ## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512
    20. ## auth.redis.password_hash = pbkdf2,sha256,1000,20
    21. ## 超级用户查询命令
    22. ##
    23. ## Variables:
    24. ## - %u: username
    25. ## - %c: clientid
    26. ## - %C: common name of client TLS cert
    27. ## - %d: subject of client TLS cert
    28. auth.redis.super_cmd = HGET mqtt_user:%u is_superuser

    配置访问控制查询命令

    1. ## ACL 查询命令
    2. ##
    3. ## Variables:
    4. ## - %u: username
    5. ## - %c: clientid
    6. auth.redis.acl_cmd = HGETALL mqtt_acl:%u

    Redis 认证用户 Hash

    默认采用 Hash 存储认证用户:

    1. HSET mqtt_user:\<username> is_superuser 1
    2. HSET mqtt_user:\<username> password "passwd"

    Redis ACL 规则 Hash

    默认采用 Hash 存储 ACL 规则:

    1. HSET mqtt_acl:\<username> topic1 1
    2. HSET mqtt_acl:\<username> topic2 2
    3. HSET mqtt_acl:\<username> topic3 3

    Tip

    1: subscribe, 2: publish, 3: pubsub

    加载 Redis 认证插件

    1. ./bin/emqx_ctl plugins load emqx_auth_redis

    配置文件 emqx_auth_mongo.conf, MongoDB、MQTT 用户、ACL 集合设置:

    1. ## MongoDB Topology 类型: single | unknown | sharded | rs
    2. auth.mongo.type = single
    3. ## MongoDB 服务器列表
    4. auth.mongo.server = 127.0.0.1:27017
    5. ## MongoDB 连接池大小
    6. auth.mongo.pool = 8
    7. ## MongoDB 用户名
    8. ## auth.mongo.user =
    9. ## MongoDB 密码
    10. ## auth.mongo.password =
    11. ## MongoDB 数据库名
    12. auth.mongo.database = mqtt
    13. ## MongoDB 超时时间
    14. ## auth.mongo.query_timeout = 5s
    15. ## 是否开启 SSL
    16. ## auth.mongo.ssl = false
    17. ## SSL keyfile.
    18. ## auth.mongo.ssl_opts.keyfile =
    19. ## SSL certfile.
    20. ## auth.mongo.ssl_opts.certfile =
    21. ## SSL cacertfile.
    22. ## auth.mongo.ssl_opts.cacertfile =
    23. ## MongoDB 写模式
    24. ## auth.mongo.w_mode =
    25. ## MongoDB 读模式
    26. ## auth.mongo.r_mode =
    27. ## MongoDB topology 选项
    28. auth.mongo.topology.pool_size = 1
    29. auth.mongo.topology.max_overflow = 0
    30. ## auth.mongo.topology.overflow_ttl = 1000
    31. ## auth.mongo.topology.overflow_check_period = 1000
    32. ## auth.mongo.topology.local_threshold_ms = 1000
    33. ## auth.mongo.topology.connect_timeout_ms = 20000
    34. ## auth.mongo.topology.socket_timeout_ms = 100
    35. ## auth.mongo.topology.server_selection_timeout_ms = 30000
    36. ## auth.mongo.topology.wait_queue_timeout_ms = 1000
    37. ## auth.mongo.topology.heartbeat_frequency_ms = 10000
    38. ## auth.mongo.topology.min_heartbeat_frequency_ms = 1000

    配置认证查询集合

    1. ## auth_query
    2. auth.mongo.auth_query.collection = mqtt_user
    3. auth.mongo.auth_query.password_field = password
    4. ## Password hash: plain, md5, sha, sha256, bcrypt
    5. auth.mongo.auth_query.password_hash = sha256
    6. ## sha256 with salt suffix
    7. ## auth.mongo.auth_query.password_hash = sha256,salt
    8. ## sha256 with salt prefix
    9. ## auth.mongo.auth_query.password_hash = salt,sha256
    10. ## bcrypt with salt prefix
    11. ## auth.mongo.auth_query.password_hash = salt,bcrypt
    12. ## pbkdf2 with macfun iterations dklen
    13. ## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512
    14. ## auth.mongo.auth_query.password_hash = pbkdf2,sha256,1000,20
    15. ## 认证 Selector
    16. ##
    17. ## Variables:
    18. ## - %u: username
    19. ## - %c: clientid
    20. ## - %C: common name of client TLS cert
    21. ## - %d: subject of client TLS cert
    22. auth.mongo.auth_query.selector = username=%u
    23. ## 超级用户 Selector
    24. auth.mongo.super_query = on
    25. auth.mongo.super_query.collection = mqtt_user
    26. auth.mongo.super_query.super_field = is_superuser
    27. auth.mongo.super_query.selector = username=%u

    配置 ACL 查询集合

    1. ## 是否开启 ACL 功能
    2. auth.mongo.acl_query = on
    3. auth.mongo.aclquery.collection = mqtt_acl
    4. ## ACL Selector.
    5. ##
    6. ## Variables:
    7. ## - %u: username
    8. ## - %c: clientid
    9. auth.mongo.aclquery.selector = username=%u

    MongoDB 数据库

    1. use mqtt
    2. db.createCollection("mqtt_user")
    3. db.createCollection("mqtt_acl")
    4. db.mqtt_user.ensureIndex({"username":1})

    Tip

    数据库、集合名称可自定义

    MongoDB 用户集合示例

    1. {
    2. username: "user",
    3. password: "password hash",
    4. is_superuser: boolean (true, false),
    5. created: "datetime"
    6. }
    7. db.mqtt_user.insert({username: "test", password: "password hash", is_superuser: false})
    8. db.mqtt_user:insert({username: "root", is_superuser: true})

    MongoDB ACL 集合示例

    1. {
    2. username: "username",
    3. clientid: "clientid",
    4. publish: ["topic1", "topic2", ...],
    5. subscribe: ["subtop1", "subtop2", ...],
    6. pubsub: ["topic/#", "topic1", ...]
    7. }
    8. db.mqtt_acl.insert({username: "test", publish: ["t/1", "t/2"], subscribe: ["user/%u", "client/%c"]})
    9. db.mqtt_acl.insert({username: "admin", pubsub: ["#"]})

    加载 MognoDB 认证插件

    1. ./bin/emqx_ctl plugins load emqx_auth_mongo

    JWT 认证插件配置

    配置 JWT 认证

    1. ## HMAC hash secret
    2. auth.jwt.secret = emqxsecret
    3. ## 配置 JWT 字符串从何处获取
    4. auth.jwt.from = password
    5. ## RSA or ECDSA 公钥文件
    6. ## auth.jwt.pubkey = /etc/certs/jwt_public_key.pem
    7. ## 是否验证 claims 字段
    8. auth.jwt.verify_claims = off
    9. ## 要验证的 claims 清单
    10. ## auth.jwt.verify_claims.username = %u

    加载 JWT 认证插件