fix(core): harden settlement and wallet integration
This commit is contained in:
71
app/Services/Player/NativeJwtSecretGuard.php
Normal file
71
app/Services/Player/NativeJwtSecretGuard.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Player;
|
||||
|
||||
use Throwable;
|
||||
use App\Models\AdminSite;
|
||||
use App\Lottery\ErrorCode;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use App\Exceptions\PlayerAuthenticationException;
|
||||
|
||||
final class NativeJwtSecretGuard
|
||||
{
|
||||
public function validatedSecret(): string
|
||||
{
|
||||
$secret = config('lottery.player_auth.native.secret');
|
||||
if (! is_string($secret) || $secret === '') {
|
||||
$this->rejectConfiguration('原生登录未配置');
|
||||
}
|
||||
|
||||
$legacySsoSecret = config('lottery.main_site.sso_jwt_secret');
|
||||
if ($this->matches($secret, $legacySsoSecret)) {
|
||||
$this->rejectConfiguration('原生登录密钥不得与 legacy SSO 密钥相同');
|
||||
}
|
||||
|
||||
if ($this->matchesStoredSiteSsoSecret($secret)) {
|
||||
$this->rejectConfiguration('原生登录密钥不得与任何站点保存的 SSO 密钥相同');
|
||||
}
|
||||
|
||||
return $secret;
|
||||
}
|
||||
|
||||
private function matchesStoredSiteSsoSecret(string $nativeSecret): bool
|
||||
{
|
||||
try {
|
||||
if (! Schema::hasTable('admin_sites')
|
||||
|| ! Schema::hasColumn('admin_sites', 'sso_jwt_secret_encrypted')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sites = AdminSite::query()
|
||||
->whereNotNull('sso_jwt_secret_encrypted')
|
||||
->get(['sso_jwt_secret_encrypted']);
|
||||
} catch (Throwable) {
|
||||
$this->rejectConfiguration('无法检查原生登录密钥是否与站点 SSO 密钥冲突');
|
||||
}
|
||||
|
||||
foreach ($sites as $site) {
|
||||
if ($this->matches($nativeSecret, $site->decryptedSsoJwtSecret())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function matches(string $nativeSecret, mixed $candidate): bool
|
||||
{
|
||||
return is_string($candidate)
|
||||
&& $candidate !== ''
|
||||
&& hash_equals($nativeSecret, $candidate);
|
||||
}
|
||||
|
||||
private function rejectConfiguration(string $message): never
|
||||
{
|
||||
throw new PlayerAuthenticationException(
|
||||
$message,
|
||||
ErrorCode::PlayerSsoSecretNotConfigured->value,
|
||||
503,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user