Lumen HTTP基本身份验证,无需使用数据库


Lumen HTTP Basic Authentication without use of database

我正在使用Lumen创建一个RESTful API,并希望添加HTTP基本身份验证以确保安全。

routes.php文件上,它为每条路由设置auth.basic中间:

$app->get('profile', ['middleware' => 'auth.basic', function() {
     // logic here
}]);

现在,当我访问http://example-api.local/profile时,系统会提示我使用HTTP基本身份验证,这很好。但当我尝试登录时,我收到了以下错误消息:Fatal error: Class ''App'User' not found in C:'..'vendor'illuminate'auth'EloquentUserProvider.php on line 126

我不希望在数据库上对用户进行验证,因为我只有一个凭据,所以很可能它只会获取变量上的用户名和密码,并从那里进行验证。

顺便说一句,我通过这个laracast教程参考了它。虽然这是一个Laravel应用程序教程,但我正在Lumen应用程序上实现它。

我正在回答我自己的问题,因为我能够让它发挥作用,但仍然希望从其他人那里了解更多关于我的解决方案和正确的方法的见解。

我能够通过创建一个自定义中间件来实现这一点:

<?php
namespace App'Http'Middleware;
use Closure;
class HttpBasicAuth
{
    /**
     * Handle an incoming request.
     *
     * @param  'Illuminate'Http'Request  $request
     * @param  'Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $envs = [
            'staging',
            'production'
        ];
        if(in_array(app()->environment(), $envs)) {
            if($request->getUser() != env('API_USERNAME') || $request->getPassword() != env('API_PASSWORD')) {
                $headers = array('WWW-Authenticate' => 'Basic');
                return response('Unauthorized', 401, $headers);
            }
        }
        return $next($request);
    }
}

如果您仔细研究一下代码,它是非常基本的,并且运行良好。尽管我想知道是否有一种"Laravel"的方法来实现这一点,因为上面的代码是一个简单的PHP代码,可以进行HTTP基本身份验证。

如果您注意到,用户名和密码的验证在.env文件中是硬编码的,因为我认为不需要访问数据库进行验证。

检查您的bootstrap/app.php。确保您已经注册了auth.basic中间件,类似于以下内容:

$app->routeMiddleware([
    'auth.basic' => Illuminate'Auth'Middleware'AuthenticateWithBasicAuth::class,
]);

之后,更改路线:

$app->get('/profile', ['middleware' => 'auth.basic', function() {
    // Logic
}]);

编辑

如果您想使用database而不是eloquent身份验证,您可以调用:

Auth::setDefaultDriver('database');

在尝试验证之前:

Auth::attempt([
    'email' => 'info@foo.bar',
    'password' => 'secret',
]);

编辑#2

如果您希望以硬编码方式进行身份验证,您可以为AuthManager类定义自己的驱动程序:

Auth::setDefaultDriver('basic');
Auth::extend('basic', function () {
    return new App'Auth'Basic();
});

下面是App'Auth'Basic类的基础:

<?php
namespace App'Auth;
use Illuminate'Contracts'Auth'UserProvider;
use Illuminate'Contracts'Auth'Authenticatable;
class Basic implements UserProvider
{
    /**
     * Retrieve a user by their unique identifier.
     *
     * @param  mixed  $identifier
     * @return 'Illuminate'Contracts'Auth'Authenticatable|null
     */
    public function retrieveById($identifier)
    {
    }
    /**
     * Retrieve a user by their unique identifier and "remember me" token.
     *
     * @param  mixed   $identifier
     * @param  string  $token
     * @return 'Illuminate'Contracts'Auth'Authenticatable|null
     */
    public function retrieveByToken($identifier, $token)
    {
    }
    /**
     * Update the "remember me" token for the given user in storage.
     *
     * @param  'Illuminate'Contracts'Auth'Authenticatable  $user
     * @param  string  $token
     * @return void
     */
    public function updateRememberToken(Authenticatable $user, $token)
    {
    }
    /**
     * Retrieve a user by the given credentials.
     *
     * @param  array  $credentials
     * @return 'Illuminate'Contracts'Auth'Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        return new User($credentials);
    }
    /**
     * Validate a user against the given credentials.
     *
     * @param  'Illuminate'Contracts'Auth'Authenticatable  $user
     * @param  array  $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        $identifier = $user->getAuthIdentifier();
        $password = $user->getAuthPassword();
        return ($identifier === 'info@foobarinc.com' && $password === 'password');
    }
}

注意,validateCredentials方法需要的第一个参数是Illuminate'Contracts'Auth'Authenticatable接口的实现,所以您需要创建自己的User类:

<?php
namespace App'Auth;
use Illuminate'Support'Fluent;
use Illuminate'Contracts'Auth'Authenticatable;
class User extends Fluent implements Authenticatable
{
    /**
     * Get the unique identifier for the user.
     *
     * @return mixed
     */
    public function getAuthIdentifier()
    {
        return $this->email;
    }
    /**
     * 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()
    {
    }
    /**
     * Set the token value for the "remember me" session.
     *
     * @param  string  $value
     * @return void
     */
    public function setRememberToken($value)
    {
    }
    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName()
    {
    }
}

您可以通过Auth::attempt方法测试自己的驱动程序:

Auth::setDefaultDriver('basic');
Auth::extend('basic', function () {
    return new App'Auth'Basic();
});
dd(Auth::attempt([
    'email' => 'info@foobarinc.com',
    'password' => 'password',
])); // return true

首先,我们将在中间件中扩展AuthenticateWithBasicAuth。

<?php
 namespace App'Http'Middleware;
 use 'Illuminate'Auth'Middleware'AuthenticateWithBasicAuth;

 class HttpBasicAuth extends AuthenticateWithBasicAuth
 {
 }

在config/auth.php中创建自定义保护,我们将使用custom_http_guard和HttpBasicAuth。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
    ],
    'custom_http_guard' => [
        'driver' => 'token',
        'provider' => 'custom_http_provider',
    ],
],

我们将使用Laravel的默认"令牌"驱动程序。

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App'User::class,
    ],
 'custom_http_provider' => [
     'data' => [
         'email' => 'info@foo.bar',
         'password' => 'secret',
      ]
 ],
],

如果你能找到像上面那样返回数据的方法。然后,您可以按照laravel标准来摇滚并获得代码。

希望你有这个想法!寻找最终解决方案。如果有人能完成:)

Vaibhav Arora