我可以在会话中将用户信息放入和检索到Laravel自定义用户提供程序吗?

时间:2017-01-28 17:47:43

标签: php laravel session laravel-5 laravel-5.3

我不是 PHP Laravel ,我有以下问题,我来自 Java

我正在按照本教程实施自定义用户提供程序

https://blog.georgebuckingham.com/laravel-52-auth-custom-user-providers-drivers/

我正在使用 Larave 5.3 版本。

我简要地说明了我需要的东西:我的 Laravel 应用程序只是一个前端应用程序,包括用户身份验证在内的所有业务逻辑都由 Java后端应用程序,公开REST Web服务

拨打电话:

http://localhost:8080/Extranet/login

并传递用户名密码作为基本身份验证我获得了一个代表已登录用户的 JSON 响应:

{
  "userName": "Painkiller",
  "email": "painkiller@gmail.com",
  "enabled": true
}

因此,在我的 Laravel 应用程序中,我必须执行此调用,然后解析先前返回的 JSON 对象,以将经过身份验证的对象生成到前端应用程序会话中。

要做到这一点,我已经实现了之前的教程(似乎有效),实现了名为 UserProvider 自定义用户提供程序类,该类实现了Laravel IlluminateUserProvider < / strong>界面:

<?php

namespace App\Authentication;

use Illuminate\Auth\GenericUser;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider as IlluminateUserProvider;
use GuzzleHttp\Client;
use function GuzzleHttp\json_encode;
use function GuzzleHttp\json_decode;
use Illuminate\Support\Facades\Log;

class UserProvider implements IlluminateUserProvider
{
    public function retrieveById($identifier)
    {
        // TODO: Implement retrieveById() method.
        \Log::info('retrieveById START');

        // PERFORM THE CALL TO MY BACK END WB SERVICE AND CREATE A NEW GenericUser USING THESE INFORMATION:

        $attributes = array(
            'id' => 123,
            'username' => 'nobili.andrea@gmail.com',
            'password' => \Hash::make('SuperSecret'),
            'name' => 'Dummy User',
        );

        $user = new GenericUser($attributes);

        return $user;

    }

    public function retrieveByToken($identifier, $token)
    {
        // TODO: Implement retrieveByToken() method.
        \Log::info('retrieveByToken START');
    }

    public function updateRememberToken(Authenticatable $user, $token)
    {
        // TODO: Implement updateRememberToken() method.
        \Log::info('updateRememberToken START');
    }

    public function retrieveByCredentials(array $credentials) {

        // TODO: Implement retrieveByCredentials() method.

        \Log::info('retrieveByCredentials START');
        \Log::info('INSERTED USER CREDENTIAL: '.$credentials['email'] . ' ' .$credentials['password']);

        $client = new Client(); //GuzzleHttp\Client

        $response = $client->get('http://localhost:8080/Extranet/login',
            [
                'auth' => [
                    'nobili.andrea@gmail.com',
                    'pswd'
                ]
            ]);

        $dettagliLogin = json_decode($response->getBody());

        \Log::info('response: '.(json_encode($dettagliLogin)));

        //$user = new User('Pippo', 'pippo@google.com', true);

        $attributes = array(
            'id' => 123,
            'username' => 'nobili.andrea@gmail.com',
            'password' => \Hash::make('SuperSecret'),
            'name' => 'Dummy User',
        );

        $user = new GenericUser($attributes);

        \Log::info('USER: '.(json_encode($user)));

        return $user;


    }

    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        // TODO: Implement validateCredentials() method.
        \Log::info('validateCredentials START');
        return true;
    }

}

这只是一个初步测试,因此返回的数据被模拟。

它以这种方式运作:

