From 1cf94e215b846228c33f8a7943df5f84a6540351 Mon Sep 17 00:00:00 2001 From: "iVampireSP.com" Date: Sun, 27 Nov 2022 14:40:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E7=89=A9=E8=81=94?= =?UTF-8?q?=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Application/AuthController.php | 11 -- .../Application/MqttAuthController.php | 146 ++++++++++++++++++ app/Models/Module.php | 29 ++-- routes/applications.php | 7 +- 4 files changed, 169 insertions(+), 24 deletions(-) delete mode 100644 app/Http/Controllers/Application/AuthController.php create mode 100644 app/Http/Controllers/Application/MqttAuthController.php diff --git a/app/Http/Controllers/Application/AuthController.php b/app/Http/Controllers/Application/AuthController.php deleted file mode 100644 index d1a3d25..0000000 --- a/app/Http/Controllers/Application/AuthController.php +++ /dev/null @@ -1,11 +0,0 @@ -input('client_id'); + $username = $request->input('username'); + $password = $request->input('password'); + + + // 分割 username + $usernames = explode('.', $username); + + $module_id = $usernames[0] ?? null; + $device_id = $usernames[1] ?? null; + + + $module = Module::where('id', $module_id)->first(); + + if (!$module) { + return $this->ignore(); + } + + // 如果没有设置 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 { + // 如果设置了 device_id,那么就是设备的连接 + + // 此时,我们得联系模块,让模块去验证设备。 + + $response = $module->baseRequest('post', 'mqtt/authentication', [ + 'client_id' => $client_id, + 'device_id' => $device_id, + 'password' => $password, + ]); + + if ($response['status'] === 200) { + return $this->allow(); + } else { + return $this->deny(); + } + + } + } + + public function authorization(Request $request) + { + // 禁止订阅保留的 + if ($request->input('topic') == '$SYS/#') { + return $this->deny(); + } + + $action = $request->input('action'); + $client_id = $request->input('client_id'); + $username = $request->input('username'); + $topic = $request->input('topic'); + + // 使用 / 分割 topic + $topics = explode('/', $topic); + + $usernames = explode('.', $username); + + $module_id = $usernames[0] ?? null; + $device_id = $usernames[1] ?? null; + + $module = Module::where('id', $module_id)->first(); + + if (!$module) { + // 不属于我们管理,跳过。 + // Log::debug('不属于我们管理,跳过。'); + return $this->ignore(); + } + + + // 设备只能在自己的模块下发布消息 + if ($action == 'publish') { + if ($topics[0] !== $module_id) { + // Log::debug('设备只能在自己的模块下发布消息'); + return $this->deny(); + } + } + + if (count($usernames) === 1) { + // 是模块自己的连接 + return $this->allow(); + } + + // Log::debug('联系模块。'); + + // 联系模块,让模块去验证设备授权。 + $response = $module->baseRequest('post', 'mqtt/authorization', [ + 'client_id' => $client_id, + 'device_id' => $device_id, + 'type' => $action, + 'topic' => $topic, + ]); + + if ($response['status'] === 200) { + return $this->allow(); + } else { + return $this->deny(); + } + } + + private function deny() + { + return response([ + 'result' => 'deny', + ], 200); + } + + private function ignore() + { + return response([ + 'result' => 'ignore', + ], 200); + } + + private function allow() + { + return response([ + 'result' => 'allow', + 'is_superuser' => false, + ], 200); + } +} diff --git a/app/Models/Module.php b/app/Models/Module.php index 96becb2..058353b 100644 --- a/app/Models/Module.php +++ b/app/Models/Module.php @@ -4,8 +4,8 @@ use GeneaLabs\LaravelModelCaching\Traits\Cachable; use GuzzleHttp\Exception\ConnectException; -use Illuminate\Http\Client\Response; use Illuminate\Foundation\Auth\User as Authenticatable; +use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; @@ -102,22 +102,27 @@ public function remote($func, $requests): array public function request($method, $path, $requests): array { - $user = auth()->user(); + return $this->baseRequest($method, "functions/{$path}", $requests); + } + + public function baseRequest($method, $path, $requests): array + { + $user = auth('sanctum')->user(); $http = Http::module($this->api_token, $this->url); - $http->withHeaders([ - 'X-User-id' => $user->id, - ]); - - $requests['user_id'] = $user->id; - - if ($method == 'post') { - // add user to requests - $requests['user'] = $user; + if ($user) { + $http->withHeaders([ + 'X-User-id' => $user->id, + ]); + $requests['user_id'] = $user->id; + if ($method == 'post') { + // add user to requests + $requests['user'] = $user; + } } - $response = $http->{$method}("functions/{$path}", $requests); + $response = $http->{$method}($path, $requests); return $this->getResponse($response); } diff --git a/routes/applications.php b/routes/applications.php index 8b6e264..a317bea 100644 --- a/routes/applications.php +++ b/routes/applications.php @@ -1,3 +1,8 @@ name('mqtt.authentication'); +// 授权 +Route::post('mqtt/authorization', [MqttAuthController::class, 'authorization'])->name('mqtt.authorization');