1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-30 06:11:38 +08:00

优化异常和错误

This commit is contained in:
xiaochong0302 2020-04-11 18:55:26 +08:00
parent d1c9dfa46f
commit ab73ac4055
18 changed files with 90 additions and 156 deletions

View File

@ -0,0 +1,8 @@
<?php
namespace App\Exceptions;
class ServiceUnavailable extends \Exception
{
}

View File

@ -22,15 +22,12 @@ class Controller extends \Phalcon\Mvc\Controller
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
if ($this->isNotSafeRequest()) {
if (!$this->checkHttpReferer() || !$this->checkCsrfToken()) {
$dispatcher->forward([
'controller' => 'public',
'action' => 'robot',
]);
return false;
}
$this->checkHttpReferer();
$this->checkCsrfToken();
}
$this->checkRateLimit();
$this->authUser = $this->getAuthUser();
if (!$this->authUser) {

View File

@ -26,18 +26,6 @@ class PublicController extends \Phalcon\Mvc\Controller
$this->response->redirect(['for' => 'admin.login']);
}
/**
* @Route("/robot", name="admin.robot")
*/
public function robotAction()
{
$isAjaxRequest = is_ajax_request();
if ($isAjaxRequest) {
return $this->jsonError(['msg' => '疑似机器人请求']);
}
}
/**
* @Route("/forbidden", name="admin.forbidden")
*/

View File

@ -13,8 +13,7 @@ use App\Traits\Security as SecurityTrait;
class SessionController extends \Phalcon\Mvc\Controller
{
use ResponseTrait;
use SecurityTrait;
use ResponseTrait, SecurityTrait;
/**
* @Route("/login", name="admin.login")
@ -23,13 +22,8 @@ class SessionController extends \Phalcon\Mvc\Controller
{
if ($this->request->isPost()) {
if (!$this->checkHttpReferer() || !$this->checkCsrfToken()) {
$this->dispatcher->forward([
'controller' => 'public',
'action' => 'robot',
]);
return false;
}
$this->checkHttpReferer();
$this->checkCsrfToken();
$sessionService = new SessionService();

View File

@ -20,7 +20,7 @@
<tr>
<td>{{ item.title }}</td>
<td><span class="layui-badge layui-bg-gray">{{ item.lesson_count }}</span></td>
<td>{{ expiry_info(item.expiry) }}</td>
<td>{{ study_expiry_info(item.study_expiry) }}</td>
<td>
<p>市场价:¥{{ item.market_price }}</p>
<p>会员价:¥{{ item.vip_price }}</p>

View File

@ -13,13 +13,7 @@ class Controller extends \Phalcon\Mvc\Controller
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
if (!$this->checkRateLimit()) {
$dispatcher->forward([
'controller' => 'public',
'action' => 'throttle',
]);
return false;
}
$this->checkRateLimit();
}
}

View File

@ -12,12 +12,4 @@ class PublicController extends \Phalcon\Mvc\Controller
use ResponseTrait;
/**
* @Get("/throttle", name="api.throttle")
*/
public function throttleAction()
{
return $this->jsonError(['msg' => '请求过于频繁']);
}
}

View File

@ -13,13 +13,7 @@ class Controller extends \Phalcon\Mvc\Controller
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
if (!$this->checkRateLimit()) {
$dispatcher->forward([
'controller' => 'public',
'action' => 'throttle',
]);
return false;
}
$this->checkRateLimit();
}
}

View File

@ -12,12 +12,4 @@ class PublicController extends \Phalcon\Mvc\Controller
use ResponseTrait;
/**
* @Get("/throttle", name="html5.throttle")
*/
public function throttleAction()
{
return $this->jsonError(['msg' => '请求过于频繁']);
}
}

View File

