Handler.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <?php
  2. namespace App\Exceptions;
  3. use App\Components\IP;
  4. use Arr;
  5. use ErrorException;
  6. use Illuminate\Auth\AuthenticationException;
  7. use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
  8. use Illuminate\Http\Client\ConnectionException;
  9. use Illuminate\Http\Request;
  10. use Illuminate\Session\TokenMismatchException;
  11. use Illuminate\Validation\ValidationException;
  12. use Log;
  13. use ReflectionException;
  14. use Response;
  15. use Symfony\Component\HttpKernel\Exception\HttpException;
  16. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  17. use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
  18. use Throwable;
  19. use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
  20. use Tymon\JWTAuth\Exceptions\TokenExpiredException;
  21. use Tymon\JWTAuth\Exceptions\TokenInvalidException;
  22. class Handler extends ExceptionHandler
  23. {
  24. /**
  25. * A list of the exception types that are not reported.
  26. *
  27. * @var array
  28. */
  29. protected $dontReport = [
  30. HttpException::class,
  31. ValidationException::class,
  32. ];
  33. /**
  34. * A list of the inputs that are never flashed for validation exceptions.
  35. *
  36. * @var array
  37. */
  38. protected $dontFlash = [
  39. 'password',
  40. 'password_confirmation',
  41. ];
  42. /**
  43. * Report or log an exception.
  44. *
  45. * @param Throwable $exception
  46. * @return void
  47. *
  48. * @throws Throwable
  49. */
  50. public function report(Throwable $exception)
  51. {
  52. // 调试模式下记录错误详情
  53. if (config('app.debug') || config('app.demo')) {
  54. Log::debug('来自链接:'.url()->full());
  55. // 记录异常来源
  56. Log::info('异常来源:'.get_class($exception));
  57. Log::debug($exception);
  58. }
  59. parent::report($exception);
  60. }
  61. /**
  62. * Render an exception into an HTTP response.
  63. *
  64. * @param Request $request
  65. * @param Throwable $exception
  66. * @return \Symfony\Component\HttpFoundation\Response
  67. *
  68. * @throws Throwable
  69. */
  70. public function render($request, Throwable $exception)
  71. {
  72. // 调试模式下直接返回错误信息,非调试模式下渲染在返回
  73. if ($exception instanceof UnauthorizedHttpException) {
  74. $preException = $exception->getPrevious();
  75. if ($preException instanceof TokenExpiredException) {
  76. return response()->json(['code'=>401,'ret'=>401,'error' => 'TOKEN_EXPIRED','msg' =>'鉴权失败,需要重新登录'],200);
  77. } else if ($preException instanceof TokenBlacklistedException) {
  78. return response()->json(['code'=>402, 'ret' => 402, 'msg' => "TOKEN禁用,需要重新登陆"], 200);
  79. }
  80. if ($exception->getMessage() === 'Token not provided') {
  81. return response()->json(['code'=>403,'ret' => 403, 'msg' => "TOKEN错误,需要重新登陆"], 200);
  82. }
  83. }
  84. if (! config('app.debug')) {
  85. switch ($exception) {
  86. case $exception instanceof ValidationException:
  87. if (strpos($request->fullUrl(),"client/v1") != false || strpos($request->fullUrl(),"client/v2") != false || strpos($request->fullUrl(),"client/v3") != false){
  88. return Response::json([
  89. 'ret' => 404,
  90. 'msg' => Arr::first(Arr::collapse($exception->errors()))
  91. ],404);
  92. }
  93. return Response::view(
  94. 'auth.error',
  95. ['message' => Arr::first(Arr::collapse($exception->errors()))],
  96. 500
  97. );
  98. // return $this->response($code, Arr::first(Arr::collapse($exception->errors())));
  99. // return Response::json(['status' => 'fail', 'message' => Arr::first(Arr::collapse($exception->errors()))], 409);
  100. case $exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException:
  101. // Log::info('异常请求:'.$exception->getMessage());
  102. return Response::json(['status' => 'fail', 'message' => $exception->getMessage()], 408);
  103. case $exception instanceof NotFoundHttpException: // 捕获访问异常
  104. // Log::info('异常请求:'.$request->fullUrl().',IP:'.IP::getClientIp());
  105. // Log::info('异常请求 route:'.$request->route());
  106. if (strpos($request->fullUrl(),"client/v1") != false || strpos($request->fullUrl(),"client/v2") != false || strpos($request->fullUrl(),"client/v3") != false ){
  107. return Response::json([
  108. 'ret' => 404,
  109. 'msg' => empty($exception->getMessage()) ? '资源没找到~' : $exception->getMessage()
  110. ],404);
  111. }
  112. if ($request->ajax() || $request->wantsJson()) {
  113. // return Response::json(['status' => 'fail', 'message' => trans('error.missing_page')], 404);
  114. return Response::json(['status' => 'fail', 'message' => empty($exception->getMessage()) ? '资源没找到~' : $exception->getMessage()], 407);
  115. }
  116. return Response::view('auth.error', ['message' => $exception->getMessage()], 404);
  117. case $exception instanceof AuthenticationException: // 捕获身份校验异常
  118. if (strpos($request->fullUrl(),"client/v1") != false || strpos($request->fullUrl(),"client/v2") != false || strpos($request->fullUrl(),"client/v3") != false ){
  119. return Response::json([
  120. 'ret' => 401,
  121. 'msg' => "登陆失效,重新登陆下"
  122. ],200);
  123. }
  124. if ($request->ajax() || $request->wantsJson()) {
  125. return Response::json(['status' => 'fail', 'message' => trans('error.unauthorized')], 401);
  126. }
  127. return Response::view('auth.error', ['message' => trans('error.unauthorized')], 401);
  128. case $exception instanceof TokenMismatchException: // 捕获CSRF异常
  129. if ($request->ajax() || $request->wantsJson()) {
  130. return Response::json([
  131. 'status' => 'fail',
  132. 'message' => trans('error.refresh_page').'<a href="'.route('login').'" target="_blank">'.trans('error.refresh').'</a>',
  133. ], 419);
  134. }
  135. return Response::view(
  136. 'auth.error',
  137. ['message' => trans('error.refresh_page').'<a href="'.route('login').'" target="_blank">'.trans('error.refresh').'</a>'],
  138. 419
  139. );
  140. case $exception instanceof ReflectionException:
  141. if ($request->ajax() || $request->wantsJson()) {
  142. return Response::json(['status' => 'fail', 'message' => trans('error.system')], 500);
  143. }
  144. return Response::view('auth.error', ['message' => trans('error.system')], 500);
  145. case $exception instanceof ErrorException: // 捕获系统错误异常
  146. if (strpos($request->fullUrl(),"client/v1") != false || strpos($request->fullUrl(),"client/v2") != false || strpos($request->fullUrl(),"client/v3") != false ){
  147. return Response::json([
  148. 'ret' => 404,
  149. 'msg' => empty($exception->getMessage()) ? '系统错误' : $exception->getMessage()
  150. ],404);
  151. }
  152. if ($request->ajax() || $request->wantsJson()) {
  153. return Response::json([
  154. 'status' => 'fail',
  155. 'message' => trans('error.system').', '.trans('error.visit').'<a href="'.route('admin.log.viewer').'" target="_blank">'.trans('error.log').'</a>',
  156. ], 500);
  157. }
  158. return Response::view(
  159. 'auth.error',
  160. ['message' => trans('error.system').', '.trans('error.visit').'<a href="'.route('admin.log.viewer').'" target="_blank">'.trans('error.log').'</a>'],
  161. 500
  162. );
  163. case $exception instanceof ConnectionException:
  164. if ($request->ajax() || $request->wantsJson()) {
  165. return Response::json(['status' => 'fail', 'message' => $exception->getMessage()], 408);
  166. }
  167. return Response::view('auth.error', ['message' => $exception->getMessage()], 408);
  168. default:
  169. return Response::json([
  170. 'status' => 'fail',
  171. 'ret' => 404,
  172. 'msg' => $exception->getMessage()
  173. ],404);
  174. }
  175. }
  176. return parent::render($request, $exception);
  177. }
  178. }