定制 metarush/otp-auth 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

metarush/otp-auth

Composer 安装命令:

composer require metarush/otp-auth

包简介

Authentication library using one-time passwords (via email token)

README 文档

README

Authenticate and log in your users using one-time passwords (OTP) via email.

Install

Install via composer as metarush/otp-auth

Database setup

In addition to your usual username and/or email column, create the ff. columns in your users table.

  • otpHash TEXT (255)
  • otpToken TEXT(12)
  • otpExpire INT (10)
  • rememberHash TEXT (255)
  • rememberToken TEXT (12)

Note: You can use other column names if you want, just set them in the config.

Sample usage

The ff. example is meant to demonstrate the library's functionality in a simple way. It is not required to use this implementation as it is.

_init.php

Create a _init.php file to be included on top of your script and put the ff.

Initialize builder

$builder = new MetaRush\OtpAuth\Builder;

Define SMTP servers

$smtpServers = [
    0 => $builder->SmtpServer()
        ->setHost('host')
        ->setUser('user')
        ->setPass('pass')
        ->setPort(465)
        ->setEncr('TLS'),
    1 => $builder->SmtpServer()
        ->setHost('host2')
        ->setUser('user')
        ->setPass('pass')
        ->setPort(465)
        ->setEncr('TLS'),
    ];

You can add as many as you like, the lib will failover to each automatically.

Initialize the library with minimum config

$auth = $builder->setDsn('mysql:host=localhost;dbname=foo')
    ->setServers($smtpServers)
    ->setAdminEmails(['admin@example.com'])
    ->setAppName('foo')
    ->setFromEmail('noreply@example.com')
    ->setUsernameColumn('email')
    ->setNotificationFromEmail('noreply@example.com')
    ->setTable('users')
    ->build();

Note: If you want to extend Auth class and still use the builder, you can pass your child class in the build() parameter as string. E.g. ->build('MyAuth');

Auto-login if username is remembered via cookie

if (!$auth->authenticated()) {
    $rememberedUsername = $auth->rememberedUsername();
    if (null !== $rememberedUsername)
        $auth->login($rememberedUsername);
}

login.php

Create a login.php file and put the ff.

<?php

include '_init.php';

if ($_POST) {
    $username = $_POST['email'];

    // check if username exists
    if (!$auth->userExist($username))
        exit('User does not exist');

    // remember username for next page (otp.php)
    setcookie('username', $username);

    // send OTP to user's email
    $otp = $auth->generateToken(5);
    $auth->sendOtp($otp, $username);

    // redirect to OTP page
    header('location: otp.php');
}

?>

<?php if ($auth->authenticated()): ?>

    You are already logged-in

<?php else: ?>

    <form method="post">
        Email: <input type="text" name="email" />
    </form>

<?php endif; ?>

otp.php

Create a otp.php file and put the ff.

<?php

include '_init.php';

if ($_POST) {
    $otp = $_POST['otp'];
    $username = $_COOKIE['username'];

    // remember username in browser if user wants to
    if (isset($_POST['remember']))
        $auth->remember($username);

    // check if OTP is valid
    if (!$auth->validOtp($otp, $username))
        exit('Invalid OTP');

    // login username
    $auth->login($username);

    echo 'OTP is valid';
    // redirect to your restricted page
}

?>

<?php if ($auth->authenticated()): ?>

    You are already logged-in

<?php else: ?>

    <form method="post">
        OTP: <input type="text" name="otp" />
        <br />
        <br />
        Remember? <input type="checkbox" name="remember" />
        <br />
        <br />
        <input type="submit" />
    </form>

<?php endif; ?>

logout.php

Create a logout.php file and put the ff.

<?php

include '_init.php';

// destroy user session
$auth->logout();

Config methods

You can use the ff. methods in the builder object, before the ->build(); method

setAdminEmails(array);

Array of admin emails that will get error notifications

setAppName(string);

Label of your app on error notifications

setBody(string);

Body of the OTP email. If you set this, you must include the template var {OTP}.

Default: {OTP}\r\n\r\nNote: This OTP is valid for 5 minutes

setCharacterPool(string);

Pool of characters where the token will be derived from

Default: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

setCookiePrefix(string);

Cookie name prefix used by metarush/otp-auth

Default: MROA_

setCookiePath(?string);

Cookie path used by metarush/otp-auth

Default: /

setDbPass(string);

DB password of your users table

setDbUser(string);

DB username of your users table

setDsn(string);

PDO DSN used to connect to your users table

setEmailColumn(string);

