Skip to content

Instantly share code, notes, and snippets.

@jamband
Last active December 4, 2018 09:51
Show Gist options
  • Save jamband/2337558 to your computer and use it in GitHub Desktop.
Save jamband/2337558 to your computer and use it in GitHub Desktop.
Yii Framework: Login Attempt
<?php if (!$isBanned): ?>
<div class="form">
<?php echo CHtml::form(); ?>
<?php echo CHtml::errorSummary($model, false); ?>
<div class="row">
<?php echo CHtml::activeLabel($model, 'login'); ?>
<?php echo CHtml::activeTextField($model, 'login', array('maxlength' => 64)); ?>
</div><!-- /.row -->
<div class="row">
<?php echo CHtml::activeLabel($model, 'password'); ?>
<?php echo CHtml::activePasswordField($model, 'password', array('maxlength' => 64)); ?>
</div><!-- /.row -->
<div class="row buttons">
<?php echo CHtml::submitButton('ログイン'); ?>
<?php echo CHtml::activeCheckBox($model, 'rememberMe'); ?>
<?php echo CHtml::activeLabel($model, 'rememberMe'); ?>
</div><!-- /.row buttons -->
<?php echo CHtml::endForm(); ?>
</div><!-- /.form -->
<?php else: ?>
<div class="flash-error">
ログイン試行回数が制限を越えてしまいました。時間をおいて、再度ログインを試してください
</div><!-- /.flash-error -->
<?php endif; ?>
<?php
class LoginAttempt extends ActiveRecord
{
const LOGIN_ATTEMPT_LIMIT = 5; // ログイン試行回数のリミット
const BANNED_IP_EXPIRATION_TIME = '+1 hour'; // この場合は禁止されてから一時間経たないとログインできない
...
/**
* @see CActiveRecord::beforeSave()
*/
protected function beforeSave()
{
$this->create_time = time();
$this->expiration_time = strtotime(self::BANNED_IP_EXPIRATION_TIME, $this->create_time);
return true;
}
/**
* ログインが禁止されたIPアドレスか、そうでないか
* @param string $ip ip address
* @return boolean
*/
public function isBanned($ip)
{
$c = $this->getCriteriaByIp($ip);
if ($this->count($c) >= self::LOGIN_ATTEMPT_LIMIT) {
return true;
}
return false;
}
/**
* ログインが禁止されたIPアドレスを期限切れの場合は削除する
* @param string $ip ip address
*/
public function purgeBannedIp($ip)
{
$c = $this->getCriteriaByIp($ip);
if ($this->count($c) >= self::LOGIN_ATTEMPT_LIMIT) {
$c->order = 't.create_time DESC';
$model = $this->find($c);
if (time() > $model->expiration_time) {
$this->deleteAll('ip = :ip', array(':ip' => $ip));
}
}
}
/**
* IPを条件にしたcriteriaを取得する
* @param string $ip ip address
* @return object criteria
*/
private function getCriteriaByIp($ip)
{
$c = new CDbCriteria;
$c->condition = 't.ip = :ip';
$c->params[':ip'] = $ip;
return $c;
}
...
<?php
class LoginController extends Controller
{
private $ip;
/**
* @see CController::defaultAction
*/
public $defaultAction = 'login';
/**
* @see CController::init()
*/
public function init()
{
$this->ip = Yii::app()->request->userHostAddress;
}
/**
* ユーザのログイン
*/
public function actionLogin()
{
if (Yii::app()->user->id) {
$this->redirect('/');
}
$loginAttempt = new LoginAttempt();
$loginAttempt->purgeBannedIp($this->ip);
$isBanned = $loginAttempt->isBanned($this->ip);
if (!$isBanned) {
$model = new Login();
if (isset($_POST['Login'])) {
$model->attributes = $_POST['Login'];
if ($model->validate()) {
$this->redirect(Yii::app()->user->returnUrl);
}
if (!empty($model->login)) {
$loginAttempt->login = $model->login;
$loginAttempt->ip = $this->ip;
$loginAttempt->save(false);
}
}
}
$this->render('/user/login', compact('model', 'isBanned'));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment