2020-05-26 01:30 PM

前回Vol.1の続き。laravel-authをベースにLinphoneユーザ管理ウエブフロントエンドを作成します。Linphoneのユーザ管理システムにおけるLaravel標準のユーザ管理システムとの大きな相違点は、(1)パスワードテーブルがユーザテーブルから独立していること、(2)ユーザ認証時などに使用されるミドルウェアのパスワード暗号化アルゴリズムです。その他、SIPアドレスの入力項目の追加、ユーザクラス名の変更などが必要となります。MVCアーキテクチャを採用したLaravelフレームワークのModel, View, Controllerの箇所に分けて説明します。

 


作業フロー

1.Model

  1. Accountモデル、Passwordモデルファイルの作成
  2. accountsテーブル、passwordsテーブルファイルの作成
  3. accountテーブル用データファイルの作成

2.Controller

  1. SHA256パスワードアルゴリズムへの対応
  2. accountsテーブルへの置換えに伴う変更

3.View

  1. accountsテーブルへの置換えに伴う変更
  2. 初期画面の設定

 

laravel-authとの差分については、Githubのlinphone-account-managerレポジトリを参照願います。

 


 

1.Model

1-1.Accountモデル、Passwordモデルファイルの作成

Laravel標準のUserモデルをAccountモデルに置換え、Accountに紐付けされたパスワードを専用テーブルで管理するためPasswordモデルを作成します。

標準のUserモデルではユーザ名を"name"としていますが、Accountモデルではアカウント名を"username"とします。

またSIPドメイン、Linphoneアプリからユーザ登録する際に必要な項目を追加します。パスワードテーブルとの紐付けについてはLaravelドキュメントEloquent: Relationshipsも参考にして下さい。

app/Models/Account.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use jeremykenedy\LaravelRoles\Traits\HasRoleAndPermission;

class Account extends Authenticatable
{
    use HasRoleAndPermission;
    use Notifiable;
    use SoftDeletes;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'accounts';

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = true;

    /**
     * The attributes that are not mass assignable.
     *
     * @var array
     */
    protected $guarded = [
        'id',
    ];

    /**
     * The relationships that should always be loaded.
     *
     * @var array
     */
    protected $with = ['password'];

    /**
     * The attributes that are hidden.
     *
     * @var array
     */
    protected $hidden = [
        'remember_token',
        'activated',
        'token',
        'confirmation_key',
    ];

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at',
        'creation_time',
        'expire_time'
    ];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username',
        'first_name',
        'last_name',
        'domain',
        'email',
        'activated',
        'token',
        'signup_ip_address',
        'signup_confirmation_ip_address',
        'signup_sm_ip_address',
        'admin_ip_address',
        'updated_ip_address',
        'deleted_ip_address',
        'confirmation_key',
        'ip_address',
        'user_agent',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'id'                                => 'integer',
        'username'                          => 'string',
        'first_name'                        => 'string',
        'last_name'                         => 'string',
        'domain'                            => 'string',
        'email'                             => 'string',
        'activated'                         => 'boolean',
        'token'                             => 'string',
        'signup_ip_address'                 => 'string',
        'signup_confirmation_ip_address'    => 'string',
        'signup_sm_ip_address'              => 'string',
        'admin_ip_address'                  => 'string',
        'updated_ip_address'                => 'string',
        'deleted_ip_address'                => 'string',
        'confirmation_key'                  => 'string',
        'ip_address'                        => 'string',
        'user_agent'                        => 'string',
        'creation_time'                     => 'datetime',
        'expire_time'                       => 'datetime',
    ];

    /**
     * Get the socials for the user.
     */
    public function social()
    {
        return $this->hasMany('App\Models\Social');
    }

    /**
     * Get the passwords for the account.
     */
    public function password()
    {
        return $this->hasOne('App\Models\Password');
    }

    /**
     * Get the profile associated with the user.
     */
    public function profile()
    {
        return $this->hasOne('App\Models\Profile');
    }

    /**
     * The profiles that belong to the user.
     */
    public function profiles()
    {
        return $this->belongsToMany('App\Models\Profile')->withTimestamps();
    }

    /**
     * Check if a user has a profile.
     *
     * @param  string  $username
     *
     * @return bool
     */
    public function hasProfile($username)
    {
        foreach ($this->profiles as $profile) {
            if ($profile->account->username === $username) {
                return true;
            }
        }

        return false;
    }

    /**
     * Add/Attach a profile to a user.
     *
     * @param  Profile $profile
     */
    public function assignProfile(Profile $profile)
    {
        return $this->profiles()->attach($profile);
    }

    /**
     * Remove/Detach a profile to a user.
     *
     * @param  Profile $profile
     */
    public function removeProfile(Profile $profile)
    {
        return $this->profiles()->detach($profile);
    }
}

 

