jsdecena/laravel-passport-multiauth

简单的 Laravel Passport 多用户认证

v0.2.4 2017-10-14 23:51 UTC

This package is auto-updated.

Last update: 2024-09-09 15:33:05 UTC


README

Latest Stable Version Total Downloads License

Laravel passport 默认行为是在 users 表上对 user 进行认证。

虽然这对大多数应用来说已经足够好,但有时如果出现新的需求,我们可能需要对其进行一点调整。

我创建了这个中间件,因为我需要一些用户组可以访问应用,并且每个用户组都有角色。

如何安装

  • 在您的终端中运行 composer require jsdecena/laravel-passport-multiauth 或将其添加到您的 composer.json
    "require": {
        ...
        "jsdecena/laravel-passport-multiauth": "^0.2",
        ...
    },
  • 在您的 config/app.php 中添加此行
	'providers' => [
	    ...
	    Jsdecena\LPM\LaravelPassportMultiAuthServiceProvider::class,
	    ...
	]
  • 在您的 app\Http\Kernel.php 中添加此行
    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        ...
        'mmda' => \Jsdecena\LPM\Middleware\ProviderDetectorMiddleware::class,
    ];
  • 同样在您的 routes/api.php
    Route::post('oauth/token/', 'CustomerTokenAuthController@issueToken')
        ->middleware(['mmda', 'throttle'])
        ->name('issue.token');

趣闻:为什么是 mmda?因为在菲律宾,他们是处理交通的人 😅

  • 并在 config/auth.php
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

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

        'customers' => [
            'driver' => 'passport',
            'provider' => 'customers'
        ],
    ],
    
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => 'App\User',
        ],
        /**
         * This is the important part. You can create as many providers as you like but right now, 
         * we just need the customer
         */
         'customers' => [
             'driver' => 'eloquent',
             'model' => 'App\Customer',
         ],
    ],

在您的控制器中,您可以通过 auth()->guard('customer')->user() 访问已登录的用户

  • 您的 Customer 模型应该扩展 Authenticatable 并使用 NotifiableHasApiTokens 特性
<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class Customer extends Authenticatable
{
    use Notifiable, HasApiTokens;

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

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
}

请注意,您需要 Customer 模型或您需要认证的任何模型。

  • 迁移客户表 php artisan vendor:publish --tag=migrations

  • 并在您的控制器中: App\Http\Controllers\Auth\CustomerTokenAuthController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Customers\Customer;
use App\Customers\Exceptions\CustomerNotFoundException;
use Illuminate\Database\ModelNotFoundException;
use Laravel\Passport\Http\Controllers\AccessTokenController;
use Laravel\Passport\TokenRepository;
use League\OAuth2\Server\AuthorizationServer;
use Psr\Http\Message\ServerRequestInterface;
use Lcobucci\JWT\Parser as JwtParser;

class CustomerTokenAuthController extends AccessTokenController
{
     /**
      * The authorization server.
      *
      * @var \League\OAuth2\Server\AuthorizationServer
      */
     protected $server;
    
     /**
      * The token repository instance.
      *
      * @var \Laravel\Passport\TokenRepository
      */
     protected $tokens;
    
     /**
      * The JWT parser instance.
      *
      * @var \Lcobucci\JWT\Parser
      */
     protected $jwt;
    
     /**
      * Create a new controller instance.
      *
      * @param  \League\OAuth2\Server\AuthorizationServer  $server
      * @param  \Laravel\Passport\TokenRepository  $tokens
      * @param  \Lcobucci\JWT\Parser  $jwt
      */
     public function __construct(AuthorizationServer $server,
                                 TokenRepository $tokens,
                                 JwtParser $jwt)
     {
         parent::__construct($server, $tokens, $jwt);
     }

     /**
      * Override the default Laravel Passport token generation
      *
      * @param ServerRequestInterface $request
      * @return array
      * @throws UserNotFoundException
      */
     public function issueToken(ServerRequestInterface $request)
     {
         $body = (parent::issueToken($request));
         $token = json_decode($body, true);
        
         if (array_key_exists('error', $token)) {
             return response()->json([
                 'error' => $token['error'],
                 'status_code' => 401
             ], 401);
         }
         
        $data = $request->getParsedBody();
        
        $email = $data['username'];  
           
        switch ($data['provider']) {
            case 'customers';
                
                try {
                
                 $user = Customer::where('email', $email)->firstOrFail();
                 
                } catch (ModelNotFoundException $e) {
                  return response()->json([
                      'error' => $e->getMessage(),
                      'status_code' => 401
                  ], 401);
                }
            
                break;
            
            default :
            
                try {
                
                 $user = User::where('email', $email)->firstOrFail();
                 
                } catch (ModelNotFoundException $e) {
                  return response()->json([
                      'error' => $e->getMessage(),
                      'status_code' => 401
                  ], 401);
                }        
        }
         
        return compact('token', 'user');
    }
}
  • 认证请求必须包含 provider 键,这样系统就会知道要认证哪个用户

例如。

POST /api/oauth/token HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache

grant_type=password&username=test%40email.com&password=secret&provider=customers

如果没有传递提供者参数,它将默认查找 users 表,就像通常一样。