Maison  >  Questions et réponses  >  le corps du texte

Comment utiliser le fournisseur de services de Laravel pour l'utilisation d'API externes (en tirant parti des informations d'identification basées sur l'utilisateur)

Je développe donc une application d'administration Laravel qui utilise une API externe, appelons-la PlatformAPI. Le fonctionnement de la plateforme est que les utilisateurs de mon application disposent d'un compte sur la plateforme. Mon application Laravel agira comme un tableau de bord d'administration afin que les utilisateurs puissent afficher certains rapports de base obtenus à partir de PlatformAPI.

Chaque utilisateur de mon application doit ajouter son identifiant client et son secret client, qu'il peut créer dans la plateforme. De cette façon, mon application pourra effectuer des requêtes auprès de PlatformAPI en leur nom en utilisant les informations d'identification de l'utilisateur.

J'ai lu des articles et des tutoriels qui décrivent essentiellement comment configurer des informations d'identification/jetons pour un service et lier ce service à un fournisseur de services comme ceci :

<?php

namespace AppServicesPlatformAPI;

class Client
{
    protected string $clientId;
    protected string $clientSecret;

    public function __construct(string $clientId, string $clientSecret)
    {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
    }

    public function getSales(string $month)
    {
        // ...
    }
}


<?php

use AppServicesPlatformApiClient;

class PlatformApiServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(Client::class, function ($app) {
            return new Client(
                clientId: config('services.platform-api.client-id'),
                clientSecret: config('services.platform-api.client-secret'),
            );
        });
    }
}

De cette façon, vous n'avez pas besoin de définir les informations d'identification du client à chaque fois que vous souhaitez utiliser PlatformApi, je peux simplement appeler le service comme ceci :

<?php

namespace AppHttpControllers;

use AppServicesPlatformApiClient;

class RandomController extends Controller
{

    protected Client $client;    

    public function __construct(Client $client)
    {
        $this->client = $client;
    }

    public function index()
    {
        $this->client->getSales(string $month);
    }
}

Cependant, comme je dois effectuer des requêtes auprès de PlatformApi au nom de l'utilisateur de mon application en utilisant les informations d'identification qu'il fournit (et les stocker dans la base de données de mon application), je ne sais pas si cette même approche fonctionnera comme le singleton. être instancié une seule fois ?

De plus, pour utiliser PlatformApi, je dois obtenir un jeton d'accès en utilisant les informations d'identification de l'utilisateur. Ce jeton d'accès doit également être stocké quelque part (dans le cache je suppose).

Je ne sais pas trop comment résoudre ce problème. Tous les indicateurs seraient grandement appréciés.

P粉465675962P粉465675962334 Il y a quelques jours443

répondre à tous(1)je répondrai

  • P粉523625080

    P粉5236250802023-12-14 13:41:31

    Je suppose que toutes vos applications utiliseront ce service client. Si tel est le cas, vous pouvez continuer à utiliser le modèle de conception singleton (pour arrêter d'autres requêtes oauth), mais essayez de séparer la logique de la méthode d'enregistrement du fournisseur. Vous pouvez retourner un access_token 的私有方法后实例化 Client 类(如果存在有效令牌,则检查 DB / Cache expires_in 时间戳值并返回它,或者向用户请求一个新的client/secret valide dans l'appel et le retourner)

    /**
         * Register any application services.
         *
         * @return void
         */
        public function register(): void
        {
            $this->app->singleton(Client::class, function () {
                return new Client(
                    accessToken: $this->getUserToken()->access_token
                );
            });
        }
    
        /**
         * Tries to get the user token from the database.
         *
         * @return ClientCredentials
         */
        private function getUserToken(): ClientCredentials
        {
            $credentials = ClientCredentials::query()
                ->latest()
                ->find(id: auth()->user()->id);
    
            if ($credentials === null || now() > $credentials->expires_at) {
                $credentials = $this->requestUserToken();
            }
    
            return $credentials;
        }
    
        /**
         * Requests a new token for the user & stores it in the database.
         *
         * @return ClientCredentials
         */
        private function requestUserToken(): ClientCredentials
        {
            $tokenResponse = API::requestToken(
                client: auth()->user()->client,
                secret: auth()->user()->secret,
            );
            
            return ClientCredentials::query()->create(
                attributes: [
                    'user_id' => auth()->user()->id,
                    'access_token' => $tokenResponse['access_token'],
                    'refresh_token' => $tokenResponse['refresh_token'],
                    'token_type' => 'Bearer',
                    'expires_at' => new DateTime(datetime: '+' . $tokenResponse['expires_in'] . ' seconds')
                ],
            );
        }

    répondre
    0
  • Annulerrépondre