forked from kevin/meshtastic_mqtt_server
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
package mqttauth
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
paho "github.com/eclipse/paho.mqtt.golang"
|
|
mqtt "github.com/mochi-mqtt/server/v2"
|
|
"github.com/mochi-mqtt/server/v2/listeners"
|
|
)
|
|
|
|
// TestBrokerIntegration 用真实 TCP broker + paho 客户端验证认证全链路。
|
|
func TestBrokerIntegration(t *testing.T) {
|
|
hook := NewHook(Config{
|
|
Enabled: true,
|
|
Users: []User{{Username: "mesh", PasswordHash: hash(t, "secret")}},
|
|
MaxFailures: 3,
|
|
})
|
|
t.Cleanup(func() { _ = hook.Stop() })
|
|
|
|
server := mqtt.New(&mqtt.Options{InlineClient: true})
|
|
if err := server.AddHook(hook, nil); err != nil {
|
|
t.Fatalf("add hook: %v", err)
|
|
}
|
|
addr := "127.0.0.1:18883"
|
|
if err := server.AddListener(listeners.NewTCP(listeners.Config{ID: "t", Address: addr})); err != nil {
|
|
t.Fatalf("listen: %v", err)
|
|
}
|
|
if err := server.Serve(); err != nil {
|
|
t.Fatalf("serve: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = server.Close() })
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
connect := func(user, pass string) bool {
|
|
opts := paho.NewClientOptions().
|
|
AddBroker("tcp://" + addr).
|
|
SetClientID("smoke-" + user + time.Now().Format("150405.000")).
|
|
SetUsername(user).SetPassword(pass).
|
|
SetConnectTimeout(3 * time.Second)
|
|
client := paho.NewClient(opts)
|
|
token := client.Connect()
|
|
token.WaitTimeout(5 * time.Second)
|
|
ok := token.Error() == nil
|
|
if ok {
|
|
client.Disconnect(50)
|
|
}
|
|
return ok
|
|
}
|
|
|
|
if !connect("mesh", "secret") {
|
|
t.Error("valid credentials should connect")
|
|
}
|
|
if connect("mesh", "wrong") {
|
|
t.Error("wrong password should be rejected")
|
|
}
|
|
if connect("", "") {
|
|
t.Error("anonymous should be rejected when disabled")
|
|
}
|
|
|
|
// 连续失败触发封禁后,正确凭据也应被拒绝(默认阈值 3,本例 MaxFailures=3)。
|
|
// 前面已失败 2 次(mesh/wrong 与匿名),再失败 1 次触发封禁。
|
|
if connect("mesh", "wrong") {
|
|
t.Fatal("wrong password should be rejected")
|
|
}
|
|
if connect("mesh", "secret") {
|
|
t.Error("blocked ip must reject even valid credentials")
|
|
}
|
|
}
|