2019/07/19
「LaravelでSSOのAPIを作成する」シリーズの第三回です。
前前回、Laravelの make:auth
認証機能を自動生成しました。
今回はこの認証機能をカスタマイズします。DB の照合処理を API にさせるように記述します。
手順
1.クライアント側のDBにもSSOのレコードをインサートする
2.パスワードは暗号化にしないとログイン認証できない
1)環境設定ファイルにAPIのアドレスを設定
環境設定ファイルにSSOのAPIのアドレスを記述します。
file_get_contents関数
でURLを指定するときに使います。
.env
:
SSO_URL=http://localhost/practice_sso/public/login
\config\app.php
:
'ssoURL' => env('SSO_URL'),
2)認証用トレイトを App\SsoAuth に移す
make:auth
を実行すると App\Http\Controllers\Auth\AuthController.php
がコントローラーとして使われます。
このコントローラーに「ログイン認証の処理」や「新規登録の処理」が入っています。
しかし、実態ファイルはトレイトとして格納されており、オリジナルはvendorディレクトリ以下 ( vendor\laravel\frameworks\src\Illuminate\Foundation\Auth\
) にあります。
vendorディレクトリ以下のファイルは Git の管理外です。また Laravel のお作法としてもこのVendorディレクトリ以下のファイルを触るのは NG です。
なので、App
直下に SsoAuthディレクトリ
を作成し、このディレクトリ以下にVendor以下に置いてあったAuth関連のファイルを設置します。
3)名前空間を変更
App\Http\Controllers\Auth\AuthController.php
//use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; // ← こっちをやめて
use App\SsoAuth\AuthenticatesAndRegistersUsers; // ← こっちにする
App\SsoAuth\AuthenticateAndRegistersUsers.php
//namespace Illuminate\Foundation\Auth; // ← こっちをやめて
namespace App\SsoAuth; // ← こっちにする
trait AuthenticatesAndRegistersUsers
{
use AuthenticatesUsers, RegistersUsers {
AuthenticatesUsers::redirectPath insteadof RegistersUsers;
AuthenticatesUsers::getGuard insteadof RegistersUsers;
}
}
4)認証用プログラムの編集
トレイトを追っていくとloginメソッドの本体は AuthenticatsUsers.php
だとわかります。
このファイルを編集します。
コメントアウトで記述している「SSOサーバーからデータを取ってくる」以外はそのままです。
App\SsoAuth\AuthenticatesUsers
public function login(Request $request)
{
// バリデーション
$this->validateLogin($request);
// スロットル取得
$throttles = $this->isUsingThrottlesLoginsTrait();
// もし、規定の回数を超えていたら
if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
// SSOサーバーからデータを取ってくる
if(!\App\Services\SSO::pre_login($request->email,$request->password)){
return $this->sendFailedLoginResponse($request);
}
// 認証情報取得
$credentials = $this->getCredentials($request);
// 認証
if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
return $this->handleUserWasAuthenticated($request, $throttles);
}
// 失敗だったらスロットルをカウントアップ
if ($throttles && ! $lockedOut) {
$this->incrementLoginAttempts($request);
}
return $this->sendFailedLoginResponse($request);
}
5)SSO用のクラスを新規作成
SSO用のクラスを App\Services に 新規に作成します。
このクラスに、SSOのAPIに接続するスクリプトを書きます。
# App\Services\SSO.php
class SSO
{
public static function pre_login($id, $pass){
// 送信データ
$data = array(
"id" => $id,
"password" => $pass
);
// JSON形式に変換
$data = json_encode($data);
// ストリームコンテキストのオプションを作成
$options = array(
// HTTPコンテキストオプションをセット
'http' => array(
'method'=> 'POST',
'header'=> 'Content-type: application/json; charset=UTF-8', //JSON形式で表示
'content' => $data
)
);
// ストリームコンテキストの作成
$context = stream_context_create($options);
// POST送信
$ssoURL = \Config::get('app.ssoURL');
$raw_data = @file_get_contents($ssoURL, false, $context);
// jsonからstdClassに変換
$data = json_decode($raw_data);
// SSOにレコードあり
if($data->result){
// クライアント側にレコードがあるか確認
$user = User::where('email',$data->email)->first();
if($user){
// クライアント側にレコードがある
return true;
}else{
// クライアント側にレコードがない
// クライアント側にもレコードがないと認証できないためインサート処理
$newuser = new User;
self::copy_to_user($data,$newuser);
$newuser->save();
return true;
}
}else{
// SSOにレコードなし(エラー)
return false;
}
}
// コピー用関数
private static function copy_to_user($result,$user)
{
$user->name = $result->name;
$user->email = $result->email;
$user->password = bcrypt($result->password);
}
}
6)動作確認
以上です。
PHPフレームワーク Laravel入門
僕がはじめてLaravelを学習するために参考にしたサイトは、掌田津耶乃(しょうだつやの)さんの libro というサイトです。当時(2016年)、Laravel学習サイトの中でもこのサイトは群を抜いてわかりやすく説明されていたので、とても勉強になったのを覚えています。この本は掌田津耶乃が書いた本なので、わかりやすく解説されているだろうと kindle で購入しました。2019年7月の時点でいうと日本国内にて唯一の Laravel の良書と言っても良いかと思います。しかし、かなりわかりやすく解説されているとはいえ、PHP中級者以上のスキルは必要です。PHP自体の知識が乏しい方は独習PHP 第3版をあわせて購入することをお勧めします。
仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。