1)当用户在登录页面(http://localhost:8000/login)中插入他的凭证时,它被称为 retrieveByCredentials()方法:

public function retrieveByCredentials(array $credentials) {

    // TODO: Implement retrieveByCredentials() method.

    \Log::info('retrieveByCredentials START');
    \Log::info('INSERTED USER CREDENTIAL: '.$credentials['email'] . ' ' .$credentials['password']);

    $client = new Client(); //GuzzleHttp\Client

    $response = $client->get('http://localhost:8080/Extranet/login',
        [
            'auth' => [
                'nobili.andrea@gmail.com',
                'pswd'
            ]
        ]);

    $dettagliLogin = json_decode($response->getBody());

    \Log::info('response: '.(json_encode($dettagliLogin)));

    //$user = new User('Pippo', 'pippo@google.com', true);

    $attributes = array(
        'id' => 123,
        'username' => 'nobili.andrea@gmail.com',
        'password' => \Hash::make('SuperSecret'),
        'name' => 'Dummy User',
    );

    $user = new GenericUser($attributes);

    \Log::info('USER: '.(json_encode($user)));

    return $user;

}

执行Web服务调用以获取与此用户相关的用户信息。然后,这些凭证由 validateCredentials()方法验证(此时每次都返回 true )。 Finnaly它返回一个 GenericUser 对象,其中包含已登录用户的信息(此时被模拟,因为这是一个测试,我还没有准备好我的Web服务所反复的 JSON

然后,当用户访问下一页(成功登录后)在我看来称为 retrieveById($ identifier)方法时,这个:

public function retrieveById($identifier)
{
    // TODO: Implement retrieveById() method.
    \Log::info('retrieveById START');

    // PERFORM THE CALL TO MY BACK END WB SERVICE AND CREATE A NEW GenericUser USING THESE INFORMATION:

    $attributes = array(
        'id' => 123,
        'username' => 'nobili.andrea@gmail.com',
        'password' => \Hash::make('SuperSecret'),
        'name' => 'Dummy User',
    );

    $user = new GenericUser($attributes);

    return $user;

}

此时逻辑是它使用先前登录用户的id来执行对后端Web服务的调用,再次获取这些信息并创建相同的 GenericUser 对象返回到使用它的下一页。现在我嘲笑这些用户信息。

好的,这样可行,但出于安全原因,我不能这样做。

所以我的想法是:当我在 retrieveByCredentials(数组$凭证)中检索用户信息时,在检查了正确之后,我会将此 GenericUser 对象放入进入会议。

然后在 retrieveById()方法中,我将从会话中检索这些信息。

我可以这样做吗?可能是一个聪明的方式?如何在会话中放入和检索对象\数据(我不是PHP和前端)

TNX

3 个答案:

答案 0 :(得分:1)

是的,你可以。

使用Laravel的身份验证API登录用户时,它会自动存储在应用程序的会话中。所以你正在做的事情完全没问题。

当您通过- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; // Configure the cell... NSString *sectionTitle = [scheduleSectionTitles objectAtIndex:indexPath.section]; NSArray *sectionAnimals = [schedule objectForKey:sectionTitle]; NSString *prepschedule = [sectionAnimals objectAtIndex:indexPath.row]; cell.textLabel.text = prepschedule; //Configure cell return cell; } 获取用户实例时,您不必担心retrieveByCredentials等方法会引发对您的REST API的调用。每次调用此方法时,它都会检查是否有用户已经插入。如果有,则只返回用户,否则,它会进行必要的调用以查找该用户。

但我建议将这些调用放在另一个类的REST API中。 Auth::user()只有UserProvider显示Laravel如何检索用户,因此它应该使用responsibility来调用其他对象来执行在某处找到某些内容的肮脏工作。

您可以详细了解delegation课程如何在laravel来源中发挥作用:

https://github.com/laravel/framework/blob/5.4/src/Illuminate/Auth/SessionGuard.php

答案 1 :(得分:0)

这样做的时候

$user = new GenericUser($attributes);

您可以遵循

Auth::login($user);

现在,您的所有User属性都存储在会话中,可以通过调用来检索

$user = Auth::user();

答案 2 :(得分:0)

我就是这样解决的。它还需要改进,但至少可以用作一般指南。

<块引用>

注意:我正在使用 PHP 8 并利用构造函数属性提升,所以也许您必须分配实例变量。我也在使用 Laravel 8。

  1. 实现实现该方法的 API 网关:
function authenticate(string $username, string $password): ?APIUser {}

创建 API 用户模型:

<?php

namespace App\Auth;

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Facades\Hash;

final class APIUser implements Authenticatable
{

    function __construct(
        private $id,
        private $username,
        private $password,
        private $access_token,
        private $remember_token,
        private $expires_in,
        private $platform_id,
    ) {
        $this->password = Hash::make($this->password);
    }


    function getUsername()
    {
        return $this->username;
    }

    function getAccessToken()
    {
        return $this->access_token;
    }

    function getExpiresIn()
    {
        return $this->expires_in;
    }

    function getPlatformId()
    {
        return $this->platform_id;
    }

    /**
     * 
     * Authenticatable section
     * 
     */

    /**
     * Get the name of the unique identifier for the user.
     * @return string
     */
    public function getAuthIdentifierName()
    {
        return 'id';
    }

    /**
     * Get the unique identifier for the user.
     * @return mixed
     */
    public function getAuthIdentifier()
    {
        return $this->id;
    }

    /**
     * Get the password for the user.
     * @return string
     */
    public function getAuthPassword()
    {
        return $this->password;
    }

    /**
     * Get the token value for the "remember me" session.
     * @return string
     */
    public function getRememberToken()
    {
        $this->remember_token;
    }

    /**
     * Set the token value for the "remember me" session.
     * @param string $value
     * @return void
     */
    public function setRememberToken($value)
    {
        $this->remember_token = $value;
    }

    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName()
    {
        return 'remember_token';
    }
}

  1. 创建用户提供程序:
<?php

namespace App\Auth;

use App\Ports\AppAPIGateway;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Session\Session;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

class APIUserProvider implements UserProvider
{
    function __construct(
        private AppAPIGateway $api,
        private Session $session
    ) {
    }

    public function retrieveById($identifier)
    {
        if ($this->session->has('user')) {
            return $this->session->get('user');
        }
        return;
    }

    public function retrieveByToken($identifier, $token)
    {
        Log::info('APIUserProvider: retrieveByToken (not implemented)');
        return null;
    }

    public function updateRememberToken(Authenticatable $user, $token)
    {
        $user->setRememberToken($token);
    }

    public function retrieveByCredentials(array $credentials)
    {
        if (
            !array_key_exists('username', $credentials)
            ||
            !array_key_exists('password', $credentials)
        ) {
            throw new AuthenticationException('Could not retrieve credentials: missing parameters');
        }

        $user = $this->api->authenticate(
            $credentials['username'],
            $credentials['password']
        );

        $this->session->put('user', $user);
        $this->session->save();

        return $user;
    }

    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        if (
            !array_key_exists('username', $credentials)
            ||
            !array_key_exists('password', $credentials)
        ) {
            throw new AuthorizationException('Could not validate credentials: missing parameters');
        }

        return
            $user->getUsername() == $credentials['username']
            && Hash::check($credentials['password'], $user->getAuthPassword());
    }
}
  1. 修改app/Providers/AuthServiceProvider.php
    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('api_driver', function ($app, array $config) {
            return new APIUserProvider(
                $app->make('App\Ports\AppAPIGateway'),
                $app->make('Illuminate\Contracts\Session\Session')
            );
        });
    }
  1. config/auth.php 中启用此新提供程序:
    'defaults' => [
        'guard' => 'api_guard',
        'passwords' => 'api_provider',
    ],
...
    'guards' => [
        'api_guard' => [
            'driver' => 'session',
            'provider' => 'api_provider',
        ],
    ],
...
    'providers' => [
        'api_provider' => [
            'driver' => 'api_driver',
        ],
    ],