🔒

Laravel ユーザーのテストデータ生成時、ちょっと気に留めておきたい事

2022/02/08に公開

前書き

Laravel でダミーデータの登録に Seeder 機能を使うと思いますが、この際、Factory を利用しなくてもダミーデータの登録はできたりします。そんな時、もしかしたら改善できるポイントがあるかも知れないという話です。

今回の話は、、、

  • 10件とか少量のデータの生成時は、気にしなくて良いです。ただ、100件超える場合などは、気に留めた方が良いかも。
  • 自動テストの際は、気にしなくて大丈夫です。

本題

という事で、見直した方がいいかも知れない例をドカンと。

DatabaseSeeder.php
<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        for ($i=0; $i < 100; $i++) {
            \DB::table('users')->insert([
                'name' => 'name'.$i,
                'email' => 'abc'.$i.'@example.net',
                'password' => \Hash::make('hogehoge'),
            ]);
        }
    }
}

「一括登録にした方がいいのでは?」とか「Factory 使えば?」とか、今回はそういう話ではなく、気にしたいのが、Hash::make() の所です。

for文で、100回 Hash::make() が実行されていますが、強力なパスワードの生成には、コストが掛かります。要は、負荷が掛かるため、その分時間が掛かります。
私の(そこそこいいかも知れない)マシンでも、この処理で5秒程掛かります。「5秒?別にいいじゃん!」という話もありますが、プログラマは基本忙しいのです。(たぶん)
もし仮に1,000件のデータにした場合、50秒とか待たされるかも知れません。

パスワードが特に重要でなければ、UserFactory に書かれているハッシュ化済み文字列をコピペした方が時間を節約できます。(100件程度なら、一瞬で終わります)

'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password

さりげなくコメントがありますが、これは、'password' という文字列をハッシュ化したものですね。

必要であれば、100件登録した後で、自分がログインするアカウントのパスワードを個別で変更した方がいいですね。

User::first()->update([
    'password' => \Hash::make('hogehoge'),
]);

自動テストの際は、何で気にしなくていいいの?

基本的に自動テスト際は、パスワード生成時のコストが最小限に設定されています。

phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...>

    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>  ← ここ
    </php>
</phpunit>

自動テスト時でない時(通常時)の設定は、下記

config/hashing.php
    'bcrypt' => [
        'rounds' => env('BCRYPT_ROUNDS', 10),
    ],

将来、マシンのスペックが向上して、今生成しているパスワードが解読されやすくなった際は、この rounds の箇所を設定(変更)して、より強固なパスワードを生成する事ができるようになっているのですね。で、そんな時は、Hash::needsRehash() とか使ったりするのですが、今日のお題とかけ離れるので、辞めておきます。

Laravel コソコソ噂話

ほぼトリビアですが、今現在の UserFactory.php では、先程見たように

'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password

'password' という文字列がハッシュ化されていますが、こうなる前(Ver.5.8辺り)は、

'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret

と 'secret' という文字列でした。
この変更は、要は「パスワード6文字って、短くない?今の時代、8文字は必要だよね?」みたいな流れに沿った結果、こうなりました。

雑感

おかしな箇所等ありましたらコメント下さい。

Discussion