如何使用 laravel Passport 从 API 注销用户

How to logout a user from API using laravel Passport

我目前正在使用 2 个项目。 1 个前端(使用 laravel 后端与 API 通信)和另一个 laravel 项目(API)。

现在我使用 Laravel Passport 对用户进行身份验证并确保每次 API 调用都是授权调用。

现在,当我想注销我的用户时,我向我的 API(使用 Bearer 令牌)发送了一个 post 请求,并尝试让他退出 API(并清除会话、cookies...)

然后在客户端上我也刷新我的会话所以令牌不再为人所知。现在,当我返回登录页面时,它会自动登录我的用户。 (或者我的用户仍然处于登录状态)。

谁能告诉我如何使用 Laravel 护照正确注销用户?

提前致谢。

您需要从数据库中删除令牌table oauth_access_tokens 你可以通过创建一个像 OauthAccessToken

这样的新模型来做到这一点
  1. 运行命令php artisan make:model OauthAccessToken创建模型。

  2. 然后在 User 模型和新创建的 OauthAccessToken 模型之间创建关系,在 User.php 中添加:

    public function AauthAcessToken(){
        return $this->hasMany('\App\OauthAccessToken');
    }
    
  3. 在UserController.php中,新建一个注销函数:

    public function logoutApi()
    { 
        if (Auth::check()) {
           Auth::user()->AauthAcessToken()->delete();
        }
    }
    
  4. 在 api.php 路由器中,创建新路由:

     Route::post('logout','UserController@logoutApi');
    
  5. 现在您可以通过调用发布到 URL /api/logout
  6. 来注销

创建注销路由:

$router->group(['middleware' => 'auth:api'], function () use ($router) {
    Route::get('me/logout', 'UserController@logout');
});

在 userController 中创建注销功能(或在您的路线中提到)

public function logout() {
        $accessToken = Auth::user()->token();
        DB::table('oauth_refresh_tokens')
            ->where('access_token_id', $accessToken->id)
            ->update([
                'revoked' => true
            ]);

        $accessToken->revoke();
        return response()->json(null, 204);
    }

确保在 User 模型中导入了这个

use Laravel\Passport\HasApiTokens;

并且您在 User 模型 class 中使用特征 HasApiTokens 使用

use HasApiTokens

在用户内部 class。 现在您创建注销路由并在控制器中, 这样做

$user = Auth::user()->token();
$user->revoke();
return 'logged out'; // modify as per your need

这将使用户从他请求注销的当前设备注销。如果你想从他登录的所有设备上注销。那就这样做

$tokens =  $user->tokens->pluck('id');
Token::whereIn('id', $tokens)
    ->update(['revoked'=> true]);

RefreshToken::whereIn('access_token_id', $tokens)->update(['revoked' => true]);

确保在顶部导入这两个

use Laravel\Passport\RefreshToken;
use Laravel\Passport\Token;

这将撤销颁发给该用户的所有访问和刷新令牌。这将从任何地方注销用户。当用户使用重置密码或忘记密码选项更改密码并且您必须从任何地方注销用户时,这真的很有用。

这是我用于注销的示例代码

public function logout(Request $request)
{
    $request->user()->token()->revoke();
    return response()->json([
        'message' => 'Successfully logged out'
    ]);
}

我正在使用 Laravel 6.12.0,下面的功能对我有用。

public function logout(Request $request){
            $accessToken = Auth::user()->token();
            $token= $request->user()->tokens->find($accessToken);
            $token->revoke();
            $response=array();
            $response['status']=1;
            $response['statuscode']=200;
            $response['msg']="Successfully logout";
            return response()->json($response)->header('Content-Type', 'application/json');
        }

这是我的第一个 post.. 我找到了一个干净的解决方案(Laravel 最新版本)

/**
 * Logout api
 *
 * @return \Illuminate\Http\Response
 */
public function logout(Request $request)
{        
    if (Auth::check()) {
        $token = Auth::user()->token();
        $token->revoke();
        return $this->sendResponse(null, 'User is logout');
    } 
    else{ 
        return $this->sendError('Unauthorised.', ['error'=>'Unauthorised'] , Response::HTTP_UNAUTHORIZED);
    } 
}

下面是我找到的最简单的方法。

1。使用数据库 SESSION 代替文件 SESSION

Official documention

php artisan session:table
php artisan migrate

在您的 .env 文件中将 SESSION_DRIVER=file 替换为 SESSION_DRIVER=database

2。登录后立即删除用户会话

用户被重定向到你的前端并登录最终获得令牌后,你可能会调用 api/routes.php 中的路由来获取用户信息,这就是我之前关闭用户后端会话的地方将用户信息发送回前端:

Route::middleware('auth:api')->get('/user', function (Request $request) {
    // Close user session here
    Illuminate\Support\Facades\DB::table('sessions')
        ->whereUserId($request->user()->id)
        ->delete();
    return $request->user();
});

3。注销时撤销令牌

然后,要从前端“注销”(实际上是撤销令牌)用户,您只需要调用另一个路由来撤销 tokenrefresh_token:

Route::middleware('auth:api')->post('/logout', function (Request $request) {
    // Revoke access token
    // => Set oauth_access_tokens.revoked to TRUE (t)
    $request->user()->token()->revoke();

    // Revoke all of the token's refresh tokens
    // => Set oauth_refresh_tokens.revoked to TRUE (t)
    $refreshTokenRepository = app('Laravel\Passport\RefreshTokenRepository');
    $refreshTokenRepository->revokeRefreshTokensByAccessTokenId($request->user()->token()->id);

    return;
});

您可能更愿意将这两个闭包放在 UserController.

希望对某人有所帮助:

 if (Auth::check()) {
   $request->user()->tokens->each(function ($token, $key) {
        $token->delete();
    });
 }

祝你好运。

public function logout(Request $request)
{
    $request->user()->token()->revoke();

    if ($request->everywhere) {
        foreach ($request->user()->tokens()->whereRevoked(0)->get() as $token) {
            $token->revoke();
        }
    }

    return response()->json(['message' => 'success']);
}

我在我的项目中使用它从多个设备注销。

public function logout(Request $request, $devices = FALSE)
{
    $this->logoutMultiple(\Auth::user(), $devices);
    return response()->json([], 204);
}

private function logoutMultiple(\App\Models\User $user, $devices = FALSE)
{

    $accessTokens = $user->tokens();

    if ($devices == 'all') {
        
    } else if ($devices == 'other') {
        $accessTokens->where('id', '!=', $user->token()->id);
    } else {
        $accessTokens->where('id', '=', $user->token()->id);
    }

    $accessTokens = $accessTokens->get();

    foreach ($accessTokens as $accessToken) {

        $refreshToken = \DB::table('oauth_refresh_tokens')
            ->where('access_token_id', $accessToken->id)
            ->update(['revoked' => TRUE]);

        $accessToken->revoke();
    }
}

尝试使用此代码帮助您退出护照身份验证。

Route::post('/logout', function(){

        if (Auth::check()) {
            Auth::user()->AauthAcessToken()->delete();
        }

        return response()->json([

            'status'    => 1,
            'message'   => 'User Logout',

        ], 200);
    });

检查您的模型是否包含需要连接数据库的OauthAccessTokenoauth_access_tokens。访问令牌存储在数据库 table oauth_access_tokens 中。并使用户与 oauth_access_tokens.

建立关系
public function AauthAcessToken(){
    return $this->hasMany(OauthAccessToken::class);
}