diff --git a/backend/app/Http/Controllers/Api/AuthenticationTrait.php b/backend/app/Http/Controllers/Api/AuthenticationTrait.php index d49a61dd..53b44ef0 100644 --- a/backend/app/Http/Controllers/Api/AuthenticationTrait.php +++ b/backend/app/Http/Controllers/Api/AuthenticationTrait.php @@ -6,23 +6,46 @@ use App\Http\Controllers\Controller, Session; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Hash; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; + +use App\Models\LoginLimits; // use App\Models\LoginLimits; trait AuthenticationTrait { - public function login (Request $r) { - // if (null === $r->server('HTTP_USER_AGENT')) { - // return ['status_code' => 400, 'error_message' => ['不正なuser_agent。']]; - // } + private function makeSession ($guard, $db) { + if (!session()->has($guard)) { + // 認証されたデータのpasswordとremember_token以外を把握する + unset($db['password']); + unset($db['remember_token']); + // セッションに保存する + session()->put($guard, $db); + } - // if (null !== ($ll = LoginLimits::where('user_agent', $r->server('HTTP_USER_AGENT'))->first())) { - // if ((time() >= strtotime($ll->updated_at) + 600) === false) { - // LoginLimits::where('user_agent', $r->server('HTTP_USER_AGENT'))->delete(); - // } - // if ($ll->fail_number >= 10) { - // return ['status_code' => 400, 'error_message' => ['10回連続で失敗しましたので、10分、ログインロックになりました。']]; - // } - // } + return $db; + } + + public function login (Request $r) { + $loginid = $this->getGuard() == 'children' ? $r->tel : $r->email; + + if (null !== ($ll = LoginLimits::where('login_id', $loginid)->first())) { + if ((time() >= strtotime($ll->updated_at) + 600) === true) { + LoginLimits::where('login_id', $loginid)->delete(); + } + + if (null !== ($ll = LoginLimits::where('login_id', $loginid)->first()) && $ll->fail_number >= 10) { + return ['status_code' => 400, 'error_message' => ['10回連続で失敗しましたので、10分、ログインロックになりました。']]; + } + } + + if (isset($_COOKIE['remember_token']) && !is_null($_COOKIE['remember_token'])) { // クッキーがある場合 + if (null === ($get = $this->getModel()->where('remember_token', $_COOKIE['remember_token'])->first())) { // トークンがある場合 + // セッションを想像する + $login_user_datum = $this->makeSession($this->getGuard(), $get->toArray()); + + return ['status_code' => 200, 'params' => ['id' => $login_user_datum['id']]]; + } + } if ($this->getGuard() == 'children') { Validator::extend('tel_size', function ($attribute, $value, $params, $validator) { @@ -46,17 +69,25 @@ trait AuthenticationTrait { // 存在しない場合 if (null === ($get = $this->getModel()->where($chk[0], $chk[1])->first())) { + if (null !== ($loglim = LoginLimits::where('login_id', $loginid)->first())) { + LoginLimits::where('login_id', $loginid)->increment('fail_number'); + } + else { + LoginLimits::create(['login_id' => $loginid, 'fail_number' => 1]); + } + return ['status_code' => 400, 'error_message' => ['ログインに失敗しました。10回連続で失敗すると、一定期間ログインできなくなります。']]; } // パスワードが異なる場合 if (!Hash::check($r->password, $get->password)) { - // if ($ll = LoginLimits::where('user_agent', $r->server('HTTP_USER_AGENT'))->first()) { - // LoginLimits::where('user_agent', $r->server('HTTP_USER_AGENT'))->update(['fail_number' => $ll->fail_number+1]); - // } - // else { - // LoginLimits::create(['user_agent' => $r->server('HTTP_USER_AGENT'), 'fail_number' => 1]); - // } + if (null !== ($loglim = LoginLimits::where('login_id', $loginid)->first())) { + LoginLimits::where('login_id', $loginid)->increment('fail_number'); + } + else { + LoginLimits::create(['login_id' => $loginid, 'fail_number' => 1]); + } + return ['status_code' => 400, 'error_message' => ['ログインに失敗しました。10回連続で失敗すると、一定期間ログインできなくなります。']]; } @@ -65,22 +96,35 @@ trait AuthenticationTrait { if (Session::has('fathers')) Session::forget('fathers'); if (Session::has('admins')) Session::forget('admins'); - // セッションを想像する - $guard = $this->getGuard(); - if (!$r->session()->has($guard)) { - // 認証されたデータのpassword以外を把握する - $login_user_datum = $get->toArray(); - unset($login_user_datum['password']); - // セッションに保存する - $r->session()->put($guard, $login_user_datum); + if ($r->remember_token == 'true') { + $token = bin2hex(random_bytes(24)); + + try { + $this->getModel()->where('id', $get->id)->update(['remember_token' => $token]); + setcookie('remember_token', $token, time()+157788000, '/', $_SERVER['HTTP_HOST'], 0, 1); + } + catch (\Throwable $e) { + Log::critical($e->getMessage()); + return ['status_code' => 400, 'error_message' => ['ログインに失敗しました。10回連続で失敗すると、一定期間ログインできなくなります。']]; + } } + // セッションを想像する + $login_user_datum = $this->makeSession($this->getGuard(), $get->toArray()); + return ['status_code' => 200, 'params' => ['id' => $login_user_datum['id']]]; } public function logout () { // セッションを破壊すると、ログイン画面に移転する。 - Session::forget($this->getGuard()); + $guard = $this->getGuard(); + if (null !== $rem = $this->getModel()->select('remember_token')->where('id', session()->get($guard)['id'])->first()) { + $this->getModel()->where('id', session()->get($guard)['id'])->update(['remember_token' => null]); + unset($_COOKIE['remember_token']); + setcookie('remember_token', '', time() - 3600, '/', $_SERVER['HTTP_HOST'], 0, 1); + } + + Session::forget($guard); return redirect(request()->route()->action['prefix'].'/login'); } diff --git a/backend/app/Models/LoginLimits.php b/backend/app/Models/LoginLimits.php index 6e9b5e0d..b9ad0a57 100644 --- a/backend/app/Models/LoginLimits.php +++ b/backend/app/Models/LoginLimits.php @@ -8,5 +8,5 @@ use Illuminate\Database\Eloquent\Model; class LoginLimits extends Model { use HasFactory; - protected $fillable = ['user_agent', 'fail_number']; + protected $fillable = ['login_id', 'fail_number']; } diff --git a/backend/database/factories/LoginLimitsFactory.php b/backend/database/factories/LoginLimitsFactory.php index e1ddbbcf..0817f323 100644 --- a/backend/database/factories/LoginLimitsFactory.php +++ b/backend/database/factories/LoginLimitsFactory.php @@ -19,17 +19,9 @@ class LoginLimitsFactory extends Factory * * @return array */ - public function definition() - { - $ua = [ - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.2 Chrome/87.0.4280.144 Safari/537.36', // qutebrowser - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36', // brave - 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0', // firefox - 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Goanna/4.8 Firefox/68.0 PaleMoon/29.4.1' // palemoon - ]; - + public function definition () { return [ - 'user_agent' => $ua[rand(0, 3)], + 'login_id' => $this->faker->email, 'fail_number' => rand(0, 10), 'created_at' => $this->faker->dateTime, 'updated_at' => $this->faker->dateTime, diff --git a/backend/database/migrations/2021_08_10_045054_create_admins_table.php b/backend/database/migrations/2021_08_10_045054_create_admins_table.php index 11cc5871..a55346e2 100644 --- a/backend/database/migrations/2021_08_10_045054_create_admins_table.php +++ b/backend/database/migrations/2021_08_10_045054_create_admins_table.php @@ -17,6 +17,7 @@ class CreateAdminsTable extends Migration $table->id(); $table->string('email', 72)->unique(); $table->string('password', 72); + $table->string('remember_token', 255)->nullable(); $table->timestamps(); }); } diff --git a/backend/database/migrations/2021_08_12_054526_create_fathers_table.php b/backend/database/migrations/2021_08_12_054526_create_fathers_table.php index 3cf52a9c..a4e8559d 100644 --- a/backend/database/migrations/2021_08_12_054526_create_fathers_table.php +++ b/backend/database/migrations/2021_08_12_054526_create_fathers_table.php @@ -17,6 +17,7 @@ class CreateFathersTable extends Migration $table->id(); $table->string('email', 255)->unique(); $table->string('password', 72); + $table->string('remember_token', 255)->nullable(); $table->string('company', 100); $table->string('image', 100)->nullable(); $table->string('profile', 1000)->nullable(); diff --git a/backend/database/migrations/2021_08_13_042143_create_children_table.php b/backend/database/migrations/2021_08_13_042143_create_children_table.php index dc2699cf..931e1a49 100644 --- a/backend/database/migrations/2021_08_13_042143_create_children_table.php +++ b/backend/database/migrations/2021_08_13_042143_create_children_table.php @@ -19,6 +19,7 @@ class CreateChildrenTable extends Migration $table->string('email', 72)->unique(); $table->string('tel', 11)->unique(); $table->string('password', 255); + $table->string('remember_token', 255)->nullable(); $table->string('last_name', 100); $table->string('first_name', 100); $table->string('image', 100)->nullable(); diff --git a/backend/database/migrations/2021_09_29_023700_create_login_limits_table.php b/backend/database/migrations/2021_09_29_023700_create_login_limits_table.php index fb859d0c..2b5af9d3 100644 --- a/backend/database/migrations/2021_09_29_023700_create_login_limits_table.php +++ b/backend/database/migrations/2021_09_29_023700_create_login_limits_table.php @@ -15,7 +15,7 @@ class CreateLoginLimitsTable extends Migration { Schema::create('login_limits', function (Blueprint $table) { $table->id(); - $table->string('user_agent', 300); + $table->string('login_id', 255); $table->unsignedInteger('fail_number'); $table->timestamps(); });