Laravel JWT-auth 身份验证的注销问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29631302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:21:25  来源:igfitidea点击:

Logout issue with Laravel JWT-auth authentication

phpangularjsauthenticationlaraveljwt

提问by Maykonn

I'm use jwt-authto make a RESTful auth resource in my API. When a client app calls the login resource, case user is logged, your current token must be invalidated and so a new token generated.

我正在使用jwt-auth在我的 API 中创建一个 RESTful auth 资源。当客户端应用程序调用登录资源时,记录用户案例,您当前的令牌必须无效,因此会生成新的令牌。

But case the current token is blacklisted a TokenBlacklistedExceptionis thrown.

但是如果当前令牌被列入黑名单,TokenBlacklistedException则会抛出。

How to verify if a token is blacklisted? Or how to correct implement an user "logout"? I try to found on jwt-auth API source but not exists a getToken()->isBlacklisted()or parseToken()->isBlacklisted()or some validator to implement it.

如何验证令牌是否被列入黑名单?或者如何正确实现用户“注销”?我尝试在智威汤逊-auth的API源找到,但不存在getToken()->isBlacklisted()parseToken()->isBlacklisted()或一些验证来实现它。

Ever token is invalid parseToken() throws a TokenBlacklistedException, so an isBlacklisted method is a good way to verify if token is valid before invalidate a token.

曾经令牌无效 parseToken() 会抛出 TokenBlacklistedException,因此 isBlacklisted 方法是在使令牌无效之前验证令牌是否有效的好方法。

INFO:

信息:

The bellow code verify if payload is invalid, thrown the TokenBlacklistedExceptionif is invalid:

下面的代码验证有效载荷是否无效,TokenBlacklistedException如果无效则抛出:

if(
    false === \Tymon\JWTAuth\Blacklist::has(
        \Tymon\JWTAuth\Facades\JWTAuth::getPayload($token)
    )
) {
     \Tymon\JWTAuth\Facades\JWTAuth::parseToken()->invalidate();
}

How to verify like:

如何验证像:

if(false ===\Tymon\JWTAuth\Facades\JWTAuth::parseToken()->isBlacklisted()) {
    // invalidate...
}

回答by Matthew Brown

You can simply destroy the session on the client side when they logout and invalidate the token on the backend, you shouldn't need to use the blacklist.

您可以简单地在客户端注销时销毁会话并使后端的令牌无效,您不需要使用黑名单。

Technically destroying the token on the client side will be enough, but for session hiHymaning, invalidating it on the backend is a good idea too.

从技术上讲,在客户端销毁令牌就足够了,但是对于会话劫持,在后端使其无效也是一个好主意。

If you are invalidating, you'll need to destroy the token after you get your response from Laravel.

如果您使无效,则需要在收到 Laravel 的响应后销毁令牌。

JWTAuth::invalidate(JWTAuth::getToken())):

Then on angular side

然后在有角度的一侧

function logout()
{ 
    UserService.logout().$promise.then(function() {
        $cookieStore.remove('userToken');
        // redirect or whatever 
    });
}

One way you can handle JWT exceptions is to setup an EventServiceProviderin laravel, here is what mine looks like:

处理 JWT 异常的一种方法是EventServiceProvider在 laravel 中设置一个,这是我的样子:

use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider {

    /**
     * The event handler mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'tymon.jwt.valid' => [
            'App\Events\JWTEvents@valid',
        ],
        'tymon.jwt.user_not_found' => [
            'App\Events\JWTEvents@notFound'
        ],
        'tymon.jwt.invalid' => [
            'App\Events\JWTEvents@invalid'  
        ],
        'tymon.jwt.expired' => [
            'App\Events\JWTEvents@expired'  
        ],
        'tymon.jwt.absent' => [
            'App\Events\JWTEvents@missing'
        ]
    ];

    /**
     * Register any other events for your application.
     *
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
     * @return void
     */
    public function boot(DispatcherContract $events)
    {
        parent::boot($events);

        //
    }
}

You'll register that in your app.php.

您将在 app.php 中注册它。

Then I implement the JWTEvents class with methods for each event.

然后我使用每个事件的方法实现 JWTEvents 类。

class JWTEvents extends Event {

    // Other methods        

    public function invalid()
    {
        return response()->json(['error' => 'Token Invalid'], 401);
        die();
    }
}

Important thing to note is that we are catching the JWT exceptions and returning a json response with a specific status code.

需要注意的重要一点是,我们正在捕获 JWT 异常并返回带有特定状态代码的 json 响应。

On the angular side, I have in my httpInterceptor class, catches for these http status codes.

在角度方面,我在 httpInterceptor 类中捕获了这些 http 状态代码。

angular.module('ngApp')
    .factory('httpInterceptor', function($q, $log, $cookieStore, $rootScope, Response) {
        return {

            request: function(config) {
                // Where you add the token to each request
            },

            responseError: function(response) {

                // Check if response code is 401 (or whatever)
                if (response.status === 401) {
                    // Do something to log user out & redirect.
                    $rootScope.$broadcast('invalid.token');
                }
            }
        }
    });

回答by usama muneer

This works for me.

这对我有用。

public function logout( Request $request ) {

        $token = $request->header( 'Authorization' );

        try {
            JWTAuth::parseToken()->invalidate( $token );

            return response()->json( [
                'error'   => false,
                'message' => trans( 'auth.logged_out' )
            ] );
        } catch ( TokenExpiredException $exception ) {
            return response()->json( [
                'error'   => true,
                'message' => trans( 'auth.token.expired' )

            ], 401 );
        } catch ( TokenInvalidException $exception ) {
            return response()->json( [
                'error'   => true,
                'message' => trans( 'auth.token.invalid' )
            ], 401 );

        } catch ( JWTException $exception ) {
            return response()->json( [
                'error'   => true,
                'message' => trans( 'auth.token.missing' )
            ], 500 );
        }
    }

回答by madone

As far as I understand, one thing that nobody stressed is the 'jwt.refresh' (aka RefreshTokenMiddleware) used to refresh the token.

据我了解,没有人强调的一件事是用于刷新令牌的“jwt.refresh”(又名 RefreshTokenMiddleware)。

Now, if anyone who wants to perform a logout action wraps the controller method in a route like

现在,如果任何想要执行注销操作的人将控制器方法包装在类似的路由中

Route::group(['middleware' => ['jwt.auth', 'jwt.refresh']], function()...

for sure will get a new token in logout response hence the client will be able to perform new requests.

肯定会在注销响应中获得一个新令牌,因此客户端将能够执行新请求。

Hope this can help clarify this issue.

希望这可以帮助澄清这个问题。