mqtt入门(三):emqx认证
前言
- 该笔记学习自mqtt
起步
- 认证方式
1. 内置数据源
username认证
clientid认证
2. 外部数据库
mysql
redis
3. 其他
jwt
http
- 认证结果
认证成功
认证失败
忽略认证
- 关闭匿名认证
# 进入容器内部
docker exec -it 79cc8ddd4941 /bin/sh
# 进入如下路径
cd /opt/emqx/etc
# 编辑配置文件
vi emqx.conf
# 检索配置信息,enter
/allow_anonymous
# 将配置改为false
# 保存并退出配置文件,但不退出容器
# 重启emqx
emqx restart
# 测试匿名认证是否关闭,点击连接,连接失败,说明已关闭匿名认证
- 在数据源中对认证信息进行加密加盐
# 进入容器内的如下路径
cd /opt/emqx/etc/plugins
# 例如编辑mysql数据源
vi emqx_auth_mysql.conf
# 可以查看到连接配置,密码加密方式配置
- 认证流程
输入用户名和密码,emqx根据不同插件连接不同的数据源,从数据源中查询用户名和密码进行认证
- 认证链
当有多个认证方式时,先使用username进行认证,认证通过则连接成功,认证失败则不能连接,当username忽略认证时,则采用clientid进行认证,若client也是忽略,那就再下一个认证方式
username认证
使用username认证,并添加认证数据
- 启动如下插件
# 查看/opt/emqx/etc/plugins路径下的emqx_auth_username.conf
cat emqx_auth_username.conf
# 发现username认证默认配置的加密方式是sha256
# 同时可以添加用户,按如下格式添加,不过这种明文的方式不推荐使用
# 可以使用emqx提供的api来添加,添加的用户数据会存储到内置数据源中
- 使用api添加数据
@hostname = 124.224.115.158
@port=8081
@contentType=application/json
@userName=admin
@password=public
#############查看已有用户认证数据##############
GET http://{{hostname}}:{{port}}/api/v4/auth_username HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
########添加用户认证数据##############
POST http://{{hostname}}:{{port}}/api/v4/auth_username HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
{
"username": "user1",
"password": "123456"
}
###########更改指定用户名的密码#############
###http://{{hostname}}:{{port}}/api/v4/auth_username/${username}
PUT http://{{hostname}}:{{port}}/api/v4/auth_username/user HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
{
"password": "user"
}
###########查看指定用户名信息#############
###http://{{hostname}}:{{port}}/api/v4/auth_username/${username}
GET http://{{hostname}}:{{port}}/api/v4/auth_username/user HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
###########删除指定的用户信息#############
###http://{{hostname}}:{{port}}/api/v4/auth_username/${username}
DELETE http://{{hostname}}:{{port}}/api/v4/auth_username/goudan1 HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
- 下载安装mqttx客户端
https://github.com/emqx/MQTTX
- 连接服务端,2个连接都可以使用同一账号
- test1发送
-test2订阅
clientid认证
- 启动clientid的插件
- 查看配置文件
同样已经默认设置好了密码加密方式
也可以在这里配置client + password,但不推荐
推荐使用emqx提供的api添加client和password
- 使用api添加
####添加clientId和密码#####
POST http://{{hostname}}:{{port}}/api/v4/auth_clientid HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
{
"clientid": "emq-client",
"password": "123456"
}
#############获取所有详细信息########
GET http://{{hostname}}:{{port}}/api/v4/auth_clientid HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
#############更改指定 Client ID 的密码########
###http://{{hostname}}:{{port}}/api/v4/auth_clientid/${client_id}
PUT http://{{hostname}}:{{port}}/api/v4/auth_clientid/emq-client1 HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
{
"password": "654321"
}
#############获取指定ClientId详细信息########
###http://{{hostname}}:{{port}}/api/v4/auth_clientid/${client_id}
GET http://{{hostname}}:{{port}}/api/v4/auth_clientid/emq-client1 HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
#############删除指定的client信息########
### http://{{hostname}}:{{port}}/api/v4/auth_clientid/${client_id}
DELETE http://{{hostname}}:{{port}}/api/v4/auth_clientid/emq-client2 HTTP/1.1
Content-Type: {{contentType}}
Authorization: Basic {{userName}}:{{password}}
- 使用mqttx客户端工具测试
- 先断开username的连接
- 使用clientid连接
注意这里的client id需要填自己刚才通过api添加的数据
host填写服务端ip地址
username也需要填写,但不要填写正确的,否则就会就username的认证了
password必须填写clientid对应的密码
- 收发消息测试
http认证
-
HTTP 认证使用外部自建 HTTP 应用认证数据源,根据 HTTP API 返回的数据判定认证结果,能够实现复杂的
认证鉴权逻辑 -
开启http认证插件
-
认证原理
client <=> EMQ X <=> 自建http认证应用(自己的认证数据源)
客户端将用户名和密码发送到emqx服务端,服务端将数据发送到自建的http认证应用
在自建的http认证应用中认证成功,将返回结果返回给emqx服务端
服务端再决定客户端能否连接emqx
- 查看配置文件
如下部分表示,emqx服务端在请求自建http认证应用时是使用http还是https的方式,默认是http的方式
# 表示emqx服务端在请求自建http认证应用时可以接收的请求头编码、可以接收哪些请求头,默认是所有格式
## HTTP Request Headers
##
## Example: auth.http.header.Accept-Encoding = *
##
## Value: String
## auth.http.header.Accept = */*
# 表示emqx服务端在请求自建http认证应用时,自建http认证应用的ip地址,请求方式默认是post,以及可以接收哪些参数
## Authentication request.
##
## Variables:
## - %u: username
## - %c: clientid
## - %a: ipaddress
## - %r: protocol
## - %P: password
## - %p: sockport of server accepted
## - %C: common name of client TLS cert
## - %d: subject of client TLS cert
##
## Value: URL
auth.http.auth_req = http://127.0.0.1:8991/mqtt/auth
## Value: post | get | put
auth.http.auth_req.method = post
## Value: Params
auth.http.auth_req.params = clientid=%c,username=%u,password=%P
## 重试设置
auth.http.request.retry_times = 3
auth.http.request.retry_interval = 1s
auth.http.request.retry_backoff = 2.0
- 自建http认证应用前提
打开配置文件,配置为自己的http认证应用的ip
auth.http.auth_req = http://192.168.200.10:8991/mqtt/auth
# 将username和clientid插件先停用
- 创建http认证应用
# 新建一个spring boot工程
# 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
# 编写配置文件
server:
port: 8991
spring:
application:
name: emq-demo
# 编写控制器
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.HashMap;
@RestController
@RequestMapping("/mqtt")
public class AuthController {
private static final Logger log = LoggerFactory.getLogger(AuthController.class);
private HashMap<String,String> users;
@PostConstruct
public void init(){
users = new HashMap<>();
users.put("user","123456");
users.put("emq-client2","123456");
users.put("emq-client3","123456");
}
@PostMapping("/auth")
public ResponseEntity auth(@RequestParam("clientid") String clientid,
@RequestParam("username") String username,
@RequestParam("password") String password){
log.info("emqx http认证组件开始调用任务服务完成认证,clientid={},username={},password={}",clientid,username,password);
String value = users.get(username);
if(StringUtils.isEmpty(value)){
return new ResponseEntity(HttpStatus.UNAUTHORIZED);
}
if(!value.equals(password)){
return new ResponseEntity(HttpStatus.UNAUTHORIZED);
}
return new ResponseEntity(HttpStatus.OK);
}
}
- 使用MQTTX连接工具测试连接