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
Laravel: How to authenticate users without DB
提问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...
这是我一直在努力实现的目标......
- Ask the user to submit a PIN
- Compare the PIN with a value within .env
- If the PIN is correct, authenticate the user
- 要求用户提交 PIN
- 将 PIN 与 .env 中的值进行比较
- 如果 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...
所以,我想知道...
How the
user provider
should look likeif it's possible to authenticate users with
env()
in the first place
怎么
user provider
看起来应该像如果可能的话进行身份验证的用户
env()
放在首位
Any advice will be appreciated.
任何建议将被认真考虑。
回答by mpyw
Create your own Guard
ignoring UserProvider
interface. 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
User
should 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_auth
will 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;
}