Accountテーブルとは独立してパスワードを管理するためPasswordモデルを作成します。

app/Models/Password.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Password extends Model
{

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'passwords';

    /**
     * The attributes that are not mass assignable.
     *
     * @var array
     */
    protected $guarded = [
        'id',
    ];

    /**
     * The attributes that are hidden.
     *
     * @var array
     */
    protected $hidden = [
        'password',
    ];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'account_id',
        'password',
        'algorithm',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'id'                                => 'integer',
        'account_id'                        => 'integer',
        'password'                          => 'string',
        'algorithm'                         => 'string',
    ];

    public function account()
    {
        return $this->belongsTo('App\Models\Account');
    }

    /* public function setPasswordAttribute($password)
    {
        $this->attributes['password'] = hash('sha256', $password->account->username.':'.$password->account->domain.':'.$password);
    }  */
}

 

1-2.accountsテーブル、passwordsテーブルファイルの作成

アカウントとパスワードのテーブルファイルを作成します。Laravelによるartisan migrationコマンドで指定データベース内に各テーブルが作成されます。

注)ファイル名の順序がテーブル作成の順序に反映されるため、テーブルの名称に注意

database/migrations/2013_04_29_123510_create_accounts_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAccountsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('accounts', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('username', 64)->unique();
            $table->string('domain', 64);
            $table->string('email', 64)->unique()->nullable();
            $table->string('first_name')->nullable();
            $table->string('last_name')->nullable();
            $table->timestamp('email_verified_at')->nullable();
            $table->rememberToken();
            $table->boolean('activated')->default(false);
            $table->string('token');
            $table->ipAddress('signup_ip_address')->nullable();
            $table->ipAddress('signup_confirmation_ip_address')->nullable();
            $table->ipAddress('signup_sm_ip_address')->nullable();
            $table->ipAddress('admin_ip_address')->nullable();
            $table->ipAddress('updated_ip_address')->nullable();
            $table->ipAddress('deleted_ip_address')->nullable();
            $table->string('confirmation_key', 14)->nullable();
            $table->string('ip_address', 39)->nullable();;
            $table->string('user_agent', 256)->nullable();;
            $table->datetime('creation_time')->nullable();;
            $table->datetime('expire_time')->nullable();
            $table->timestamps();
            $table->softDeletes();
        });

        Schema::create('passwords', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('account_id')->unsigned()->index();
            $table->string('password', 255);
            $table->string('algorithm', 10)->default('SHA-256');
            $table->timestamps();

            //Relationships
            //$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
    });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('accounts');
        Schema::dropIfExists('passwords');
    }
}

 

database/migrations/2014_10_12_100000_create_password_resets_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePasswordResetsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('password_resets', function (Blueprint $table) {
            $table->increments('id');
            $table->string('email')->index();
            $table->string('token')->index();
            $table->timestamp('created_at')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('password_resets');
    }
}

 

1-3.accountテーブル用データファイルの作成

管理者アカウントと一般アカウントを定義したaccounts,passwordsテーブル用データファイルを用意します。

