138 lines
3.7 KiB
PHP
138 lines
3.7 KiB
PHP
|
|
<?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' => '/',
|
|||
|
|
'domain' => $domain,
|
|||
|
|
'secure' => function_exists('cloak_request_is_https') && cloak_request_is_https(),
|
|||
|
|
'httponly' => true,
|
|||
|
|
'samesite' => 'Lax',
|
|||
|
|
]);
|
|||
|
|
} elseif ($domain !== '') {
|
|||
|
|
session_set_cookie_params(
|
|||
|
|
0,
|
|||
|
|
'/',
|
|||
|
|
$domain,
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$requestHost = (string) ($_SERVER['HTTP_HOST'] ?? '');
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
$host = strtolower(trim($host));
|
|||
|
|
if ($host === '') {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (function_exists('cloak_fingerprint_cookie_domain')) {
|
|||
|
|
$cookieDomain = ltrim(cloak_fingerprint_cookie_domain(), '.');
|
|||
|
|
if ($cookieDomain !== '' && self::hostMatchesSuffix($host, $cookieDomain)) {
|
|||
|
|
return $cookieDomain;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$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;
|
|||
|
|
}
|
|||
|
|
}
|