Table column where users' email is stored

Default: email

setFromEmail(string);

From Email of the OTP message

setFromName(string);

From Name of the OTP message

setNotificationFromEmail(string);

If you set an admin email via setAdminEmail(), you must set a From Email for error notifications

setOtpExpire(int);

OTP expiration in minutes. If you set this, make sure to also change the email message via setBody(string); to reflect the OTP expiration the email.

Default: 5

setOtpExpireColumn(string);

Table column where OTP expire is stored

Default: otpExpire

setOtpHashColumn(string);

Table column where OTP hash is stored

Default: otpHash

setOtpTokenColumn(string);

Table column where OTP token is stored

Default: otpToken

setRememberCookieExpire(int);

How long "remember me" cookie expires in seconds

Default: 2592000 (30 days)

setRememberHashColumn(string);

Table column name for "remember me" hash

Default: rememberHash

setRememberTokenColumn(string);

Table column name for lookup token for "remember me" cookie

Default: rememberToken

setServers(array);

Array of SmtpServer objects. See above sample "Define SMTP servers"

setSubject(string);

Subject of the OTP email

Default: Here's your OTP

setTable(string);

Table where usernames will be authenticated

Default: users

setUsernameColumn(string);

Table column name where username is stored

Default: username

setUserIdColumn(string);

Table column name where userId is stored

Default: id

SMTP round-robin mode

You can use round-robin mode to distribute the load to all SMTP hosts when sending OTP email.

To enable round-robin mode, you must use a storage driver to track the last server used to send email.

Available drivers and their config:

files

$driver = 'files';
$driverConfig = [
    'path' => '/var/www/example/emailFallbackCache/'
];

memcached

$driver = 'memcached';
$driverConfig = [
    'host'         => '127.0.0.1',
    'port'         => 11211,
    'saslUser'     => '',
    'saslPassword' => ''
];

Note: Only single server/non-distriubuted memcached is supported at the moment.

redis

$driver = 'redis';
$driverConfig = [
    'host'      => '127.0.0.1',
    'port'      => 6379,
    'password'  => '',
    'database'  => 0
];

Note: Use memcached or redis if available as files is not recommended for heavy usage.

After selecting a driver, set the following in the builder object, before the ->build(); method:

->setRoundRobinMode(true)
->setRoundRobinDriver($driver)
->setRoundRobinDriverConfig($driverConfig)

Service methods

authenticated(): bool

Check if user is authenticated

generateToken(int $length): string

$length Length of token you want to generate.

Generate random token

login(string $username, ?array $userData = []): void

Log in user as authenticated

$username Username to login

$userData Optional arbitrary user data defined by you, e.g., firstName, email

logout(): void

Log out user and remove "remember me" cookie

remember(string $username, int $howLong = null): void

Remember username's login in browser

$username Username to remember

$howLong How long to remember user in seconds. Default is value is 30 days unless setRememberCookieExpire() was used in config.

rememberedUsername(?string $cookie = null): ?string

Get remembered username (via cookie) if any.

$cookie If null, default cookie will be used.

sendOtp(string $otp, string $username, bool $useNextSmtpHost = false, int $testLastServerKey = null): void

Send OTP to user via email

$otp The OTP to send to user. You can use generateToken() service method to generate random OTP. Recommended OTP length is at least 8.

$username Username to send OTP to

$useNextSmtpHost Set to true on your next usage of sendOtp() if you want to use the next SMTP host available relative to the current user. This is useful if the last email is slow to arrive. E.g., Create a "try again" UI then use sendOtp($otp, $username, true) to send a new OTP using the next SMTP host.

userData(): array

Returns arbitrary user data, if set via login() param

userExist(string $username): bool

Check if user exist

$username Username to check

validOtp(string $otp, string $username, ?string $testOtpToken = null): bool

Validate OTP

$otp OTP to be validated

$username Username associated with the OTP

otpExpired(string $username): bool

Check if OTP is expired

$username Username associated with the OTP

userId(string $username): int

Returns the userId of $username

$username Username to get userId

Brute-force protection

We recommended using the metarush/firewall library for login brute-force protection.

metarush/otp-auth 适用场景与选型建议

metarush/otp-auth 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 43 次下载、GitHub Stars 达 3, 最近一次更新时间为 2019 年 03 月 16 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「Authentication」 「login」 「auth」 「one-time password」 「email token」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 metarush/otp-auth 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 metarush/otp-auth 我们能提供哪些服务?
定制开发 / 二次开发

基于 metarush/otp-auth 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 43
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 28
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-03-16