database/seeds/AccountsTableSeeder.php

<?php

use App\Models\Profile;
use App\Models\Account;
use App\Models\Password;
use Illuminate\Database\Seeder;
use jeremykenedy\LaravelRoles\Models\Role;

class AccountsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = Faker\Factory::create();
        $password = new Password();
        $profile = new Profile();
        $adminRole = Role::whereName('Admin')->first();
        $userRole = Role::whereName('User')->first();

        // Seed test admin
        $seededAdminEmail = 'admin@admin.com';
        $user = Account::where('email', '=', $seededAdminEmail)->first();
        if ($user === null) {
            $user = Account::create([
                'username'                       => $faker->userName,  
                'first_name'                     => $faker->firstName,
                'last_name'                      => $faker->lastName,
                'domain'                         => $faker->domainName,
                'email'                          => $seededAdminEmail,
                'token'                          => str_random(64),
                'activated'                      => true,
                'signup_confirmation_ip_address' => $faker->ipv4,
                'admin_ip_address'               => $faker->ipv4,
                'user_agent'                     => $faker->userAgent,
                'ip_address'                     => $faker->ipv4,
                'creation_time'                  => $faker->dateTime,
            ]);

            $password = Password::create ([
                'account_id'       => $user->id,
                'password'         => hash('sha256', $user->username.':'.$user->domain.':testtest'),
                'algorithm'        => 'SHA-256',
            ]);

            $user->password()->save($password);
            $user->profile()->save($profile);
            $user->attachRole($adminRole);
            $user->save();
        }

        // Seed test user
        $user = Account::where('email', '=', 'user@user.com')->first();
        if ($user === null) {
            $user = Account::create([
                'username'                       => $faker->userName,
                'first_name'                     => $faker->firstName,
                'last_name'                      => $faker->lastName,
                'domain'                         => $faker->domainName,
                'email'                          => 'user@user.com',
                'token'                          => str_random(64),
                'activated'                      => true,
                'signup_ip_address'              => $faker->ipv4,
                'signup_confirmation_ip_address' => $faker->ipv4,
                'user_agent'                     => $faker->userAgent,
                'ip_address'                     => $faker->ipv4,
                'creation_time'                  => $faker->dateTime,
            ]);

            $password = Password::create ([
                'account_id'       => $user->id,
                'password'         => hash('sha256', $user->username.':'.$user->domain.':testtest'),
                'algorithm'        => 'SHA-256',
            ]);

            $user->password()->save($password);
            $user->profile()->save(new Profile());
            $user->attachRole($userRole);
            $user->save();
        }

        // Seed test users
        // $user = factory(App\Models\Profile::class, 5)->create();
        // $users = Account::All();
        // foreach ($users as $user) {
        //     if (!($user->isAdmin()) && !($user->isUnverified())) {
        //         $user->attachRole($userRole);
        //     }
        // }
    }
}

 

2.Controller

2-1.SHA256パスワードアルゴリズムへの対応

独立したパスワードテーブルとパスワードハッシュアルゴリズムSHA256に対応するように、以下RegisterController, UsersManagementControllerのコードを改変します。

