Lae/app/Http/Controllers/Application/MqttAuthController.php

163 lines
4.3 KiB
PHP
Raw Normal View History

2022-11-27 06:40:45 +00:00
<?php
namespace App\Http\Controllers\Application;
use App\Http\Controllers\Controller;
use App\Models\Module;
2022-12-03 06:05:37 +00:00
use App\Models\ModuleAllow;
2022-11-27 06:40:45 +00:00
use Illuminate\Http\Request;
2023-01-10 13:42:27 +00:00
use Illuminate\Http\Response;
2022-11-27 06:40:45 +00:00
class MqttAuthController extends Controller
{
2023-01-10 13:42:27 +00:00
public function authentication(Request $request): Response
2022-11-27 06:40:45 +00:00
{
2023-01-19 16:06:38 +00:00
$client_id = explode('.', $request->input('client_id'));
2022-11-27 06:40:45 +00:00
2023-01-19 16:06:38 +00:00
$username = $request->input('username');
2022-11-27 06:40:45 +00:00
$usernames = explode('.', $username);
2023-01-19 16:06:38 +00:00
$password = $request->input('password');
2022-11-27 06:40:45 +00:00
$module_id = $usernames[0] ?? null;
$device_id = $usernames[1] ?? null;
2023-01-10 13:42:27 +00:00
$module = (new Module)->where('id', $module_id)->first();
2022-11-27 06:40:45 +00:00
if (!$module) {
return $this->ignore();
}
2023-01-19 16:06:38 +00:00
if ($client_id[0] !== $module->id) {
return $this->ignore();
}
2022-11-27 06:40:45 +00:00
// 如果没有设置 device_id那么就是模块自己的连接
if (!$device_id) {
// 让 api_token 可见
$module->makeVisible('api_token');
// 比较 api_token
if ($module->api_token == $password) {
return $this->allow();
} else {
return $this->deny();
}
} else {
2023-01-19 16:06:38 +00:00
// 如果设置了 device_id那么就是设备的连接此时我们得联系模块让模块去验证设备。
2023-01-19 16:55:05 +00:00
// 设备必须有两段 ID
if (count($client_id) < 2) {
return $this->ignore();
}
2022-11-27 06:40:45 +00:00
$response = $module->baseRequest('post', 'mqtt/authentication', [
2023-01-19 16:06:38 +00:00
'client_id' => $client_id[1],
2022-11-27 06:40:45 +00:00
'device_id' => $device_id,
'password' => $password,
]);
if ($response['status'] === 200) {
return $this->allow();
} else {
return $this->deny();
}
}
}
2023-01-10 13:42:27 +00:00
private function ignore(): Response
2022-12-27 16:25:22 +00:00
{
return response([
'result' => 'ignore',
], 200);
}
2023-01-10 13:42:27 +00:00
private function allow(): Response
2022-12-27 16:25:22 +00:00
{
return response([
'result' => 'allow',
'is_superuser' => false,
], 200);
}
2023-01-10 13:42:27 +00:00
private function deny(): Response
2022-12-27 16:25:22 +00:00
{
return response([
'result' => 'deny',
], 200);
}
2023-01-10 13:42:27 +00:00
public function authorization(Request $request): Response
2022-11-27 06:40:45 +00:00
{
// 禁止订阅保留的
if ($request->input('topic') == '$SYS/#') {
return $this->deny();
}
2023-01-19 16:06:38 +00:00
$client_id = explode('.', $request->input('client_id'));
if (count($client_id) < 2) {
return $this->deny();
}
2022-11-27 06:40:45 +00:00
$action = $request->input('action');
2023-01-19 16:06:38 +00:00
2022-11-27 06:40:45 +00:00
$username = $request->input('username');
$topic = $request->input('topic');
2022-11-27 07:51:58 +00:00
if ($topic === '#') {
return $this->deny();
}
2022-11-27 06:40:45 +00:00
// 使用 / 分割 topic
$topics = explode('/', $topic);
$usernames = explode('.', $username);
$module_id = $usernames[0] ?? null;
$device_id = $usernames[1] ?? null;
2023-01-10 13:42:27 +00:00
$module = (new Module)->where('id', $module_id)->first();
2022-11-27 06:40:45 +00:00
if (!$module) {
// 不属于我们管理,跳过。
return $this->ignore();
}
// 设备只能在自己的模块下发布消息
if ($action == 'publish') {
if ($topics[0] !== $module_id) {
2022-12-03 06:05:37 +00:00
// 但是,在拒绝之前,应该检查一下,是否有允许的模块
2023-01-10 13:42:27 +00:00
$allow = (new ModuleAllow)->where('module_id', $topics[0])->where('allowed_module_id', $module_id)->exists();
2022-12-03 06:05:37 +00:00
if (!$allow) {
return $this->deny();
}
2022-11-27 06:40:45 +00:00
}
}
2022-12-03 04:51:28 +00:00
2022-11-27 06:40:45 +00:00
if (count($usernames) === 1) {
// 是模块自己的连接
return $this->allow();
}
2022-12-03 04:51:28 +00:00
// 其他情况,让模块去验证
2022-11-27 06:40:45 +00:00
// 联系模块,让模块去验证设备授权。
$response = $module->baseRequest('post', 'mqtt/authorization', [
2023-01-19 16:06:38 +00:00
'client_id' => $client_id[1],
2022-11-27 06:40:45 +00:00
'device_id' => $device_id,
'type' => $action,
'topic' => $topic,
]);
if ($response['status'] === 200) {
return $this->allow();
} else {
return $this->deny();
}
}
}