mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-26 12:23:06 +08:00
Merge branch 'koogua/block-flood-login' into demo
This commit is contained in:
commit
c2c1c9987e
@ -97,7 +97,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':article.id,'type':'article','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':article.id,'type':'article'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -57,7 +57,7 @@
|
||||
<input type="hidden" name="bind_user_url" value='{{ bind_user_url }}'>
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':chapter.id,'type':'chapter','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':chapter.id,'type':'chapter'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -43,7 +43,7 @@
|
||||
<input type="hidden" name="chapter.learning_url" value="{{ learning_url }}">
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':chapter.id,'type':'chapter','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':chapter.id,'type':'chapter'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -43,7 +43,7 @@
|
||||
<input type="hidden" name="chapter.play_urls" value='{{ chapter.play_urls|json_encode }}'>
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':chapter.id,'type':'chapter','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':chapter.id,'type':'chapter'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -94,7 +94,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':course.id,'type':'course','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':course.id,'type':'course'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -97,7 +97,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':question.id,'type':'question','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':question.id,'type':'question'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -96,7 +96,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':user.id,'type':'user','referer':auth_user.id}) %}
|
||||
{% set share_url = full_url({'for':'home.share'},{'id':user.id,'type':'user'}) %}
|
||||
{% set qrcode_url = url({'for':'home.qrcode'},{'text':share_url}) %}
|
||||
|
||||
<div class="layui-hide">
|
||||
|
@ -16,7 +16,7 @@ class AppInfo
|
||||
|
||||
protected $link = 'https://koogua.com';
|
||||
|
||||
protected $version = '1.4.6';
|
||||
protected $version = '1.4.7';
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
|
||||
class UserSession extends Model
|
||||
{
|
||||
|
||||
@ -45,6 +47,13 @@ class UserSession extends Model
|
||||
*/
|
||||
public $client_ip = '';
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $deleted = 0;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*
|
||||
@ -71,6 +80,18 @@ class UserSession extends Model
|
||||
return 'kg_user_session';
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->addBehavior(
|
||||
new SoftDelete([
|
||||
'field' => 'deleted',
|
||||
'value' => 1,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->create_time = time();
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Phalcon\Mvc\Model\Behavior\SoftDelete;
|
||||
|
||||
class UserToken extends Model
|
||||
{
|
||||
|
||||
@ -45,6 +47,13 @@ class UserToken extends Model
|
||||
*/
|
||||
public $client_ip = '';
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $deleted = 0;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*
|
||||
@ -71,6 +80,18 @@ class UserToken extends Model
|
||||
return 'kg_user_token';
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->addBehavior(
|
||||
new SoftDelete([
|
||||
'field' => 'deleted',
|
||||
'value' => 1,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function beforeCreate()
|
||||
{
|
||||
$this->create_time = time();
|
||||
|
@ -18,10 +18,26 @@ class UserSession extends Repository
|
||||
* @param int $userId
|
||||
* @return ResultsetInterface|Resultset|UserSessionModel[]
|
||||
*/
|
||||
public function findByUserId($userId)
|
||||
public function findUserActiveSessions($userId)
|
||||
{
|
||||
return UserSessionModel::query()
|
||||
->where('user_id = :user_id:', ['user_id' => $userId])
|
||||
->andWhere('deleted = 0')
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param int $minutes
|
||||
* @return ResultsetInterface|Resultset|UserSessionModel[]
|
||||
*/
|
||||
public function findUserRecentSessions($userId, $minutes = 10)
|
||||
{
|
||||
$createTime = time() - $minutes * 60;
|
||||
|
||||
return UserSessionModel::query()
|
||||
->where('user_id = :user_id:', ['user_id' => $userId])
|
||||
->andWhere('create_time > :create_time:', ['create_time' => $createTime])
|
||||
->execute();
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,26 @@ class UserToken extends Repository
|
||||
* @param int $userId
|
||||
* @return ResultsetInterface|Resultset|UserTokenModel[]
|
||||
*/
|
||||
public function findByUserId($userId)
|
||||
public function findUserActiveTokens($userId)
|
||||
{
|
||||
return UserTokenModel::query()
|
||||
->where('user_id = :user_id:', ['user_id' => $userId])
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param int $minutes
|
||||
* @return ResultsetInterface|Resultset|UserTokenModel[]
|
||||
*/
|
||||
public function findUserRecentTokens($userId, $minutes = 10)
|
||||
{
|
||||
$createTime = time() - $minutes * 60;
|
||||
|
||||
return UserTokenModel::query()
|
||||
->where('user_id = :user_id:', ['user_id' => $userId])
|
||||
->andWhere('create_time > :create_time:', ['create_time' => $createTime])
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ class Api extends AuthService
|
||||
{
|
||||
$repo = new UserTokenRepo();
|
||||
|
||||
$records = $repo->findByUserId($userId);
|
||||
$records = $repo->findUserActiveTokens($userId);
|
||||
|
||||
if ($records->count() == 0) return;
|
||||
|
||||
|
@ -68,7 +68,7 @@ class Home extends AuthService
|
||||
|
||||
$repo = new UserSessionRepo();
|
||||
|
||||
$records = $repo->findByUserId($userId);
|
||||
$records = $repo->findUserActiveSessions($userId);
|
||||
|
||||
if ($records->count() == 0) return;
|
||||
|
||||
|
@ -12,13 +12,19 @@ use App\Exceptions\Forbidden as ForbiddenException;
|
||||
use App\Library\Utils\Password as PasswordUtil;
|
||||
use App\Library\Validators\Common as CommonValidator;
|
||||
use App\Models\Account as AccountModel;
|
||||
use App\Models\Client as ClientModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\Account as AccountRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Repos\UserSession as UserSessionRepo;
|
||||
use App\Repos\UserToken as UserTokenRepo;
|
||||
use App\Traits\Client as ClientTrait;
|
||||
|
||||
class Account extends Validator
|
||||
{
|
||||
|
||||
use ClientTrait;
|
||||
|
||||
public function checkAccount($name)
|
||||
{
|
||||
$account = null;
|
||||
@ -175,6 +181,34 @@ class Account extends Validator
|
||||
if ($locked && !$expired) {
|
||||
throw new ForbiddenException('account.locked');
|
||||
}
|
||||
|
||||
$this->checkFloodLogin($user->id);
|
||||
}
|
||||
|
||||
public function checkFloodLogin($userId)
|
||||
{
|
||||
$clientIp = $this->getClientIp();
|
||||
$clientType = $this->getClientType();
|
||||
|
||||
if ($clientType == ClientModel::TYPE_PC) {
|
||||
$repo = new UserSessionRepo();
|
||||
$records = $repo->findUserRecentSessions($userId, 10);
|
||||
} else {
|
||||
$repo = new UserTokenRepo();
|
||||
$records = $repo->findUserRecentTokens($userId, 10);
|
||||
}
|
||||
|
||||
if ($records->count() == 0) return;
|
||||
|
||||
$clientIps = array_column($records->toArray(), 'client_ip');
|
||||
|
||||
$countValues = array_count_values($clientIps);
|
||||
|
||||
foreach ($countValues as $ip => $count) {
|
||||
if ($clientIp == $ip && $count > 4) {
|
||||
throw new ForbiddenException('account.flood_login');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ $error['captcha.invalid_code'] = '无效的验证码';
|
||||
*/
|
||||
$error['account.not_found'] = '账号不存在';
|
||||
$error['account.locked'] = '账号被锁定,无法登录';
|
||||
$error['account.flood_login'] = '帐号泛滥登录';
|
||||
$error['account.login_pwd_incorrect'] = '登录密码不正确';
|
||||
$error['account.invalid_login_name'] = '无效的登录名';
|
||||
$error['account.invalid_email'] = '无效的电子邮箱';
|
||||
|
46
db/migrations/20211019093522.php
Normal file
46
db/migrations/20211019093522.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
|
||||
* @license https://opensource.org/licenses/GPL-2.0
|
||||
* @link https://www.koogua.com
|
||||
*/
|
||||
|
||||
use Phinx\Db\Adapter\MysqlAdapter;
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class V20211019093522 extends AbstractMigration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->alterUserSessionTable();
|
||||
$this->alterUserTokenTable();
|
||||
}
|
||||
|
||||
protected function alterUserSessionTable()
|
||||
{
|
||||
$this->table('kg_user_session')
|
||||
->addColumn('deleted', 'integer', [
|
||||
'null' => false,
|
||||
'default' => '0',
|
||||
'limit' => MysqlAdapter::INT_REGULAR,
|
||||
'signed' => false,
|
||||
'comment' => '删除标识',
|
||||
'after' => 'client_ip',
|
||||
])->save();
|
||||
}
|
||||
|
||||
protected function alterUserTokenTable()
|
||||
{
|
||||
$this->table('kg_user_token')
|
||||
->addColumn('deleted', 'integer', [
|
||||
'null' => false,
|
||||
'default' => '0',
|
||||
'limit' => MysqlAdapter::INT_REGULAR,
|
||||
'signed' => false,
|
||||
'comment' => '删除标识',
|
||||
'after' => 'client_ip',
|
||||
])->save();
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user