7
votes

Comment activer à la fois l'API et la protection Web dans Laravel

{
    "access_token": true,
    "token_type": "bearer",
    "expires_in": 31536000,
    "status": 200,
    "response": "Successfully login"
}

15 commentaires

Je ne sais pas quel est le cas d'utilisation ici.


@apokryfos d'accord, laissez-moi essayer d'expliquer mon problème.Si j'utilise api guard, je ne pourrai pas me connecter via l'application Web et si j'utilise web guard non du point de terminaison api fonctionnera, comment puis-je activer les deux?


Vous pouvez utiliser auth: api, web comme middleware où vous auriez généralement auth comme middleware pour que la vérification d'authentification fonctionne avec les deux.


@apokryfos, je dois donc utiliser auth: api, web dans les routes web.php et api.php?


Si vous voulez que les deux fonctionnent pour les deux, alors oui. Cependant, je pense que c'est une mauvaise pratique. Les routes API ne doivent autoriser l'authentification API que car l'authentification Web utilise généralement la session que les routes API n'utilisent pas de toute façon. Si j'étais toi, je prendrais du recul et repenserais toute ma stratégie


@apokryfos J'ai essayé, mais il est à nouveau redirigé vers la page de connexion.


@apokryfos quelle serait la meilleure façon de travailler avec le Web et l'API?


@apokryfos Faites-moi savoir aussi, si j'ai besoin de partager quelque chose de plus?


Pouvez-vous s'il vous plaît montrer vos routes web.php et api.php @PrafullaKumarSahu


@LimKeanPhang J'ai édité la question, veuillez la vérifier.


Donc web.php fonctionne alors que api.php ne fonctionne pas? @PrafullaKumarSahu


@LimKeanPhang oui, maintenant je peux activer n'importe lequel d'entre eux.


@PrafullaKumarSahu J'ai fait de légers ajustements et ajouté l'espace de noms dans la route api, je recommanderai d'utiliser postman pour tester l'API voir si cela fonctionne


@apokryfos J'ai mis à jour ma question, j'espère que cela rend un peu plus clair.


Continuons cette discussion en chat .


5 Réponses :


2
votes

Route API, vous devez utiliser postman de chrome / app pour tester l'API