app/Http/Controllers/Auth/RegisterController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\Profile;
use App\Models\Account;
use App\Models\Password;
use App\Traits\ActivationTrait;
use App\Traits\CaptchaTrait;
use App\Traits\CaptureIpTrait;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use jeremykenedy\LaravelRoles\Models\Role;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
     */

    use ActivationTrait;
    use CaptchaTrait;
    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = '/activate';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest', [
            'except' => 'logout',
        ]);
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param array $data
     *
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        $data['captcha'] = $this->captchaCheck();

        if (! config('settings.reCaptchStatus')) {
            $data['captcha'] = true;
        }

        return Validator::make(
            $data,
            [
                'username'                  => 'required|max:255|unique:accounts',
                'first_name'            => '',
                'last_name'             => '',
                'domain'                => 'required|max:64',
                'email'                 => 'required|email|max:255|unique:accounts',
                'password'              => 'required|min:6|max:30|confirmed',
                'password_confirmation' => 'required|same:password',
                'g-recaptcha-response'  => '',
                'captcha'               => 'required|min:1',
            ],
            [
                'username.unique'                   => trans('auth.userNameTaken'),
                'username.required'                 => trans('auth.userNameRequired'),
                'first_name.required'           => trans('auth.fNameRequired'),
                'last_name.required'            => trans('auth.lNameRequired'),
                'domain.required'               => trans('auth.domainRequired'),
                'email.required'                => trans('auth.emailRequired'),
                'email.email'                   => trans('auth.emailInvalid'),
                'password.required'             => trans('auth.passwordRequired'),
                'password.min'                  => trans('auth.PasswordMin'),
                'password.max'                  => trans('auth.PasswordMax'),
                'g-recaptcha-response.required' => trans('auth.captchaRequire'),
                'captcha.min'                   => trans('auth.CaptchaWrong'),
            ]
        );
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param array $data
     *
     * @return Account
     */
    protected function create(array $data)
    {
        $ipAddress = new CaptureIpTrait();

        if (config('settings.activation')) {
            $role = Role::where('slug', '=', 'unverified')->first();
            $activated = false;
        } else {
            $role = Role::where('slug', '=', 'user')->first();
            $activated = true;
        }

        $user = Account::create([
            'username'          => $data['username'],
            'first_name'        => $data['first_name'],
            'last_name'         => $data['last_name'],
            'domain'            => $data['domain'],
            'email'             => $data['email'],
            'token'             => str_random(64),
            'signup_ip_address' => $ipAddress->getClientIp(),
            'activated'         => $activated,
        ]);

        $password = Password::create ([
            'account_id'       => $user->id,
            'password'         => hash('sha256', $user->username.':'.$user->domain.':'.$data['password']),
            'algorithm'        => 'SHA-256',
        ]);

        $user->attachRole($role);
        $this->initiateEmailActivation($user);

        if (! config('settings.activation')) {
            $user->password()->save($password);
            $profile = new Profile();
            $user->profile()->save($profile);
            $user->save();
        }

        return $user;
    }
}

 

app/Http/Controllers/UsersManagementController.php(一部抜粋)

