CaiWuXiTong/app/Http/Middleware/AuthenticateOnceWithDynamicApi.php
15061959991 1adf627c0d feat: 财务系统二次开发 - 营销账户账单功能
- 基础环境:Docker 部署配置,源码挂载实时同步
- 修复:super_admin 权限补全、登录重定向循环
- 开发:店铺营销账户账单 - 抖音账户(15字段汇总账单)
- 开发:店铺营销账户账单 - 淘系支付宝账户(8字段流水账单)
- 开发:店铺营销账户账单 - 拼多多账户(7字段流水账单)
- 业务页面导航集成:config/business_navigation.php + Business\Pages 控制器
- 各平台独立表结构和视图,互不影响
2026-07-21 18:43:52 +08:00

89 lines
3.5 KiB
PHP

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
/**
* AuthenticateOnceWithDynamicApi — Dispatcher
*
* Detects credential type from the Authorization header and delegates
* to the appropriate dedicated middleware:
*
* Authorization: Bearer <token> → AuthenticateOnceWithOAuth::handle()
* Authorization: Basic <base64> → AuthenticateOnceWithBasicAuth::handle()
* (no header) → 401
*
* Auth logic lives in the dedicated classes — extend/fix them independently.
*/
class AuthenticateOnceWithDynamicApi
{
public function __construct(
private readonly AuthenticateOnceWithOAuth $oauthMiddleware,
private readonly AuthenticateOnceWithBasicAuth $basicMiddleware,
) {}
public function handle(Request $request, Closure $next): mixed
{
$shouldLog = (bool) config('oauth.verbose_log', false) || ! app()->environment('production');
// Skip if OAuth module is disabled to avoid unnecessary processing; delegate to Basic Auth directly since it's simpler and more likely to be used without OAuth.
if (! config('oauth.enabled', false)) {
if ($shouldLog) {
Log::debug('OAuth Dispatcher: OAuth disabled, using basic auth', [
'path' => $request->path(),
'method' => $request->method(),
]);
}
return $this->basicMiddleware->handle($request, function (Request $req) use ($next) {
$req->attributes->set('auth_method', 'basic');
return $next($req);
});
}
$authorization = (string) $request->header('Authorization', '');
if ($shouldLog) {
Log::debug('OAuth Dispatcher: Authorization header detected', [
'path' => $request->path(),
'method' => $request->method(),
'authorization_type' => preg_match('/^\s*(\w+)\s+/i', $authorization, $m) === 1 ? strtolower($m[1]) : 'none',
'has_header' => $authorization !== '' ? 'yes' : 'no',
]);
}
// ── Bearer token → delegate to OAuth middleware ───────────────────────
if (preg_match('/^\s*Bearer\s+/i', $authorization) === 1) {
return $this->oauthMiddleware->handle($request, function (Request $req) use ($next) {
$req->attributes->set('auth_method', 'oauth');
return $next($req);
});
}
// ── Basic credentials → delegate to Basic Auth middleware ─────────────
if (preg_match('/^\s*Basic\s+/i', $authorization) === 1) {
return $this->basicMiddleware->handle($request, function (Request $req) use ($next) {
$req->attributes->set('auth_method', 'basic');
return $next($req);
});
}
// ── No Authorization header → 401 ─────────────────────────────────────
$realm = config('app.name', 'Akaunting');
return response()->json([
'message' => 'Unauthenticated.',
'error' => 'invalid_client',
'error_description' => 'Authentication required. Use an OAuth Bearer token or HTTP Basic credentials.',
], 401, [
'WWW-Authenticate' => sprintf('Bearer realm="%s", Basic realm="%s"', $realm, $realm),
]);
}
}