前言
- 該筆記學習自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連接工具測試連接