Laravel:如何在没有数据库的情况下对用户进行身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50602198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 17:46:37  来源:igfitidea点击:

Laravel: How to authenticate users without DB

phplaravellaravel-5laravel-5.6

提问by Hiroki

As the title suggests, is it possible to authenticate without DB (instead, using User Provider)?

正如标题所暗示的,是否可以在没有数据库的情况下进行身份验证(而是使用用户提供程序)?

I've seen posts about how to authenticate without password, but would it be ever possible to authenticate without DB?

我看过有关如何在没有密码的情况下进行身份验证的帖子,但是是否有可能在没有DB 的情况下进行身份验证?

Here is what I've been trying to achieve...

这是我一直在努力实现的目标......

  1. Ask the user to submit a PIN
  2. Compare the PIN with a value within .env
  3. If the PIN is correct, authenticate the user
  1. 要求用户提交 PIN
  2. 将 PIN 与 .env 中的值进行比较
  3. 如果 PIN 正确,请验证用户

It seems to be possible to do authenticate without a traditional RDBMS by introducing a user provider.

通过引入用户提供程序,似乎可以在没有传统 RDBMS 的情况下进行身份验证

However, the doc doesn't seem to describe how the user provider should look like.

但是,该文档似乎并未描述用户提供程序的外观。

Here are snippets of my code (well, I simply mimicked the doc)...

这是我的代码片段(好吧,我只是模仿了文档)...

class AuthServiceProvider extends ServiceProvider {

    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('myUser', function ($app, array $config) {
            // Return an instance of Illuminate\Contracts\Auth\UserProvider...

            return new MyUserProvider($app->make('myUser'));
        });
    }
}

In auth.php...

auth.php...

'providers' => [
    'users' => [
        'driver' => 'myUser',
    ],
],

Now, I have no clue as to how to proceed.

现在,我不知道如何继续。

So, I'd like to know...

所以,我想知道...

  1. How the user providershould look like

  2. if it's possible to authenticate users with env()in the first place

  1. 怎么user provider看起来应该像

  2. 如果可能的话进行身份验证的用户env()放在首位

Any advice will be appreciated.

任何建议将被认真考虑。

回答by mpyw

Create your own Guardignoring UserProviderinterface. I adopted it in my project and it's working well.

创建您自己的Guard忽略UserProvider界面。我在我的项目中采用了它,并且运行良好。

PinGuard.php

PinGuard.php

<?php

declare(strict_types=1);

namespace App\Auth\Guards;

use App\User;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;

/**
 * Class PinGuard
 */
class PinGuard implements Guard
{
    /**
     * @var null|Authenticatable|User
     */
    protected $user;

    /**
     * @var Request
     */
    protected $request;

    /**
     * OpenAPIGuard constructor.
     *
     * @param Request $request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Check whether user is logged in.
     *
     * @return bool
     */
    public function check(): bool
    {
        return (bool)$this->user();
    }

    /**
     * Check whether user is not logged in.
     *
     * @return bool
     */
    public function guest(): bool
    {
        return !$this->check();
    }

    /**
     * Return user id or null.
     *
     * @return null|int
     */
    public function id(): ?int
    {
        $user = $this->user();
        return $user->id ?? null;
    }

    /**
     * Manually set user as logged in.
     * 
     * @param  null|\App\User|\Illuminate\Contracts\Auth\Authenticatable $user
     * @return $this
     */
    public function setUser(?Authenticatable $user): self
    {
        $this->user = $user;
        return $this;
    }

    /**
     * @param  array $credentials
     * @return bool
     */
    public function validate(array $credentials = []): bool
    {
        throw new \BadMethodCallException('Unexpected method call');
    }

    /**
     * Return user or throw AuthenticationException.
     *
     * @throws AuthenticationException
     * @return \App\User
     */
    public function authenticate(): User
    {
        $user = $this->user();
        if ($user instanceof User) {
            return $user;
        }
        throw new AuthenticationException();
    }

    /**
     * Return cached user or newly authenticate user.
     *
     * @return null|\App\User|\Illuminate\Contracts\Auth\Authenticatable
     */
    public function user(): ?User
    {
        return $this->user ?: $this->signInWithPin();
    }

