Laravel 4 - 硬编码身份验证

Posted

技术标签:

【中文标题】Laravel 4 - 硬编码身份验证【英文标题】:Laravel 4 - Hardcoded authentication 【发布时间】:2015-07-22 12:25:03 【问题描述】:

我想创建身份验证机制不需要数据库,只有一个知道正确用户名和密码(我会硬编码)的人(管理员)才能登录。我还是想用Auth::attempt()、Auth::check()等函数。

我发现我可以创建自己的User driver,但在我看来应该有更简单的东西。

也许这不是很好的解决方案,但我希望网站尽可能简单。

【问题讨论】:

尽可能简单意味着您可以简单地扩展attemptcheck 方法并实现一个简单的比较器功能,该功能只需检查请求输入是否正确组合了用户+通行证。 【参考方案1】:

接受的答案对我不起作用。每次登录都是成功的,但是在/home页面时,我又被重定向到了登录页面。

我发现这是由于用户没有作为经过身份验证的用户存储在会话中。为了解决这个问题,我必须在 User 模型类中实现 getAuthIdentifier 方法,并且还要实现 retrieveById 方法。

我还调整了我的解决方案以支持多个硬编码用户(它假定电子邮件是唯一的,因此我们也可以将其用作用户的 id):

1.app/config/auth.php

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

'credentials' => [
    'userA@email.com' => 'passA',
    'userB@email.com' => 'passB',
]

2.UserProvider

use \Illuminate\Auth\GenericUser;
use \Illuminate\Contracts\Auth\UserProvider;
use \Illuminate\Contracts\Auth\Authenticatable;

class ArrayUserProvider implements UserProvider

    private $credential_store;

    public function __construct(array $credentials_array)
    
        $this->credential_store = $credentials_array;
    

    // IMPORTANT: Also implement this method!
    public function retrieveById($identifier) 
        $username = $identifier;
        $password = $this->credential_store[$username];
        return new User([
            'email' => $username,
            'password' => $password,
        ]);
    

    public function retrieveByToken($identifier, $token)  
    public function updateRememberToken(Authenticatable $user, $token)  

    public function retrieveByCredentials(array $credentials)
    
        $username = $credentials['email'];

        // Check if user even exists
        if (!isset($this->credential_store[$username])) 
            return null;
        

        $password = $this->credential_store[$username];
        return new GenericUser([
            'email' => $username,
            'password' => $password,
            'id' => null,
        ]);
    

    public function validateCredentials(Authenticatable $user, array $credentials)
    
        return $credentials['email'] == $user->email && $credentials['password'] == $user->getAuthPassword();
    

3.app/Providers/AuthServiceProvider

use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider

...

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    
        Auth::provider('array', function($app, array $config) 
            // Return an instance of Illuminate\Contracts\Auth\UserProvider...
            return new ArrayUserProvider($app['config']['auth.credentials']);
        );
    

4. 在 User.php(模型)中:

class User extends Authenticatable

    ...

    public function getAuthIdentifier()
    
        return $this->email;
    

更多信息:

对于所有感兴趣的人,为什么需要上述补充: 登录时会调用Illuminate\Auth\SessionGuard中的login方法。在这个方法中你会发现,用户的标识符存储在会话中$this->updateSession($user->getAuthIdentifier())。因此我们需要在我们的用户模型中实现这个方法。

当您在控制器中添加$this->middleware('auth') 时,会调用Illuminate\Auth\Middleware\Authenticate 中的方法authenticate()。这再次调用$this->auth->guard($guard)->check() 来检查用户是否经过身份验证。 check() 方法仅测试会话中是否存在用户(请参阅Illuminate\Auth\GuardHelpers)。它通过调用守卫的user() 方法来做到这一点,在这种情况下又是SessionGuard。在user()方法中,获取用户的方法是获取session中存储的id,调用retrieveById获取用户。

【讨论】:

【参考方案2】:

看起来应该有一些更简单的东西,但实际上,如果您想扩展身份验证系统,那就很简单了。您通过Auth 外观使用的所有方法(如attemptcheck 等)都在Illuminate\Auth\Guard 类中实现。此类需要将UserProviderInterface 实现注入到构造函数中才能工作。这意味着要使用 Auth 外观,您要么需要使用已经实现的 DatabaseUserProviderEloquentUserProvider,要么实现您自己的提供程序来处理您想要的简单登录。

虽然您链接到的文章可能看起来很长,但要实现您的需要,您可能会在提供程序中使用比您想象的要少得多的代码。以下是我认为您需要的:

1. 在您的 app/config/auth.php 中将驱动程序更改为 simple 并附加所需的登录凭据:

'driver' => 'simple',
'credentials' => array(
    'email'    => 'user@email.com',
    'password' => 'yourpassword'
)

2. 在您的 app 目录中创建一个名为 SimpleUserProvider.php 的文件,其中包含以下代码:

use Illuminate\Auth\UserInterface;
use Illuminate\Auth\GenericUser;
use Illuminate\Auth\UserProviderInterface;

class SimpleUserProvider implements UserProviderInterface 

    protected $user;

    public function __construct(array $credentials)
    
        $this->user = new GenericUser(array_merge($credentials, array('id' => null)));
    

    // If you only need to login via credentials the following 3 methods
    // don't need to be implemented, they just need to be defined
    public function retrieveById($identifier)  
    public function retrieveByToken($identifier, $token)  
    public function updateRememberToken(UserInterface $user, $token)  

    public function retrieveByCredentials(array $credentials)
    
        return $this->user;
    

    public function validateCredentials(UserInterface $user, array $credentials)
    
        return $credentials['email'] == $user->email && $credentials['password'] == $user->password;
    


3. 最后,您需要向身份验证系统注册新的提供商。您可以将其附加到 app/start/global.php 文件中:

Auth::extend('simple', function($app)

    return new SimpleUserProvider($app['config']['auth.credentials']);
);

这应该给你一个简单的(无数据库)用户身份验证,同时仍然能够使用 Laravel 的外观。

【讨论】:

谢谢,它成功了(几乎:))。我只需要将 app_path() . '/components', 添加到 ClassLoader::addDirectories 并将 SimpleUserProvider 添加到 app/components 目录。 其实我可以通过Auth::attemp,但是Auth::check总是返回false,即我总是客人。这是我的代码 sn-p:pastebin

以上是关于Laravel 4 - 硬编码身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在应用程序代码中安全地硬编码身份验证令牌 - Java

Google Calendar API v3 - 使用硬编码凭据进行身份验证

Angular 和 Laravel 身份验证 JWT?

身份验证 laravel 4.2 无法工作

Laravel 4.1 身份验证会话数据不会跨请求持久化

Laravel 4 身份验证注销错误