/**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make(
            $request->all(),
            [
                'username'              => 'required|max:255|unique:accounts',
                'first_name'            => '',
                'last_name'             => '',
                'domain'                => 'required|max:64',
                'email'                 => 'required|email|max:255|unique:accounts',
                'password'              => 'required|min:6|max:20|confirmed',
                'password_confirmation' => 'required|same:password',
                'role'                  => 'required',
            ],
            [
                'username.unique'         => trans('auth.userNameTaken'),
                'username.required'       => trans('auth.userNameRequired'),
                'first_name.required' => trans('auth.fNameRequired'),
                'last_name.required'  => trans('auth.lNameRequired'),
                'domain.required'     => trans('auth.domainRequired'),
                'email.required'      => trans('auth.emailRequired'),
                'email.email'         => trans('auth.emailInvalid'),
                'password.required'   => trans('auth.passwordRequired'),
                'password.min'        => trans('auth.PasswordMin'),
                'password.max'        => trans('auth.PasswordMax'),
                'role.required'       => trans('auth.roleRequired'),
            ]
        );

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $ipAddress = new CaptureIpTrait();
        $profile = new Profile();

        $user = Account::create([
            'username'         => $request->input('username'),
            'first_name'       => $request->input('first_name'),
            'last_name'        => $request->input('last_name'),
            'domain'           => $request->input('domain'),
            'email'            => $request->input('email'),
            'token'            => str_random(64),
            'admin_ip_address' => $ipAddress->getClientIp(),
            'activated'        => 1,
        ]);

        $password = Password::create ([
            'account_id'       => $user->id,
            'password'         => hash('sha256', $user->username.':'.$user->domain.':'.$request->input('password')),
            'algorithm'        => 'SHA-256',
        ]);

        $user->password()->save($password);
        $user->profile()->save($profile);
        $user->attachRole($request->input('role'));
        $user->save();

        return redirect('users')->with('success', trans('usersmanagement.createSuccess'));
    }

 

ログイン、アカウント登録、パスワードリセットなどの認証処理に使用されるミドルウェアRedirectIfAuthenticated.phpをSHA256に対応するよう改変します。

app/Http/Middleware/RedirectIfAuthenticated.php

<?php

namespace App\Http\Middleware;

use Closure;
use App\Models\Account;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure                 $next
     * @param string|null              $guard
     *
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        $password_bool = false;
        
        if ($request->has('email')) {
            
            $email = $request->input('email');
            $input_password = $request->input('password');

            $account = Account::where('email', $email)->first();
            if ($account == null) {
                return $next($request);
            }

            $username = $request->input('username', $account->username);
            $domain = $account->domain;

            $hash_pass = hash('sha256', $username.':'.$domain.':'.$input_password);

            if ($request->has('token')) {
                if (Auth::guard($guard)->check()) {
                    return redirect('/home');
                } else {
                    return $next($request);
                }
            }
            
            $password = $account->password;
            $password_bool = hash_equals($password->password, $hash_pass);
                
        }
        if ($password_bool) {
            Auth::login($account, true);
            Auth::guard($guard)->check();
            return redirect('/home');
        }

        return $next($request);
    }
}

 

パスワードリセットコントローラapp/Http/Controllers/Auth/ResetPasswordController.php内で使用されているトレイトをApp\Traits\ResetsPasswordsへ変更し、app/Traits/ResetsPasswords.phpと、このトレイト内で使用されているapp/Traits/RedirectsUsers.phpを作成します。

 

app/Traits/ResetsPasswords.php

<?php

namespace App\Traits;

use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

trait ResetsPasswords
{
    use RedirectsUsers;

    /**
     * Display the password reset view for the given token.
     *
     * If no token is present, display the link request form.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string|null  $token
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function showResetForm(Request $request, $token = null)
    {
        return view('auth.passwords.reset')->with(
            ['token' => $token, 'email' => $request->email]
        );
    }

    /**
     * Reset the given user's password.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    public function reset(Request $request)
    {
        $request->validate($this->rules(), $this->validationErrorMessages());

        // Here we will attempt to reset the user's password. If it is successful we
        // will update the password on an actual user model and persist it to the
        // database. Otherwise we will parse the error and return the response.
        $response = $this->broker()->reset(
            $this->credentials($request), function ($user, $password) {
                $this->resetPassword($user, $password);
            }
        );

        // If the password was successfully reset, we will redirect the user back to
        // the application's home authenticated view. If there is an error we can
        // redirect them back to where they came from with their error message.
        return $response == Password::PASSWORD_RESET
                    ? $this->sendResetResponse($request, $response)
                    : $this->sendResetFailedResponse($request, $response);
    }

    /**
     * Get the password reset validation rules.
     *
     * @return array
     */
    protected function rules()
    {
        return [
            'token' => 'required',
            'email' => 'required|email',
            'password' => 'required|confirmed|min:8',
        ];
    }

    /**
     * Get the password reset validation error messages.
     *
     * @return array
     */
    protected function validationErrorMessages()
    {
        return [];
    }

    /**
     * Get the password reset credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        return $request->only(
            'email', 'password', 'password_confirmation', 'token'
        );
    }

    /**
     * Reset the given user's password.
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @param  string  $password
     * @return void
     */
    protected function resetPassword($user, $password)
    {
        $this->setUserPassword($user, $password);

        $user->setRememberToken(Str::random(60));

        $user->password->save();
        $user->save();

        event(new PasswordReset($user));

        $this->guard()->login($user);
    }

    /**
     * Set the user's password.
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @param  string  $password
     * @return void
     */
    protected function setUserPassword($user, $password)
    {
        $username = $user->username;
        $domain = $user->domain;
        $user->password->password = hash('sha256', $username.':'.$domain.':'.$password);
        //dd($user);
    }

    /**
     * Get the response for a successful password reset.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $response
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    protected function sendResetResponse(Request $request, $response)
    {
        if ($request->wantsJson()) {
            return new JsonResponse(['message' => trans($response)], 200);
        }

        return redirect($this->redirectPath())
                            ->with('status', trans($response));
    }

    /**
     * Get the response for a failed password reset.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $response
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    protected function sendResetFailedResponse(Request $request, $response)
    {
        if ($request->wantsJson()) {
            throw ValidationException::withMessages([
                'email' => [trans($response)],
            ]);
        }

        return redirect()->back()
                    ->withInput($request->only('email'))
                    ->withErrors(['email' => trans($response)]);
    }

    /**
     * Get the broker to be used during password reset.
     *
     * @return \Illuminate\Contracts\Auth\PasswordBroker
     */
    public function broker()
    {
        return Password::broker();
    }

    /**
     * Get the guard to be used during password reset.
     *
     * @return \Illuminate\Contracts\Auth\StatefulGuard
     */
    protected function guard()
    {
        return Auth::guard();
    }
}

 