    /**
     * Sign in using requested PIN.
     *
     * @return null|User
     */
    protected function signInWithPin(): ?User
    {
        // Implement your logic here
        // Return User on success, or return null on failure
    }

    /**
     * Logout user.
     */
    public function logout(): void
    {
        if ($this->user) {
            $this->setUser(null);
        }
    }
}

NoRememberTokenAuthenticatable.php

NoRememberTokenAuthenticatable.php

Usershould mixin this trait.

User应该混合这个特性。

<?php

declare(strict_types=1);

namespace App\Auth;

use Illuminate\Database\Eloquent\Model;

/**
 * Trait NoRememberTokenAuthenticatable
 *
 * @mixin Model
 */
trait NoRememberTokenAuthenticatable
{
    /**
     * 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
     * @codeCoverageIgnore
     */
    public function getAuthPassword()
    {
        throw new \BadMethodCallException('Unexpected method call');
    }

    /**
     * Get the token value for the "remember me" session.
     *
     * @return string
     * @codeCoverageIgnore
     */
    public function getRememberToken()
    {
        throw new \BadMethodCallException('Unexpected method call');
    }

    /**
     * Set the token value for the "remember me" session.
     *
     * @param string $value
     * @codeCoverageIgnore
     */
    public function setRememberToken($value)
    {
        throw new \BadMethodCallException('Unexpected method call');
    }

    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     * @codeCoverageIgnore
     */
    public function getRememberTokenName()
    {
        throw new \BadMethodCallException('Unexpected method call');
    }
}

AuthServiceProvider.php

AuthServiceProvider.php

<?php

declare(strict_types=1);

namespace App\Providers;

use App\Auth\Guards\PinGuard;
use Illuminate\Container\Container;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [];

    /**
     * Register any authentication / authorization services.
     */
    public function boot()
    {
        Auth::extend('pin', function (Container $app) {
            return new PinGuard($app['request']);
        });
        $this->registerPolicies();
    }
}

config/auth.php

config/auth.php

You should comment out most of them.

您应该注释掉其中的大部分。

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' => 'pin',
        ],
        // 'api' => [
        //     'driver' => 'session',
        //     'provider' => 'users',
        // ],
        // 'web' => [
        //     'driver' => 'session',
        //     'provider' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | 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.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        // 'users' => [
        //     'driver' => 'eloquent',
        //     'model' => App\User::class,
        // ],
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    // 'passwords' => [
    //     'users' => [
    //         'provider' => 'users',
    //         'table' => 'password_resets',
    //         'expire' => 60,
    //     ],
    // ],

];

回答by Hiroki

Thank you all, but there was a much simpler solution... which is to use session().

谢谢大家,但有一个更简单的解决方案......那就是使用session().

In the controller,

在控制器中,

public function login(Request $request)
{
    if ($request->input('pin') === env('PIN')) {
        $request->session()->put('authenticated', time());
        return redirect()->intended('success');
    }

    return view('auth.login', [
        'message' => 'Provided PIN is invalid. ',
    ]);
    //Or, you can throw an exception here.
}

The route looks like,

路线看起来像,

Route::group(['middleware' => ['web', 'custom_auth']], function () {
    Route::get('/success', 'Controller@success')->name('success');
});

The custom_authwill looke like,

custom_auth会looke一样,

public function handle($request, Closure $next)
{
    if (!empty(session('authenticated'))) {
        $request->session()->put('authenticated', time());
        return $next($request);
    }

    return redirect('/login');
}

Hope this will help someone.

希望这会帮助某人。

回答by foram kantaria

If you know who the user is (IE: have a $user instance already), you can simply login without using any guards as shown in the documentation

如果您知道用户是谁(IE:已经有一个 $user 实例),您可以简单地登录而不使用任何守卫,如文档中所示

Auth::login($user);

I would pass in a User instance instead of $email/$password to your function

我会将 User 实例而不是 $email/$password 传递给您的函数

$user = User::whereEmail($email)->first();
$class->login($user);

and then in your class

然后在你的班级

public static function Login(User $user) 
{
// ...
 if(substr ( $result, 0, 3 ) == '+OK')
    Auth::login($user);
    return true; //user will be logged in and then redirect
 else
    return false;
 }