@ -20,23 +20,12 @@ class Controller extends \Phalcon\Mvc\Controller
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
if (!$this->checkRateLimit()) {
$dispatcher->forward([
'controller' => 'public',
'action' => 'throttle',
]);
return false;
if ($this->isNotSafeRequest()) {
$this->checkHttpReferer();
$this->checkCsrfToken();
}
if ($this->isNotSafeRequest()) {
if (!$this->checkHttpReferer() || !$this->checkCsrfToken()) {
$dispatcher->forward([
'controller' => 'public',
'action' => 'robot',
]);
return false;
}
}
$this->checkRateLimit();
$this->siteSettings = $this->getSiteSettings();
$this->navList = $this->getNavList();

View File

@ -53,7 +53,7 @@ class ErrorController extends \Phalcon\Mvc\Controller
$isAjaxRequest = is_ajax_request();
if ($isAjaxRequest || $isApiRequest) {
return $this->jsonError(['code' => 'sys.uri_not_found']);
return $this->jsonError(['code' => 'sys.not_found']);
}
}
@ -65,4 +65,12 @@ class ErrorController extends \Phalcon\Mvc\Controller
$this->response->setStatusCode(500);
}
/**
* @Get("/503", name="web.error.503")
*/
public function show503Action()
{
$this->response->setStatusCode(503);
}
}

View File

@ -12,56 +12,6 @@ class PublicController extends \Phalcon\Mvc\Controller
use ResponseTrait;
/**
* @Route("/auth", name="web.auth")
*/
public function authAction()
{
$isAjaxRequest = is_ajax_request();
if ($isAjaxRequest) {
return $this->jsonError(['msg' => '会话已过期,请重新登录']);
}
$this->response->redirect(['for' => 'web.login']);
}
/**
* @Route("/robot", name="web.robot")
*/
public function robotAction()
{
$isAjaxRequest = is_ajax_request();
if ($isAjaxRequest) {
return $this->jsonError(['msg' => '疑似机器人请求']);
}
}
/**
* @Route("/forbidden", name="web.forbidden")
*/
public function forbiddenAction()
{
$isAjaxRequest = is_ajax_request();
if ($isAjaxRequest) {
return $this->jsonError(['msg' => '无相关操作权限']);
}
}
/**
* @Get("/throttle", name="web.throttle")
*/
public function throttleAction()
{
$isAjaxRequest = is_ajax_request();
if ($isAjaxRequest) {
return $this->jsonError(['msg' => 'web请求过于频繁']);
}
}
/**
* @Get("/content/img/{id:[0-9]+}", name="web.content.img")
*/

View File

@ -2,7 +2,7 @@
namespace App\Traits;
use App\Services\Throttle;
use App\Validators\Security as SecurityValidator;
use Phalcon\Di;
use Phalcon\Http\Request;
@ -11,39 +11,23 @@ trait Security
public function checkCsrfToken()
{
/**
* @var Request $request
*/
$request = Di::getDefault()->get('request');
$validator = new SecurityValidator();
$tokenKey = $request->getHeader('X-Csrf-Token-Key');
$tokenValue = $request->getHeader('X-Csrf-Token-Value');
/**
* @var \App\Library\Security $security
*/
$security = Di::getDefault()->get('security');
return $security->checkToken($tokenKey, $tokenValue);
$validator->checkCsrfToken();
}
public function checkHttpReferer()
{
/**
* @var Request $request
*/
$request = Di::getDefault()->get('request');
$validator = new SecurityValidator();
$httpHost = parse_url($request->getHttpReferer(), PHP_URL_HOST);
return $httpHost == $request->getHttpHost();
$validator->checkHttpReferer();
}
public function checkRateLimit()
{
$throttle = new Throttle();
$validator = new SecurityValidator();
return $throttle->checkRateLimit();
$validator->checkRateLimit();
}
public function isNotSafeRequest()

View File

@ -123,7 +123,7 @@ class Account extends Validator
$user = $this->checkUserLogin($name, $password);
if ($user->admin_role == 0) {
throw new ForbiddenException('sys.access_denied');
throw new ForbiddenException('sys.forbidden');
}
return $user;

