laravel8 passport 不使用http请求获取access_token和refresh_token

借鉴地址:https://github.com/laravel/passport/issues/71#issuecomment-330506407


trait文件

namespace App\Traits;

use App\Models\User;

use GuzzleHttp\Psr7\Response;

use Illuminate\Events\Dispatcher;

use Laravel\Passport\Bridge\AccessToken;

use Laravel\Passport\Bridge\AccessTokenRepository;

use Laravel\Passport\Bridge\Client;

use Laravel\Passport\Bridge\RefreshTokenRepository;

use Laravel\Passport\Bridge\Scope;

use Laravel\Passport\Passport;

use Laravel\Passport\TokenRepository;

use League\OAuth2\Server\CryptKey;

use League\OAuth2\Server\Entities\AccessTokenEntityInterface;

use League\OAuth2\Server\Exception\OAuthServerException;

use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;

use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;

//借鉴文档地址https://github.com/laravel/passport/issues/71#issuecomment-330506407

/**

* @mixin User

*/

trait PassportTrait

{

    public function createBearerToken($clientId, $scopes = [])

{

        $passportToken = $this->createPassportToken($clientId, $scopes);

        $bearerToken = $this->sendBearerTokenResponse($passportToken['access_token'], $passportToken['refresh_token']);

        return json_decode($bearerToken->getBody()->__toString(), true);

    }

    protected function createPassportToken($clientId, $scopes = [])

{

        //格式化scopes

        $scopes = $this->genScopes($scopes);

        $client = \Laravel\Passport\Client::find($clientId);

        $accessClient = new Client($client->id, $client->name, $client->redirect);

        $accessToken = new AccessToken($this->id, $scopes, $accessClient);

        $accessToken->setIdentifier($this->generateUniqueIdentifier());

        $accessToken->setClient($accessClient);

        $accessToken->setExpiryDateTime((new \DateTimeImmutable)->add(Passport::tokensExpireIn()));

        $accessTokenRepository = new AccessTokenRepository(new TokenRepository(), app(Dispatcher::class));

        //触发 AccessTokenCreated 事件

        $accessTokenRepository->persistNewAccessToken($accessToken);

        $refreshToken = $this->issueRefreshToken($accessToken);

        return [

            'access_token'  => $accessToken,

            'refresh_token' => $refreshToken,

        ];

    }

    protected function sendBearerTokenResponse($accessToken, $refreshToken)

{

        $response = new BearerTokenResponse();

        $response->setAccessToken($accessToken);

        $response->setRefreshToken($refreshToken);

        $privateKey = new CryptKey(file_get_contents(Passport::keyPath('oauth-private.key')));

        $accessToken->setPrivateKey($privateKey);

        $response->setPrivateKey($privateKey);

        $response->setEncryptionKey(app('encrypter')->getKey());

        return $response->generateHttpResponse(new Response);

    }

    private function generateUniqueIdentifier($length = 40)

{

        try {

            return bin2hex(random_bytes($length));

        } catch (\TypeError | \Error $e) {

            throw OAuthServerException::serverError('An unexpected error has occurred');

        } catch (\Exception $e) {

            // If you get this message, the CSPRNG failed hard.

            throw OAuthServerException::serverError('Could not generate a random string');

        }

        // @codeCoverageIgnoreEnd

    }

    private function issueRefreshToken(AccessTokenEntityInterface $accessToken)

{

        $maxGenerationAttempts = 10;

        $refreshTokenRepository = app(RefreshTokenRepository::class);

        $refreshToken = $refreshTokenRepository->getNewRefreshToken();

        $refreshToken->setExpiryDateTime((new \DateTimeImmutable)->add(Passport::refreshTokensExpireIn()));

        $refreshToken->setAccessToken($accessToken);

        while ($maxGenerationAttempts-- > 0) {

            $refreshToken->setIdentifier($this->generateUniqueIdentifier());

            try {

                $refreshTokenRepository->persistNewRefreshToken($refreshToken);

                return $refreshToken;

            } catch (UniqueTokenIdentifierConstraintViolationException $e) {

                if ($maxGenerationAttempts === 0) {

                    throw $e;

                }

}

}

}

    private function genScopes($scopes)

{

        foreach ($scopes as $key => $scope) {

            if (is_string($scope)) {

                $scopes[$key] = new Scope($scope);

            }

}

        return $scopes;

    }

}



用户模型引用trait

namespace App\Models;

class User extends Authenticatable

{

    use HasApiTokens, HasFactory, Notifiable, HasRoles, PassportTrait;

}



生成token

$user = User::find(1);

$token = $user->createBearerToken(2, ['*']);

token结果为

 "token_type" => "Bearer",

    "expires_in" => 7199,

    "access_token" =>  "eyJ0eXAiOiJKV......",

    "refresh_token" => "def5020056704......"

]

你可能感兴趣的:(laravel8 passport 不使用http请求获取access_token和refresh_token)