return [

/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

Config / auth.php

Route::group(['prefix' => 'auth',namespace =>'App\Http\Controller'], function () {
    Route::post('login', 'Auth\AuthController@login')->name('api.login');

    Route::group(['middleware' => 'auth:api'], function () {

       Route::post('register', 'Auth\AuthController@register')->name('api.register');
        Route::post('forgot-password', 'Auth\ForgotPasswordController@forgotPassword')->name('api.forgot-password');
        Route::post('logout', 'Auth\AuthController@logout')->name('api.logout');
});
});


29 commentaires

J'obtiens Uncaught Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException dans pour le Web. Je veux que les deux fonctionnent.


J'ai mis à jour le code et rendre la structure plus claire, veuillez réessayer


J'obtiens Method Illuminate \\ Auth \\ SessionGuard :: factory n'existe pas. " cela fonctionnera si je le change la garde par défaut en api. Mais alors le Web ne fonctionnera pas.


Vous devez à la fois garder pas en ajoutant simplement auth | api se référer à la dernière mise à jour


J'ai ajouté mes pleasae auth.php, jetez-y un œil, j'y ajoute déjà les deux gardes.


Je serai mieux si vous le séparez ... je ne pense pas que je travaillerai de cette façon car le pilote pourrait être différent


Ensuite, comment puis-je permettre à la fois l'application Web et l'API de fonctionner? Pourriez-vous s'il vous plaît suggérer une idée car la plupart des points de terminaison du composant WebPart et de l'API sont déjà codés.


J'ai mis à jour le config / auth.php à partir de ma réponse, veuillez vérifier


Cela autorisera uniquement le Web et non l'API. vérifiez que ce n'est pas différent du auth.php que j'ai récemment ajouté à ma question.


Avez-vous essayé de faire fonctionner la page de connexion à partir de l'API? essayez de renvoyer dd ('123') du contrôleur et assurez-vous que votre URL est correcte


Les deux fonctionnent séparément, si je définirai la garde par défaut sur api, l'api fonctionne et si le paramètre est Web, le Web fonctionne.


Il n'est pas nécessaire de modifier la garde par défaut. avez-vous ajouté localhost / api / auth / .. lorsque vous appelez pour l'API?


Cela renvoie-t-il quelque chose? Pouvez-vous ajouter quelque chose de la fonction de connexion ou il y a une erreur. Réinitialisez le btw par défaut. Utilisez-vous un plugin jtw ou vous avez peut-être manqué la configuration là-bas


J'obtiens Method Illuminate \\ Auth \\ SessionGuard :: factory n'existe pas. cette erreur.


Contrôleur d'authentification s'il vous plaît. fonction construct__


`public function __construct () {$ this-> middleware ('auth: api', ['except' => ['login', 'register']]); } `


public function __construct () {$ this-> middleware ('guest') -> except ('logout'); } Votre contrôleur de connexion modifié?


Continuons cette discussion en chat .


Je reçois toujours Method Illuminate \\ Auth \\ SessionGuard :: factory n'existe pas.


non, je pense que c'est jwt expire time, qui n'a aucun rapport avec mon problème. Je vais encore essayer maintenant et vous le faire savoir.


jeton csrf sur formulaire?


J'ai également vérifié les modifications décrites dans le problème git, ce n'est pas grave, cela ne résoudra pas ce problème. Il est intéressant qu'aucun organisme n'ait fait face à cette situation, peut-être parce que tout le monde utilise l'api et certains frameworks js, pas blade, jquery pour l'application web, mais dans notre cas, on nous a demandé d'utiliser jquery et blade et nous ne pensions pas que tout faire via api uniquement, nous avons pensé qu'il y aurait un moyen de faire fonctionner les deux, en fait je crois toujours qu'il doit y avoir un moyen.


Hé, j'ai quelque chose, mais dans ce cas, je n'obtiens pas le jeton d'authentification dont j'aurai besoin. Permettez-moi de mettre à jour la question avec le changement et la sortie.


L'API et le Web fonctionnent donc déjà tous les deux? Le porteur est un jeton que vous obtenez une fois authentifié


oui les deux fonctionnent, mais après authentification, je ne reçois pas le jeton.


Je pense que c'est mieux d'ouvrir un nouveau message car le commentaire ici est surchargé et vous avez une réponse à votre question. Juste qu'il y a un nouveau problème


si je n'obtiens pas le jeton d'accès, les gens ne pourront jamais utiliser l'api, donc le problème n'est pas résolu, j'essaye peu de choses, si j'obtiens une solution, je la posterai comme réponse, oui, nous devrions en fait aller discuter.


Probablement une configuration manquante lors de la configuration de ces packages. Vérifiez simplement que le package global de jwt fera l'affaire. J'utilise en fait le passeport laravel au lieu de jwt, donc je ne peux pas fournir beaucoup d'aide pour le moment ~


J'ai ajouté une réponse, veuillez jeter un œil, cela fonctionne bien, mais j'ai toujours un problème. Nous pouvons discuter en chat ou plus tard, je posterai une autre question à ce sujet, si je ne pouvais pas la résoudre.



5
votes

J'ai changé le AuthController en quelque chose comme

Route::group([
    'middleware' => 'api',
    'prefix' => 'auth'
], function ($router) {

    Route::post('register', 'Auth\AuthController@register')->name('api.register');
    Route::post('forgot-password', 'Auth\ForgotPasswordController@forgotPassword')->name('api.forgot-password');
    Route::post('login', 'Auth\AuthController@login')->name('api.login');
    Route::middleware('jwt.auth')->post('logout', 'Auth\AuthController@logout')->name('api.logout');
    Route::middleware('auth')->post('refresh', 'Auth\AuthController@refresh')->name('api.refresh');
    Route::middleware('jwt.auth')->post('me', 'Auth\AuthController@me')->name('api.me');
});

Et dans api.php changer auth en jwt.auth résout le problème.

<?php

namespace App\Http\Controllers;

use Auth;
use Illuminate\Http\Request;

class AuthController extends Controller
{
    /**
     * Create a new AuthController instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
    }

    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login()
    {
        $credentials = request(['username', 'password']);

        $token = auth()->guard('api')->attempt($credentials);

        if (!$token) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $this->respondWithToken($token);
    }

    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth()->guard('api')->logout();

        return response()->json(['message' => 'Successfully logged out']);
    }

    /**
     * Refresh a token.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth()->refresh());
    }

    /**
     * Get the token array structure.
     *
     * @param string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type'   => 'bearer',
            'expires_in'   => auth('api')->factory()->getTTL() * 60,
        ]);
    }
}


2 commentaires

merci, ça m'aide beaucoup. Seulement définir une garde spécifique m'aide à résoudre le problème


@MayWeatherVN Je suis heureux que cela vous ait aidé.



0
votes

Je viens de rencontrer ce problème moi-même et je publie ma réponse au cas où quelqu'un la trouverait utile.

Dans mon cas, j'ai besoin que mon API soit accessible à la fois par mon site Web et par des clients externes. Le site Web utilise la protection session , car le navigateur inclut automatiquement tout cookie de session avec chaque demande. Les autres clients utilisent la protection api avec le pilote token , car ils ne gèrent pas les cookies, mais utilisent le champ token_id dans la table des utilisateurs .

// routes/api.php
Route::group(['middleware' => ['auth:web,api']], function () {
    Route::get('/abc', 'MyController@abc');
});

Je peux maintenant protéger mes itinéraires comme ceci:

// contig/auth.php
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
    ],
],

Notez le web, api code> syntaxe prise en charge par Laravel, mais non documentée. J'ai réalisé que c'était possible en analysant le code source de Laravel.


0 commentaires

-1
votes

Vous ne pouvez pas utiliser les deux guard (web et api) en même temps donc ce que vous devez faire est de générer le jwt en utilisant la fonction JWTAuth :: try comme ci-dessous.

  1. ajoutez le code ci-dessous en haut de l'AuthController
    public function login(){
            $credentials = request(['email', 'password']);

            if (! $token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'Unauthorized'], 401);
                }
                return response()->json(['status'=>200,'token'=>$token]);
    }
  1. mettre à jour la fonction de connexion avec le code ci-dessous.
use JWTAuth;
  1. Assurez-vous que dans auth.php vous utilisez Web Guard.

Cela générera le jeton et vous pourrez utiliser les deux gardes d'authentification.


1 commentaires

Veuillez vérifier la logique déjà implémentée et elle fonctionne, donc elle est vérifiée. Bienvenue à SO.



0
votes

La définition du pilote par défaut dans le constructeur fonctionne également:

private method guard() {
   return Auth::guard('api'); // Tymon\JWTAuth\JWTGuard
}

et si vous avez tout configuré correctement, appeler Auth :: guard () devrait renvoyer Tymon \ JWTAuth \ JWTGuard

vous pouvez également passer le pilote en tant que paramètre à la méthode guard comme ceci:

public function __construct() {
   auth()->setDefaultDriver('api');
}


0 commentaires