初始化本地仓库
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: https://madong.tech
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: http://www.madong.tech
|
||||
*/
|
||||
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* 跨域中间件
|
||||
*
|
||||
* @author Mr.April
|
||||
* @since 1.0
|
||||
*/
|
||||
class AllowCrossOriginMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
|
||||
$response->withHeaders([
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With,Origin',
|
||||
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS,PATCH',
|
||||
]);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use core\tool\ApiEncryptService;
|
||||
use core\tool\Json;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
class ApiEncryptMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function __construct(protected ApiEncryptService $service)
|
||||
{
|
||||
}
|
||||
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
if ($this->service->isEnabled()
|
||||
&& !$this->service->shouldExcludePath($request->path())
|
||||
&& $this->service->isEncryptedRequest($request)) {
|
||||
try {
|
||||
$data = $this->service->decryptRequest($request);
|
||||
$this->service->applyDecryptedPayload($request, $data);
|
||||
} catch (\Throwable $exception) {
|
||||
return Json::fail($exception->getMessage(), null, 400);
|
||||
}
|
||||
}
|
||||
|
||||
$response = $handler($request);
|
||||
|
||||
if (!$response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!$this->service->shouldEncrypt($request)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!$this->service->hasActiveSessionKey()) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!$this->service->isJsonResponse($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
try {
|
||||
$body = $response->rawBody();
|
||||
if ($body === '') {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$encryptedBody = $this->service->encryptResponseBody($body);
|
||||
return $response->withBody($encryptedBody)->withHeader('Content-Type', 'application/json');
|
||||
} catch (\Throwable $exception) {
|
||||
return Json::fail($exception->getMessage(), null, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: https://madong.tech
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* 安装检查中间件
|
||||
*
|
||||
* @author Mr.April
|
||||
* @since 1.0
|
||||
*/
|
||||
class CheckInstallMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
// 检查是否已安装
|
||||
$lockFileExists = file_exists(base_path() . '/install.lock');
|
||||
if (!$lockFileExists) {
|
||||
// 如果未安装,重定向到安装页面
|
||||
return redirect('/install');
|
||||
}
|
||||
// 如果已安装,继续处理请求
|
||||
return $handler($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: http://www.madong.tech
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use app\adminapi\middleware\helper\SseHelper;
|
||||
use core\jwt\JwtToken;
|
||||
use core\tool\Json;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* 演示限制操作-实际生产移除
|
||||
*
|
||||
* @author Mr.April
|
||||
* @since 1.0
|
||||
*/
|
||||
class DemoEnvRouteRestrictionMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
// 不允许操作的路由
|
||||
$restrictedRoutes = [
|
||||
'/adminapi/system/user',
|
||||
'/adminapi/system/user/\d+',
|
||||
'/adminapi/system/menu',
|
||||
'/adminapi/system/menu/\d+',
|
||||
'/adminapi/system/role',
|
||||
'/adminapi/system/role/\d+',
|
||||
'/adminapi/system/dept/',
|
||||
'/adminapi/system/dept/\d+',
|
||||
'/adminapi/system/post',
|
||||
'/adminapi/system/post/\d+',
|
||||
'/adminapi/system/dict',
|
||||
'/adminapi/system/dict/\d+',
|
||||
'/adminapi/system/dict-item',
|
||||
'/adminapi/system/dict-item/\d+',
|
||||
'/adminapi/system/recycle-bin',
|
||||
'/adminapi/system/recycle-bin/\d+',
|
||||
'/adminapi/system/config',
|
||||
'/adminapi/dev/crontab',
|
||||
'/adminapi/dev/crontab/\d+',
|
||||
'/adminapi/platform/db',
|
||||
'/adminapi/platform/tenant-subscription',
|
||||
'/adminapi/platform/tenant-subscription/\d+',
|
||||
'/adminapi/platform/tenant-member',
|
||||
'/adminapi/platform/tenant-member/\d+',
|
||||
'/adminapi/generator/\d+/deploy',
|
||||
//offline插件限制路由
|
||||
'/adminapi/market/category',
|
||||
'/adminapi/market/category/\d+',
|
||||
'/adminapi/market/apps',
|
||||
'/adminapi/market/apps/\d+',
|
||||
'/adminapi/market/apps/publish-version',
|
||||
'/adminapi/docs',
|
||||
'/adminapi/docs/\d+',
|
||||
'/adminapi/doc/content',
|
||||
'/adminapi/doc/content/\d+',
|
||||
'/adminapi/ask/answer',
|
||||
'/adminapi/ask/answer/\d+',
|
||||
'/adminapi/ask/category',
|
||||
'/adminapi/ask/category/\d+',
|
||||
'/adminapi/ask/question',
|
||||
'/adminapi/ask/question/\d+',
|
||||
'/adminapi/ask/tag',
|
||||
'/adminapi/ask/tag/\d+',
|
||||
'/adminapi/generator/code/\d+/deploy',
|
||||
//插件服务
|
||||
'/adminapi/plugin/install',
|
||||
'/adminapi/plugin',
|
||||
'/adminapi/plugin/uninstall',
|
||||
//WEB终端服务
|
||||
'/adminapi/terminal',
|
||||
'/adminapi/terminal/\d+',
|
||||
];
|
||||
$currentPath = $request->path();
|
||||
|
||||
$method = $request->method();
|
||||
|
||||
// 检查当前路径是否在限制的路由中
|
||||
foreach ($restrictedRoutes as $pattern) {
|
||||
if (preg_match("#^$pattern$#", $currentPath)) {
|
||||
// 检查是否为 root 用户
|
||||
if ($this->isRootUser()) {
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
// 检查是否为SSE请求
|
||||
$isSseRequest = SseHelper::isSseRequest($request);
|
||||
|
||||
// SSE请求需要单独处理
|
||||
if ($isSseRequest) {
|
||||
return SseHelper::sendSseErrorViaConnection($request, '演示环境,不支持当前操作');
|
||||
}
|
||||
|
||||
// 非SSE的写操作(PUT, POST, DELETE)也限制
|
||||
if (in_array(strtoupper($method), ['PUT', 'POST', 'DELETE'])) {
|
||||
return Json::fail('演示环境,不支持当前操作');
|
||||
}
|
||||
|
||||
// 对于GET请求,如果不是SSE,默认允许(演示环境可能允许查看)
|
||||
}
|
||||
}
|
||||
|
||||
// 继续处理请求
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为 root 用户
|
||||
*/
|
||||
private function isRootUser(): bool
|
||||
{
|
||||
$payload = (new JwtToken())->getPayloadFromRequest();
|
||||
$extra = is_array($payload) ? ($payload['extra'] ?? null) : (is_object($payload) ? ($payload->extra ?? null) : null);
|
||||
|
||||
if (!empty($payload['id'])) {
|
||||
return (int)$payload['id'] == -1;
|
||||
}
|
||||
if (is_object($extra)) {
|
||||
return ($extra->user_name ?? '') === 'root';
|
||||
}
|
||||
|
||||
if (is_array($extra)) {
|
||||
return ($extra['user_name'] ?? '') === 'root';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* 文件访问权限中间件
|
||||
* 用于控制上传文件的访问权限
|
||||
*/
|
||||
class FileAccessMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
// $path = $request->path;
|
||||
// $path = str_replace('/upload/', '', $path);
|
||||
//
|
||||
// // 公开文件类型,无需权限验证
|
||||
// $publicExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'ico', 'css', 'js', 'woff', 'woff2', 'ttf', 'eot'];
|
||||
//
|
||||
// $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
//
|
||||
// if (in_array($extension, $publicExtensions)) {
|
||||
// return $handler($request);
|
||||
// }
|
||||
|
||||
// // 私密文件需要身份验证
|
||||
// if (!$request->user) {
|
||||
// return json([
|
||||
// 'code' => 401,
|
||||
// 'msg' => '请先登录',
|
||||
// 'data' => null
|
||||
// ], 401);
|
||||
// }
|
||||
//
|
||||
// // 根据文件路径进行权限控制
|
||||
// // 示例:某些敏感文件只能管理员访问
|
||||
// if (str_starts_with($path, 'private/')) {
|
||||
// $user = $request->user;
|
||||
// if (!isset($user['roles']) || !in_array('R_SUPER', $user['roles'] ?? [])) {
|
||||
// return json([
|
||||
// 'code' => 403,
|
||||
// 'msg' => '无权访问',
|
||||
// 'data' => null
|
||||
// ], 403);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 用户个人文件访问控制
|
||||
// // 例如:/uploads/avatar/user_123.png 只有 user_123 或管理员可以访问
|
||||
// if (preg_match('/^(avatar|document|private)\/(\d+)_/', $path, $matches)) {
|
||||
// $userId = $matches[2];
|
||||
// $user = $request->user;
|
||||
//
|
||||
// // 管理员可访问所有文件
|
||||
// if (isset($user['roles']) && in_array('R_SUPER', $user['roles'] ?? [])) {
|
||||
// return $handler($request);
|
||||
// }
|
||||
//
|
||||
// // 普通用户只能访问自己的文件
|
||||
// if ($user['id'] != $userId) {
|
||||
// return json([
|
||||
// 'code' => 403,
|
||||
// 'msg' => '无权访问此文件',
|
||||
// 'data' => null
|
||||
// ], 403);
|
||||
// }
|
||||
// }
|
||||
|
||||
return $handler($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: https://madong.tech
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* @author Mr.April
|
||||
* @since 1.0
|
||||
*/
|
||||
class Lang implements MiddlewareInterface
|
||||
{
|
||||
private const LANG_MAP = [
|
||||
'en' => ['en', 'en_US', 'en_AU', 'en_CA', 'en_GB', 'en-US', 'en-AU', 'en-CA', 'en-GB'],
|
||||
'zh_CN' => ['zh_CN', 'zh_HK', 'zh_TW', 'zh_SG', 'zh-CN', 'zh-HK', 'zh-TW', 'zh-SG'],
|
||||
];
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$lang = $request->header('Accept-Language', config('app.lang'));
|
||||
$langPrefix = substr($lang, 0, 2);
|
||||
if (array_key_exists($langPrefix, self::LANG_MAP)) {
|
||||
$locale = self::LANG_MAP[$langPrefix][0]; // 默认选择第一个匹配的语言
|
||||
} else {
|
||||
$locale = config('app.lang');
|
||||
}
|
||||
// 设置会话中的语言
|
||||
|
||||
session('lang', $locale);
|
||||
locale($locale);
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: http://www.madong.tech
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use app\service\admin\gateway\RetaLimiterService;
|
||||
use app\service\admin\gateway\RetaRestrictionsService;
|
||||
use core\cache\CacheService;
|
||||
use support\Container;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\RateLimiter\Limiter;
|
||||
use Webman\RateLimiter\RateLimitException;
|
||||
|
||||
/**
|
||||
* 限访限流中间件
|
||||
*
|
||||
* 功能特性:
|
||||
* 1. IP-based 黑名单访问限制
|
||||
* 2. 基于路径的限流控制
|
||||
* 3. 支持多种匹配模式:精确匹配、通配符匹配、正则表达式匹配
|
||||
* 4. 支持多种限流类型:IP限流、用户限流
|
||||
* 5. 配置化限流规则(作为数据库规则的 fallback)
|
||||
* 6. 缓存优化(1小时缓存过期)
|
||||
*
|
||||
* 配置示例(config/rate_limiter.php):
|
||||
* [
|
||||
* [
|
||||
* 'path' => '/api/*',
|
||||
* 'methods' => '*',
|
||||
* 'match_type' => 'wildcard',
|
||||
* 'limit_type' => 'ip',
|
||||
* 'limit_value' => 100,
|
||||
* 'ttl' => 60,
|
||||
* 'message' => '请求过于频繁,请稍后再试'
|
||||
* ]
|
||||
* ]
|
||||
*
|
||||
* @author Mr.April
|
||||
* @since 1.0
|
||||
*/
|
||||
class RateLimiterMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* process
|
||||
*
|
||||
* @param \Webman\Http\Request $request
|
||||
* @param callable $handler
|
||||
*
|
||||
* @return \Webman\Http\Response
|
||||
*/
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$path = $request->path();
|
||||
//跳过对应的安装接口
|
||||
if (in_array($path, ['/'])) {
|
||||
return $handler($request);
|
||||
}
|
||||
$ip = $request->getRealIp();
|
||||
$method = $request->method();
|
||||
$userId = $this->getUserId($request);
|
||||
|
||||
//限访处理
|
||||
$rateRestrictions = $this->getRateRestrictions($ip, $path, $method);
|
||||
if (!empty($rateRestrictions)) {
|
||||
throw new RateLimitException($rateRestrictions['message'] ?? '拒绝访问');
|
||||
}
|
||||
|
||||
$rateRule = $this->getRateLimit($path, $method);
|
||||
//限流处理
|
||||
if (!empty($rateRule)) {
|
||||
$key = $this->generateLimitKey($rateRule, $ip, $userId, $method, $path);
|
||||
Limiter::check(md5($key), $rateRule['limit_value'], $rateRule['ttl'] ?? 1, $rateRule['message']);
|
||||
//可以实现更多自定义的限流规则
|
||||
}
|
||||
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户ID
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
protected function getUserId(Request $request): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成限流键
|
||||
*
|
||||
* @param array $rule
|
||||
* @param string $ip
|
||||
* @param int|null $userId
|
||||
* @param string $method
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateLimitKey(array $rule, string $ip, ?int $userId, string $method, string $path): string
|
||||
{
|
||||
$limitType = $rule['limit_type'] ?? 'ip';
|
||||
switch ($limitType) {
|
||||
case 'user':
|
||||
if ($userId) {
|
||||
return $userId . $method . $path;
|
||||
}
|
||||
// 如果没有用户ID,回退到IP
|
||||
return $ip . $method . $path;
|
||||
case 'ip':
|
||||
default:
|
||||
return $ip . $method . $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匹配的限流规则(缓存优先)
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $methods
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getRateLimit(string $path, string $methods = 'GET'): ?array
|
||||
{
|
||||
$cache = Container::make(CacheService::class);
|
||||
$service = Container::make(RetaLimiterService::class);
|
||||
$rules = $cache->remember(RetaLimiterService::CACHE_KEY, function () use ($service) {
|
||||
return $service->selectList(['enabled' => 1], '*', 0, 0, 'priority desc')->toArray();
|
||||
});
|
||||
if (empty($rules)) {
|
||||
return $this->getConfigBasedLimit($path, $methods);
|
||||
}
|
||||
foreach ($rules as $rule) {
|
||||
if ($this->matchPath($rule['path'], $path, $rule['match_type'] ?? 'exact') &&
|
||||
($rule['methods'] === '*' || $rule['methods'] === $methods)) {
|
||||
return $rule;
|
||||
}
|
||||
}
|
||||
return $this->getConfigBasedLimit($path, $methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置-based限流规则
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $methods
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getConfigBasedLimit(string $path, string $methods = 'GET'): ?array
|
||||
{
|
||||
$config = config('rate_limiter', []);
|
||||
if (empty($config)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($config as $rule) {
|
||||
if (isset($rule['path'], $rule['limit_value']) &&
|
||||
$this->matchPath($rule['path'], $path, $rule['match_type'] ?? 'exact') &&
|
||||
(($rule['methods'] ?? '*') === '*' || ($rule['methods'] ?? 'GET') === $methods)) {
|
||||
return $rule;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取限访规则
|
||||
*
|
||||
* @param string $ip
|
||||
* @param string $path
|
||||
* @param string $methods
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getRateRestrictions(string $ip, string $path, string $methods = 'GET'): ?array
|
||||
{
|
||||
$currentTime = time();
|
||||
$cache = Container::make(CacheService::class);
|
||||
$service = Container::make(RetaRestrictionsService::class);
|
||||
$rules = $cache->remember(RetaRestrictionsService::CACHE_KEY,function () use ($service) {
|
||||
return $service->selectList(['enabled' => 1], '*', 0, 0, 'priority desc')->toArray();
|
||||
});
|
||||
|
||||
if (empty($rules)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
// IP匹配
|
||||
if (!empty($rule['ip']) && $rule['ip'] !== $ip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 路径匹配
|
||||
if (!$this->matchPath($rule['path'], $path, $rule['match_type'] ?? 'exact')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 方法匹配
|
||||
if ($rule['methods'] !== '*' && $rule['methods'] !== $methods) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hasStartTime = isset($rule['start_time']) && $rule['start_time'] > 0;
|
||||
$hasEndTime = isset($rule['end_time']) && $rule['end_time'] > 0;
|
||||
|
||||
// 规则未生效(未来时间)或已过期
|
||||
if (($hasStartTime && $currentTime < $rule['start_time']) ||
|
||||
($hasEndTime && $currentTime > $rule['end_time'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $rule;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 路径匹配
|
||||
*
|
||||
* @param string $rulePath
|
||||
* @param string $requestPath
|
||||
* @param string $matchType
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function matchPath(string $rulePath, string $requestPath, string $matchType = 'exact'): bool
|
||||
{
|
||||
switch ($matchType) {
|
||||
case 'exact':
|
||||
return $rulePath === $requestPath;
|
||||
case 'wildcard':
|
||||
$pattern = str_replace('*', '.*', preg_quote($rulePath, '/'));
|
||||
return preg_match('/^' . $pattern . '$/', $requestPath) === 1;
|
||||
case 'regex':
|
||||
return preg_match('/^' . $rulePath . '$/', $requestPath) === 1;
|
||||
default:
|
||||
return $rulePath === $requestPath;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* Class StaticFile
|
||||
* @package app\middleware
|
||||
*/
|
||||
class StaticFile implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
if (str_contains($request->path(), '/.')) {
|
||||
return response('<h1>403 forbidden</h1>', 403);
|
||||
}
|
||||
/** @var Response $response */
|
||||
$response = $handler($request);
|
||||
// Add cross domain HTTP header
|
||||
/*$response->withHeaders([
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
]);*/
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user