Commit c32ddb4c by 汪伟伟

自定义接口 和中间件登录

parent ed8ca110
...@@ -49,4 +49,15 @@ Route::group([ ...@@ -49,4 +49,15 @@ Route::group([
// $router->get('/approves/{id}/edit', 'TasksApproveController@edit'); // $router->get('/approves/{id}/edit', 'TasksApproveController@edit');
});
Route::group([
'prefix' => 'api',
'middleware' => ['refresh.token']
], function (Router $router) {
$router->get('test', [\App\Http\Controllers\UserController::class, 'test']);
$router->get('login', [\App\Http\Controllers\UserController::class, 'login'])->withoutMiddleware('refresh.token');
}); });
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
namespace App\Exceptions; namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Throwable; use Throwable;
class Handler extends ExceptionHandler class Handler extends ExceptionHandler
...@@ -10,7 +14,7 @@ class Handler extends ExceptionHandler ...@@ -10,7 +14,7 @@ class Handler extends ExceptionHandler
/** /**
* A list of the exception types that are not reported. * A list of the exception types that are not reported.
* *
* @var array * @var array<int, class-string<Throwable>>
*/ */
protected $dontReport = [ protected $dontReport = [
// //
...@@ -19,7 +23,7 @@ class Handler extends ExceptionHandler ...@@ -19,7 +23,7 @@ class Handler extends ExceptionHandler
/** /**
* A list of the inputs that are never flashed for validation exceptions. * A list of the inputs that are never flashed for validation exceptions.
* *
* @var array * @var array<int, string>
*/ */
protected $dontFlash = [ protected $dontFlash = [
'current_password', 'current_password',
...@@ -38,4 +42,59 @@ class Handler extends ExceptionHandler ...@@ -38,4 +42,59 @@ class Handler extends ExceptionHandler
// //
}); });
} }
protected function getErrors($err)
{
$errStr = '';
foreach ($err as $er) {
foreach ($er as $v) {
$errStr .= ($v . ';');
}
}
return $errStr;
}
/**
* 所有异常的处理归口处(可以统一封装异常处理的操作)
* @param Throwable $e
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
*/
public function render($request, Throwable $e)
{
$data = function () use ($request, $e) {
try {
$routes = Route::getRoutes();
$routes->match($request);//校验当前路由是否存在
//捕获表单验证异常,改成统一的返回样式
if ($e instanceof UnauthorizedHttpException) {
return ['code' => 400401, 'message' => $e->getMessage(), 'data' => null];
}
// if ($e instanceof AuthenticationException) {
// return ['errCode' => 400401, 'errMsg' => $e->getMessage(), 'data' => null];
// }
if ($e instanceof ValidationException) {
$errors = $this->getErrors($e->errors());
return ['code' => 422, 'message' => $errors, 'data' => null];
}
return [
'code' => ($e->getCode() != 0) ? $e->getCode() : 400001,
// 'errMsg' => '文件【' . $e->getFile() . '】的第' . $e->getLine() . '行出现异常,大致是:【' . ($e->getMessage() ?? "error!") . '】',
'message' => $e->getMessage(),
'data' => null,
];
} catch (NotFoundHttpException $ex) {
return ['code' => 404, 'message' => '请求地址不存在...', 'data' => null];
} catch (\Exception $excep) {
return [
'code' => ($excep->getCode() != 0) ? $excep->getCode() : 400002,
'message' => $excep->getMessage() ?? "error!",
'data' => null,
];
}
};
return response()->json($data());//返回json对象用这个方法
}
} }
...@@ -5,9 +5,39 @@ namespace App\Http\Controllers; ...@@ -5,9 +5,39 @@ namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController class Controller extends BaseController
{ {
use AuthorizesRequests, DispatchesJobs, ValidatesRequests; use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
/**
* @param array $data
* @param int $code
* @param string $msg
* @return \Illuminate\Http\JsonResponse
*/
public function success(array $data = [], int $code = 0, string $msg = 'success'):JsonResponse
{
return response()->json([
'code' => $code,
'data' => $data,
'message' => $msg
]);
}
/**
* @param int $code
* @param string $msg
* @return \Illuminate\Http\JsonResponse
*/
public function error(string $msg = 'error', int $code = 400, ):JsonResponse
{
return response()->json([
'code' => $code,
'data' => null,
'message' => $msg
]);
}
} }
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
public function test()
{
return $this->success([authUser()]);
}
public function login()
{
$credentials = request(['username', 'password']);
if (!$token = auth('api')->attempt($credentials)) {
return $this->error('登录失败,用户密码不匹配');
}
return $this->success([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
/**
* 注销jwt.
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
auth('api')->logout();
return response()->json(['message' => '注销成功!']);
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace App\Http; namespace App\Http;
use App\Http\Middleware\RefreshToken;
use Illuminate\Foundation\Http\Kernel as HttpKernel; use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel class Kernel extends HttpKernel
...@@ -62,5 +63,6 @@ class Kernel extends HttpKernel ...@@ -62,5 +63,6 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'refresh.token' => RefreshToken::class,
]; ];
} }
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
class RefreshToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// 检查此次请求中是否带有 token,如果没有则抛出异常。
$this->checkForToken($request);
// dd(123);
// 使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException 异常
try {
// 检测用户的登录状态,如果正常则通过.
if ($this->auth->parseToken()->authenticate()) {
return $next($request);
}
throw new UnauthorizedHttpException('jwt-auth', '未登录');
} catch (TokenExpiredException $exception) {
// 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
try {
// 刷新用户的 token
$token = $this->auth->refresh();
// 使用一次性登录以保证此次请求的成功
Auth::guard()
->onceUsingId($this->auth->manager()
->getPayloadFactory()
->buildClaimsCollection()
->toPlainArray()['sub']);
} catch (JWTException $exception) {
// 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
}
}
// 在响应头中返回新的 token
return $this->setAuthenticationHeader($next($request), $token);
}
}
<?php
//if (!function_exists('success')) {
// /**
// * @param $data
// * @return \Illuminate\Http\JsonResponse
// */
// function success($data = [])
// {
// $res = [
// 'code' => 0,
// 'message' => 'success',
// 'data' => $data,
// ];
// return response()->json($res);
// }
//}
if (!function_exists('authUser')) {
/**
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
function authUser()
{
return auth('api')->user();
}
}
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
"phpunit/phpunit": "^9.3.3" "phpunit/phpunit": "^9.3.3"
}, },
"autoload": { "autoload": {
"files": [
"app/helpers.php"
],
"psr-4": { "psr-4": {
"App\\": "app/", "App\\": "app/",
"Database\\Factories\\": "database/factories/", "Database\\Factories\\": "database/factories/",
......
...@@ -66,6 +66,7 @@ return [ ...@@ -66,6 +66,7 @@ return [
'middleware' => ['web', 'admin'], 'middleware' => ['web', 'admin'],
'enable_session_middleware' => false, 'enable_session_middleware' => false,
], ],
/* /*
...@@ -210,11 +211,13 @@ return [ ...@@ -210,11 +211,13 @@ return [
// All method to path like: auth/users/*/edit // All method to path like: auth/users/*/edit
// or specific method to path like: get:auth/users. // or specific method to path like: get:auth/users.
'except' => [ 'except' => [//跳过权限认证的接口
'/', '/',
'auth/login', 'auth/login',
'auth/logout', 'auth/logout',
'auth/setting', 'auth/setting',
'api/test'
], ],
], ],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment