【问题标题】:Custom Laravel Passport Check自定义 Laravel 护照检查
【发布时间】:2017-12-28 06:11:24
【问题描述】:

是否有另外 1 个变量添加或传递给 findForPassport ?

在默认 laravel 护照登录中,我只能传递 2 个变量(用户名、密码),但我想再传递 1 个变量并检查 findForPassport 用户是否属于其他表。

【问题讨论】:

标签: laravel laravel-passport


【解决方案1】:

来自the link to passport issue #81 pointed by @Arun in OP

现在可能有更好的方法来执行此操作,但我扩展了 PassportServiceProvider 并复制了 registerAuthorizationServer 函数,以便我可以注册自己的授权类型。

将 config\app.php 中的提供程序替换为您的新提供程序:

'providers' => [
 //Laravel\Passport\PassportServiceProvider::class,
    App\Providers\PassportClientCredentialsServiceProvider::class,

更新了 registerAuthorizationServer 函数,包括新的授权选项:

protected function registerAuthorizationServer()
  {
    parent::registerAuthorizationServer();
    $this->app->singleton(AuthorizationServer::class, function () {
      return tap($this->makeAuthorizationServer(), function ($server) {
        /**
         * @var $server AuthorizationServer
         */
        $server->enableGrantType(
          new ClientCredentialsGrant(), Passport::tokensExpireIn()
        );
        /** custom grant type */
        $server->enableGrantType(
          new PasswordOverrideGrant(
            $this->app->make(UserRepository::class),
            $this->app->make(RefreshTokenRepository::class)
          ), Passport::tokensExpireIn()
        );

        $server->enableGrantType(
          $this->makeAuthCodeGrant(), Passport::tokensExpireIn()
        );

        $server->enableGrantType(
          $this->makeRefreshTokenGrant(), Passport::tokensExpireIn()
        );

        $server->enableGrantType(
          $this->makePasswordGrant(), Passport::tokensExpireIn()
        );

        $server->enableGrantType(
          new PersonalAccessGrant(), new \DateInterval('P1Y')
        );
      });
    });
  }

PasswordOverrideGrant 如下所示:

<?php

namespace App\Auth;

use App\User;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\PasswordGrant;
use League\OAuth2\Server\RequestEvent;
use Psr\Http\Message\ServerRequestInterface;

class PasswordOverrideGrant extends PasswordGrant
{
  protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
  {
    $username = $this->getRequestParameter('username', $request);
    if (is_null($username)) {
      throw OAuthServerException::invalidRequest('username');
    }

    $custom_hash_token = $this->getRequestParameter('hash_token', $request);
    if (is_null($custom_hash_token)) {
      throw OAuthServerException::invalidRequest('identifier');
    }

    $credentials = [
      'username' => $username,
      'hash_token' => $custom_hash_token,
    ];

    $user = User::where($credentials)->first();

    if ($user instanceof User === false) {
      $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));

      throw OAuthServerException::invalidCredentials();
    }

    return $user;
  }
  public function getIdentifier()
  {
    return 'password_override';
  }
}

【讨论】:

    【解决方案2】:

    我希望这个答案可以对其他人有所帮助。
    如果要添加变量并将此变量传递给 User Authenticate 模型中的 findPassport 函数,则需要更新护照中的 3 类:
    - UserRepositoryInterface 在 vendor\league\oauth2-server\src\Repositories\UserRepositoryInterface
    - PasswordGrant 在 vendor\league\oauth2-server\src\Grant\PasswordGrant
    - UserRepository 在 vendor\laravel\passport\src\Bridge\UserRepository

    在示例代码中,我将添加父变量,代码将如下所示

    +在UserRepositoryInterface类中

    interface UserRepositoryInterface extends RepositoryInterface
    {
    
    /**
     * Get a user entity.
     *
     * @param string                $username
     * @param string                $password
     * @param string                $grantType    The grant type used
     * @param ClientEntityInterface $clientEntity
     *
     * @return UserEntityInterface
     */
    public function getUserEntityByUserCredentials(
        $username,
        $password,
        $parent,                           <------variable example 
        $grantType,
        ClientEntityInterface $clientEntity
    );
    }
    

    +在 PasswordGrant 类中

    class PasswordGrant extends AbstractGrant{ 
    protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
    {
        $username = $this->getRequestParameter('username', $request);
        if (is_null($username)) {
            throw OAuthServerException::invalidRequest('username');
        }
    
        $password = $this->getRequestParameter('password', $request);
        if (is_null($password)) {
            throw OAuthServerException::invalidRequest('password');
        }
    
      /**
      * Get a user parent.
      * varaible example 
      */
        $parent = $this->getRequestParameter('parent', $request);  
        if (is_null($parent)) {
            throw OAuthServerException::invalidRequest('password');
        }
    
        $user = $this->userRepository->getUserEntityByUserCredentials(
            $username,
            $password,
            $parent,                          <--- variable example get from request
            $this->getIdentifier(),
            $client
        );
        if ($user instanceof UserEntityInterface === false) {
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
    
            throw OAuthServerException::invalidCredentials();
        }
    
        return $user;
    }  }
    

    +在 UserRepository 类中

    class UserRepository implements UserRepositoryInterface
    {
    
    public function getUserEntityByUserCredentials($username, $password, $parent, $grantType, ClientEntityInterface $clientEntity) 
    /*add 1more parameter that implement from UserRepositoryInterface*/
    {
        $provider = config('auth.guards.api.provider');
    
        if (is_null($model = config('auth.providers.'.$provider.'.model'))) {
            throw new RuntimeException('Unable to determine authentication model from configuration.');
        }
    
        if (method_exists($model, 'findForPassport')) {
            $user = (new $model)->findForPassport($username,$parent);    <--- finally we pass parent variable to findForPassport here
        } else {
            $user = (new $model)->where('email', $username)->first();
        }
    
        if (! $user) {
            return;
        } elseif (method_exists($user, 'validateForPassportPasswordGrant')) {
            if (! $user->validateForPassportPasswordGrant($password)) {
                return;
            }
        } elseif (! $this->hasher->check($password, $user->getAuthPassword())) {
            return;
        }
    
        return new User($user->getAuthIdentifier());
    }
    }
    

    然后你可以从 findForPassport 的参数中获取 $parent 值。但请确保你以 eloquent User 的形式返回值。如果你想加入表格,你可以在下面查看我的示例代码

    class User extends Authenticatable{
    
    ..........
    public function findForPassport($identifier,$parent) {
        $a = $this
            ->Join('role as r', 'r.user_id', '=', 'users.id')
            ->get();
        return $a->where('name', $identifier)->where('role_id',$parent)->first();
    
      }
    }
    

    【讨论】:

    • 修改供应商文件?真的吗?这个答案差点让我得了癌症>_
    • 修改供应商文件从来都不是一个好主意,只要作曲家更新所有更改都会消失。
    猜你喜欢
    • 2017-03-29
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2017-07-27
    • 2014-12-07
    • 2017-05-18
    相关资源
    最近更新 更多