CaiWuXiTong/app/Http/Middleware/ValidateSignature.php
WuYongJie 9595267ee7
Some checks failed
Tests / PHP 8.1 (push) Has been cancelled
Tests / PHP 8.2 (push) Has been cancelled
Tests / PHP 8.3 (push) Has been cancelled
chore: 导入 Akaunting 初始源码与团队协作规则
2026-07-20 18:20:25 +08:00

87 lines
2.4 KiB
PHP

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Routing\Exceptions\InvalidSignatureException;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
class ValidateSignature
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*
* @throws \Illuminate\Routing\Exceptions\InvalidSignatureException
*/
public function handle($request, Closure $next)
{
if ($this->hasValidSignature($request)) {
return $next($request);
}
throw new InvalidSignatureException;
}
/**
* Determine if the given request has a valid signature.
*
* @param \Illuminate\Http\Request $request
* @param bool $absolute
* @return bool
*/
public function hasValidSignature(Request $request, $absolute = true)
{
return $this->hasCorrectSignature($request, $absolute)
&& $this->signatureHasNotExpired($request);
}
/**
* Determine if the signature from the given request matches the URL.
*
* @param \Illuminate\Http\Request $request
* @param bool $absolute
* @return bool
*/
public function hasCorrectSignature(Request $request, $absolute = true)
{
$url = $absolute ? $request->url() : '/' . $request->path();
$original = rtrim($url . '?' . Arr::query(
Arr::only($request->query(), ['company_id'])
) . Arr::query(
Arr::only($request->query(), ['expires'])
), '?');
$signature = hash_hmac('sha256', $original, call_user_func(function () {
return config('app.key');
}));
return hash_equals($signature, (string) $request->query('signature', ''));
}
/**
* Determine if the expires timestamp from the given request is not from the past.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
public function signatureHasNotExpired(Request $request)
{
$expires = $request->query('expires');
// No expiry parameter: URL is permanently valid (intentional design for shared invoice links)
if ($expires === null) {
return true;
}
// Cast to int so expires=0 (epoch/falsy) is correctly treated as a past timestamp
return Carbon::now()->getTimestamp() <= (int) $expires;
}
}