zegert/cakephp-two-factor-auth

该软件包已被废弃且不再维护。作者建议使用 https://github.com/andrej-griniuk/cakephp-two-factor-auth/releases/tag/3.1.0 软件包。

CakePHP 双因素认证组件和提供者

安装: 13

依赖项: 0

建议者: 0

安全: 0

星标: 0

关注者: 0

分支: 10

类型:cakephp-plugin

4.3 2024-03-27 09:18 UTC

This package is auto-updated.

Last update: 2024-04-03 13:07:31 UTC


README

Build Status codecov License

为 CakePHP 提供两因素认证功能的插件

此插件使用 RobThree/TwoFactorAuth 库提供两因素认证功能。基本上,它的工作方式与 CakePHP FormAuthenticate 相似。在提交正确的用户名/密码后,如果用户设置了 secret 字段,将被要求输入一次性的验证码。注意:它只提供认证提供者和组件,不负责用户的注册、管理等。

要求

  • CakePHP 4.0+(对于 CakePHP <3.7,使用 ^1.3 版本,对于 CakePHP <4.0,使用 ^2.0 版本)

安装

您可以使用 Composer 将此插件安装到您的 CakePHP 应用程序中。

composer require andrej-griniuk/cakephp-two-factor-auth

用法

首先,您需要将 secret 字段添加到您的用户表中(字段名可以根据 TwoFactorAuth.Form 认证器配置更改为其他名称)。

ALTER TABLE `users` ADD `secret` VARCHAR(255) NULL;

其次,您需要在 Application.php 中加载此插件

$this->addPlugin('TwoFactorAuth');

或者,执行以下命令

bin/cake plugin load TwoFactorAuth

您可以在 这里 查看默认配置值,并在 这里 了解它们的含义。要覆盖它们,请将它们作为 TwoFactorForm 认证器值传递。

然后,您需要像通常一样在 Application.php 中设置认证,但使用 TwoFactorForm 认证器而不是 Form,例如:

class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
    public function bootstrap(): void
    {
        // Call parent to load bootstrap from files.
        parent::bootstrap();

        $this->addPlugin('TwoFactorAuth');
        $this->addPlugin('Authentication');
    }

    public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
    {
        // Various other middlewares for error handling, routing etc. added here.

        // Create an authentication middleware object
        $authentication = new AuthenticationMiddleware($this);

        // Add the middleware to the middleware queue.
        // Authentication should be added *after* RoutingMiddleware.
        // So that subdirectory information and routes are loaded.
        $middlewareQueue->add($authentication);

        return $middlewareQueue;
    }

    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        $service = new AuthenticationService();
        $service->setConfig([
            'unauthenticatedRedirect' => '/users/login',
            'queryParam' => 'redirect',
        ]);

        $fields = [
            'username' => 'username',
            'password' => 'password'
        ];

        // Load the authenticators, you want session first
        $service->loadAuthenticator('Authentication.Session');
        $service->loadAuthenticator('TwoFactorAuth.TwoFactorForm', [
            'fields' => $fields,
            'loginUrl' => '/users/login'
        ]);

        // Load identifiers
        $service->loadIdentifier('Authentication.Password', compact('fields'));

        return $service;
    }
}

接下来,在 AppController 中加载 AuthenticationTwoFactorAuth 组件

// in src/Controller/AppController.php
public function initialize()
{
    parent::initialize();

    $this->loadComponent('Authentication.Authentication');
    $this->loadComponent('TwoFactorAuth.TwoFactorAuth');
}

一旦将中间件应用到您的应用程序中,您就需要一种让用户登录的方法。一个简单的 UsersController 看起来可能像这样

class UsersController extends AppController
{
    public function beforeFilter(\Cake\Event\EventInterface $event)
    {
        parent::beforeFilter($event);

        $this->Authentication->allowUnauthenticated(['login', 'verify']);
    }

    public function login()
    {
        $result = $this->Authentication->getResult();
        if ($result->isValid()) {
            // If the user is logged in send them away.
            $target = $this->Authentication->getLoginRedirect() ?? '/home';

            return $this->redirect($target);
        }

        if ($this->request->is('post') && !$result->isValid()) {
            if ($result->getStatus() == \TwoFactorAuth\Authenticator\Result::TWO_FACTOR_AUTH_FAILED) {
                // One time code was entered and it's invalid
                $this->Flash->error('Invalid 2FA code');

                return $this->redirect(['action' => 'verify']);
            } elseif ($result->getStatus() == \TwoFactorAuth\Authenticator\Result::TWO_FACTOR_AUTH_REQUIRED) {
                // One time code is required and wasn't yet entered - redirect to the verify action 
                return $this->redirect(['action' => 'verify']);
            } else {
                $this->Flash->error('Invalid username or password');
            }
        }
    }

    public function logout()
    {
        $this->Authentication->logout();

        return $this->redirect(['action' => 'login']);
    }

    public function verify()
    {
        // This action is only needed to render a vew with one time code form
    }
}

verify.php 可能看起来像这样

<div class="users form content">
    <?= $this->Form->create(null, ['url' => ['action' => 'login']]) ?>
    <fieldset>
        <legend><?= __('Please enter your 2FA code') ?></legend>
        <?= $this->Form->control('code') ?>
    </fieldset>
    <?= $this->Form->button(__('Continue')); ?>
    <?= $this->Form->end() ?>
</div>

基本上,它的工作方式与 CakePHP Authentication.Form 认证器相同。在输入正确的用户名/密码组合后,如果用户设置了 secret 字段(可以通过 TwoFactorAuth.TwoFactorForm 配置进行覆盖),则将重定向到 verify 操作,用户将要求输入一次性的验证码。此操作没有逻辑,它只是渲染一个表单,该表单需要再次提交到 loginAction,并设置 code 字段。

您可以通过 $this->TwoFactorAuth->getTfa() 从控制器访问 RobThree\Auth\TwoFactorAuth 实例,或者直接在 TwoFactorAuth 组件上调用一些方法。例如,您可以通过这种方式生成用户的密钥并获取其 QR 码数据 URI

$secret = $this->TwoFactorAuth->createSecret();
$secretDataUri = $this->TwoFactorAuth->getQRCodeImageAsDataUri('CakePHP:user@email.com', $secret);

然后,在视图中显示它

<img src="<?= $secretDataUri ?>" />

有关完整文档,请参阅库页面: https://github.com/RobThree/TwoFactorAuth

错误 & 反馈

https://github.com/andrej-griniuk/cakephp-two-factor-auth/issues

鸣谢

https://github.com/RobThree/TwoFactorAuth

许可

版权所有(C)2020,安德烈·格里纽克,并许可于MIT许可证