View File

@ -3,13 +3,49 @@
namespace App\Validators;
use App\Exceptions\BadRequest as BadRequestException;
use App\Exceptions\ServiceUnavailable as ServiceUnavailableException;
use App\Library\Validator\Common as CommonValidator;
use App\Services\Captcha as CaptchaService;
use App\Services\Throttle as ThrottleService;
use App\Services\VerifyCode as VerifyCodeService;
class Security extends Validator
{
public function checkCsrfToken()
{
$tokenKey = $this->request->getHeader('X-Csrf-Token-Key');
$tokenValue = $this->request->getHeader('X-Csrf-Token-Value');
$result = $this->security->checkToken($tokenKey, $tokenValue);
if (!$result) {
throw new BadRequestException('security.invalid_csrf_token');
}
}
public function checkHttpReferer()
{
$httpHost = parse_url($this->request->getHttpReferer(), PHP_URL_HOST);
$result = $httpHost == $this->request->getHttpHost();
if (!$result) {
throw new BadRequestException('security.invalid_http_referer');
}
}
public function checkRateLimit()
{
$throttleService = new ThrottleService();
$result = $throttleService->checkRateLimit();
if (!$result) {
throw new ServiceUnavailableException('security.too_many_requests');
}
}
public function checkVerifyCode($key, $code)
{
$verifyCodeService = new VerifyCodeService();

View File

@ -12,14 +12,14 @@ class Validator extends Component
public function checkAuthUser($authUser)
{
if (empty($authUser['id'])) {
throw new UnauthorizedException('sys.auth_failed');
throw new UnauthorizedException('sys.unauthorized');
}
}
public function checkOwner($userId, $ownerId)
{
if ($userId != $ownerId) {
throw new ForbiddenException('sys.access_denied');
throw new ForbiddenException('sys.forbidden');
}
}

View File

@ -5,6 +5,7 @@ namespace Bootstrap;
use App\Exceptions\BadRequest as BadRequestException;
use App\Exceptions\Forbidden as ForbiddenException;
use App\Exceptions\NotFound as NotFoundException;
use App\Exceptions\ServiceUnavailable as ServiceUnavailableException;
use App\Exceptions\Unauthorized as UnauthorizedException;
use App\Library\Logger as AppLogger;
use Phalcon\Mvc\User\Component;
@ -60,6 +61,8 @@ class HttpErrorHandler extends Component
$this->response->setStatusCode(403);
} elseif ($e instanceof NotFoundException) {
$this->response->setStatusCode(404);
} elseif ($e instanceof ServiceUnavailableException) {
$this->response->setStatusCode(503);
} else {
$this->response->setStatusCode(500);
}

View File

@ -3,17 +3,22 @@
$error = [];
/**
* 通用相关
* 系统相关
*/
$error['sys.uri_not_found'] = '资源地址不存在';
$error['sys.invalid_referer'] = '非法的请求来源';
$error['sys.auth_failed'] = '认证失败';
$error['sys.access_denied'] = '拒绝访问';
$error['sys.unauthorized'] = '认证失败';
$error['sys.forbidden'] = '拒绝访问';
$error['sys.bad_request'] = '无效的请求';
$error['sys.not_found'] = '资源不存在';
$error['sys.internal_server_error'] = '内部错误';
$error['sys.service_unavailable'] = '服务不可用';
$error['sys.unknown_error'] = '未知错误';
/**
* 安全相关
*/
$error['security.too_many_requests'] = '请求过于频繁';
$error['security.invalid_csrf_token'] = '无效的CSRF令牌';
$error['security.invalid_http_referer'] = '无效请求来源';
$error['security.invalid_captcha_code'] = '无效的验证码';
$error['security.invalid_verify_code'] = '无效的验证码';