app/Traits/RedirectsUsers.php

<?php

namespace App\Traits;

trait RedirectsUsers
{
    /**
     * Get the post register / login redirect path.
     *
     * @return string
     */
    public function redirectPath()
    {
        if (method_exists($this, 'redirectTo')) {
            return $this->redirectTo();
        }

        return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home';
    }
}

 

2-2.accountsテーブルへの置換えに伴う変更

usersテーブルからaccountsテーブルへの名称変更、usersテーブル内の"name"からaccountsテーブル内の"username"へ変更したため、各コントローラの該当箇所を修正します。

  • App\Models\User ---> App\Models\Account インスタンスの箇所もUserからAccountへ変更
  • user_id ---> account_id へ変更
  • use App\Models\Password;の追加

 

config/auth.php 以下モデルクラス変更

'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model'  => App\Models\Account::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

 

3.View

3-1.accountsテーブルへの置換えに伴うファイル変更

"name" ---> "username" へ変更し、SIPドメイン入力メニューの箇所を追加。

resources/views/auth/register.blade.php (一部抜粋)

.....

<div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Username') }}</label>

                            <div class="col-md-6">
                                <input id="username" type="text" class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}" name="username" value="{{ old('username') }}" required autofocus>

                                @if ($errors->has('username'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('username') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

.....

.....

<div class="form-group row">
                            <label for="domain" class="col-md-4 col-form-label text-md-right">{{ __('SIP Domain') }}</label>

                            <div class="col-md-6">
                                <input id="domain" type="text" class="form-control{{ $errors->has('domain') ? ' is-invalid' : '' }}" name="domain" value="{{ old('domain') }}" required autofocus>

                                @if ($errors->has('domain'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('domain') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

.....

 

laravel-authのBootstrapに必要なjQuery, Popper.jsバージョンがLarevl ver.7に対応していないので、app.blade.phpapp.jsを無効にし最新版を指定。

 

resources/views/layouts/app.blade.php

{{-- Scripts --}}
        <!-- script src="{{ mix('/js/app.js') }}"></script -->
        <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>

 

3-2.初期画面の設定

ログイン画面がホームページになるように設定

routes/web.php(一部抜粋)

// Homepage Route
Route::group(['middleware' => ['web', 'checkblocked']], function () {
    // Route::get('/', 'WelcomeController@welcome')->name('welcome');
    Route::get('/', 'UserController@index')->middleware('auth');
    Route::get('/terms', 'TermsController@terms')->name('terms');
});