2026-06-15 22:42:59 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Session 与 f_check 跨域(CORS)辅助
|
|
|
|
|
|
*/
|
|
|
|
|
|
class CloakSession
|
|
|
|
|
|
{
|
|
|
|
|
|
public static function start()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$domain = function_exists('cloak_fingerprint_cookie_domain')
|
|
|
|
|
|
? cloak_fingerprint_cookie_domain()
|
|
|
|
|
|
: '';
|
|
|
|
|
|
|
|
|
|
|
|
if ($domain !== '' && PHP_VERSION_ID >= 70300) {
|
|
|
|
|
|
session_set_cookie_params([
|
|
|
|
|
|
'lifetime' => 0,
|
|
|
|
|
|
'path' => '/',
|
2026-06-16 04:58:56 +08:00
|
|
|
|
'domain' => ltrim($domain, '.'),
|
2026-06-15 22:42:59 +08:00
|
|
|
|
'secure' => function_exists('cloak_request_is_https') && cloak_request_is_https(),
|
|
|
|
|
|
'httponly' => true,
|
|
|
|
|
|
'samesite' => 'Lax',
|
|
|
|
|
|
]);
|
|
|
|
|
|
} elseif ($domain !== '') {
|
|
|
|
|
|
session_set_cookie_params(
|
|
|
|
|
|
0,
|
|
|
|
|
|
'/',
|
2026-06-16 04:58:56 +08:00
|
|
|
|
ltrim($domain, '.'),
|
2026-06-15 22:42:59 +08:00
|
|
|
|
function_exists('cloak_request_is_https') && cloak_request_is_https(),
|
|
|
|
|
|
true
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
session_start();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class CloakFcheckCors
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* OPTIONS 预检:在 session/bootstrap 之前调用。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function handlePreflight()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'OPTIONS') {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self::emitHeaders();
|
|
|
|
|
|
http_response_code(204);
|
|
|
|
|
|
exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 响应头(含 AJAX 跨子域 withCredentials)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function emitHeaders()
|
|
|
|
|
|
{
|
|
|
|
|
|
$origin = (string) ($_SERVER['HTTP_ORIGIN'] ?? '');
|
|
|
|
|
|
if ($origin !== '' && self::isAllowedOrigin($origin)) {
|
|
|
|
|
|
header('Access-Control-Allow-Origin: ' . $origin);
|
|
|
|
|
|
header('Access-Control-Allow-Credentials: true');
|
|
|
|
|
|
header('Vary: Origin');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
header('Access-Control-Allow-Methods: POST, OPTIONS');
|
|
|
|
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
|
|
|
|
header('Access-Control-Max-Age: 86400');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param string $origin
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static function isAllowedOrigin($origin)
|
|
|
|
|
|
{
|
|
|
|
|
|
$originHost = parse_url($origin, PHP_URL_HOST);
|
|
|
|
|
|
if (!is_string($originHost) || $originHost === '') {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-16 04:58:56 +08:00
|
|
|
|
$requestHost = function_exists('cloak_normalize_request_host')
|
|
|
|
|
|
? cloak_normalize_request_host($_SERVER['HTTP_HOST'] ?? '')
|
|
|
|
|
|
: strtolower(trim((string) ($_SERVER['HTTP_HOST'] ?? '')));
|
|
|
|
|
|
$originHost = function_exists('cloak_normalize_request_host')
|
|
|
|
|
|
? cloak_normalize_request_host($originHost)
|
|
|
|
|
|
: strtolower(trim($originHost));
|
|
|
|
|
|
|
2026-06-15 22:42:59 +08:00
|
|
|
|
if ($requestHost !== '' && strcasecmp($originHost, $requestHost) === 0) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$suffix = self::registrableSuffix($requestHost);
|
|
|
|
|
|
if ($suffix === '') {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$originSuffix = self::registrableSuffix($originHost);
|
|
|
|
|
|
if ($originSuffix === '' || strcasecmp($originSuffix, $suffix) !== 0) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return self::hostMatchesSuffix($originHost, $suffix);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param string $host
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static function registrableSuffix($host)
|
|
|
|
|
|
{
|
2026-06-16 04:58:56 +08:00
|
|
|
|
if (function_exists('cloak_registrable_domain')) {
|
|
|
|
|
|
return cloak_registrable_domain($host);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-15 22:42:59 +08:00
|
|
|
|
$host = strtolower(trim($host));
|
|
|
|
|
|
if ($host === '') {
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$parts = explode('.', $host);
|
|
|
|
|
|
if (count($parts) < 2) {
|
|
|
|
|
|
return $host;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $parts[count($parts) - 2] . '.' . $parts[count($parts) - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @param string $host
|
|
|
|
|
|
* @param string $suffix
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static function hostMatchesSuffix($host, $suffix)
|
|
|
|
|
|
{
|
|
|
|
|
|
$host = strtolower($host);
|
|
|
|
|
|
$suffix = strtolower($suffix);
|
|
|
|
|
|
|
|
|
|
|
|
return $host === $suffix || substr($host, -strlen('.' . $suffix)) === '.' . $suffix;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|