简体   繁体   English

JWT / LARAVEL令牌已过期

[英]JWT/LARAVEL token expired

I developed an API and I have a problem with the expiration of the token, and I try to find ways to refresh the tokens sent by API and I found nothing This is my user mdoal: 我开发了一个API,但令牌过期有问题,我尝试找到刷新API发送的令牌的方法,但没有发现任何问题。这是我的用户mdoal:

<?php

namespace App;


use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password','username','lastname','tel','tel',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}

and this is my loginController 这是我的loginController

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\User;
use JWTFactory;
use JWTAuth;
use Validator;


class APILoginController extends Controller
{
    //


    public function login( Request $request){
        $validator = Validator::make($request -> all(),[
         'email' => 'required|string|email|max:255',
         'password'=> 'required'
        ]);

        if ($validator -> fails()) {
            # code...
            return response()->json($validator->errors());

        }


        $credentials = $request->all('email','password');
        try{
            if (! $token = JWTAuth::attempt( $credentials) ) {
                # code...
                return response()->json( ['error'=> 'invalid username and password'],401);
            }
        }catch(JWTException $e){

          return response()->json( ['error'=> 'could not create token'],500);
        }

        $currentUser = Auth::user();

        return response()->json( ['user'=> $currentUser,'token'=>compact('token')],200);
        ///return response()->json( compact('token'));

    }

}

and I found in github a solution to creat a custom middleware,When the token is expired, the refreshed token is added to the response headers. 我在github中找到了创建自定义中间件的解决方案。当令牌过期时,刷新的令牌将添加到响应头中。 The app just needs to search if the response has this, if so, update the saved token. 该应用仅需要搜索响应中是否包含此信息,如果是,则更新已保存的令牌。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        try
        {
            if (! $user = JWTAuth::parseToken()->authenticate() )
            {
                return response()->json([
                    'code'   => 101, // means auth error in the api,
                   'response' => null // nothing to show
                 ]);
            }
        }
        catch (TokenExpiredException $e)
        {
            // If the token is expired, then it will be refreshed and added to the headers
            try
            {
                $refreshed = JWTAuth::refresh(JWTAuth::getToken());
                $user = JWTAuth::setToken($refreshed)->toUser();
                header('Authorization: Bearer ' . $refreshed);
            }
            catch (JWTException $e)
            {
                return response()->json([
                    'code'   => 103, // means not refreshable
                   'response' => null // nothing to show
                 ]);
            }
        }
        catch (JWTException $e)
        {
            return response()->json([
                'code'   => 101 ,//, means auth error in the api,
                   'response' => null // nothing to show
            ]);
        }

        // Login the user instance for global usage
        Auth::login($user, false);

        return  $next($request);
    }
}

So you are using normal PHP methods for setting headers inside a Laravel middleware, that ain't going to work. 因此,您正在使用普通的PHP方法在Laravel中间件中设置标头,但无法正常工作。

You should checko this out: https://github.com/tymondesigns/jwt-auth/blob/develop/src/Http/Middleware/BaseMiddleware.php 您应该检查一下: https : //github.com/tymondesigns/jwt-auth/blob/develop/src/Http/Middleware/BaseMiddleware.php

https://github.com/tymondesigns/jwt-auth/blob/develop/src/Http/Middleware/RefreshToken.php https://github.com/tymondesigns/jwt-auth/blob/develop/src/Http/Middleware/RefreshToken.php

Basically, change: 基本上,更改:

header('Authorization: Bearer ' . $refreshed);

to

$response = $next($request);
$response->headers->set('Authorization', 'Bearer '.$token);

The thing is the following, this aproach won't work as expected because this kind of "AfterMiddleware" gets executed after the request has been throught your app. 事情是这样的,此方法无法按预期工作,因为这种“ AfterMiddleware”在请求通过您的应用程序后执行。 So: 所以:

  1. User makes request with expired token 用户使用过期的令牌发出请求
  2. The app will return a 403 or 401 (can't remember) because of TokenExpired. 由于TokenExpired,应用程序将返回403或401(不记得了)。
  3. The response however will contain a header with the new token 但是,响应将包含带有新令牌的标头
  4. You make the same request with the new token and it should work. 您使用新令牌发出了相同的请求,它应该可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM