Slide 1

Slide 1 text

Copyright © Xchange Solutions All right reserved. Fukuoka.php Vol.19 Laravelの認証について 株式会社エクスチェンジ ソリューションズ 野田 健夫 2016.10.20

Slide 2

Slide 2 text

2 Copyright © Xchange Solutions All right reserved. こんにちは! 株式会社エクスチェンジ ソリューションズ 野田 健夫(のだたけお) https://twitter.com/nodatakeo https://www.facebook.com/nodatakeo

Slide 3

Slide 3 text

3 Copyright © Xchange Solutions All right reserved. 認証ページ 認証ページを作る目的。  ユーザー識別  アクセス制限、権限制御  ユーザーごとのサービスカスタマイズ Webサービスの実装において定番機能。 毎度、実装していると思います。

Slide 4

Slide 4 text

4 Copyright © Xchange Solutions All right reserved. Laravelにおける認証の仕組み  認証は、middlewareを使って実現。  middlewareは、StackPHPというライブラリをベース にしている。 http://stackphp.com/より引用 Symfonyの HttpKernelInterfaceを使う前提はあるが、フレームワーク に依存しない汎用性の高いミドルウェアを作ることができる。 Appがコアとなる処理 Session/Authがミドルウェア部分

Slide 5

Slide 5 text

5 Copyright © Xchange Solutions All right reserved. 認証を処理するmiddlewareの仕組み Pipeline Design Pattern による実装 send() then() through() TASK1 TASK2 TASK3 …. (new Pipeline($this->app)) ->send($request) ->through($this->middleware) ->then($this->dispatchToRouter()); ※Illuminate¥Foundation¥Http¥Kernelより一部省略して引用。 ※Pipelineをarray_reduceを使って関数型の書き方で実装。 ← 各タスクに流すリクエスト情報 ← middlewareの配列 ← 最終的にControllerのメソッドへ Pipelineに処理を見立てる

Slide 6

Slide 6 text

6 Copyright © Xchange Solutions All right reserved. Laravelで認証ページを作る方法 1. ひな形(scaffold)を使う 2. 自分で実装する 3. その他 1. BASIC認証 2. OAuth認証(クライアント)

Slide 7

Slide 7 text

7 Copyright © Xchange Solutions All right reserved. ひな形(scaffold)を使ってみよう laravel new (プロジェクト名) cd (プロジェクト名) chmod 777 -R storage/ ※.env ファイルのDB設定、メールサーバー設定を調整 php artisan make:auth php artisan migrate プロジェクトを作成 認証のひな形を作成

Slide 8

Slide 8 text

8 Copyright © Xchange Solutions All right reserved. ひな形のルーティング情報 +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | home | | App¥Http¥Controllers¥HomeController@index | web,auth | | | GET|HEAD | login | login | App¥Http¥Controllers¥Auth¥LoginController@showLoginForm | web,guest | | | POST | login | | App¥Http¥Controllers¥Auth¥LoginController@login | web,guest | | | POST | logout | | App¥Http¥Controllers¥Auth¥LoginController@logout | web | | | POST | password/email | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@sendResetLinkEmail | web,guest | | | GET|HEAD | password/reset | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@showLinkRequestForm | web,guest | | | POST | password/reset | | App¥Http¥Controllers¥Auth¥ResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset/{token} | | App¥Http¥Controllers¥Auth¥ResetPasswordController@showResetForm | web,guest | | | GET|HEAD | register | | App¥Http¥Controllers¥Auth¥RegisterController@showRegistrationForm | web,guest | | | POST | register | | App¥Http¥Controllers¥Auth¥RegisterController@register | web,guest | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ ルーティング情報をチェック php artisan route:list ※赤枠が追加された認証のひな形部分

Slide 9

Slide 9 text

9 Copyright © Xchange Solutions All right reserved. 認証ページの種類 登録ページ(/register) ログインページ(/login) パスワードリセットページ(/password/reset) ホーム(/home) ログアウト(/logout) ログイン認証前に 使うページ ログイン認証後に 使うページ

Slide 10

Slide 10 text

10 Copyright © Xchange Solutions All right reserved. ひな形のルーティング情報:認証前 +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | home | | App¥Http¥Controllers¥HomeController@index | web,auth | | | GET|HEAD | login | login | App¥Http¥Controllers¥Auth¥LoginController@showLoginForm | web,guest | | | POST | login | | App¥Http¥Controllers¥Auth¥LoginController@login | web,guest | | | POST | logout | | App¥Http¥Controllers¥Auth¥LoginController@logout | web | | | POST | password/email | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@sendResetLinkEmail | web,guest | | | GET|HEAD | password/reset | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@showLinkRequestForm | web,guest | | | POST | password/reset | | App¥Http¥Controllers¥Auth¥ResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset/{token} | | App¥Http¥Controllers¥Auth¥ResetPasswordController@showResetForm | web,guest | | | GET|HEAD | register | | App¥Http¥Controllers¥Auth¥RegisterController@showRegistrationForm | web,guest | | | POST | register | | App¥Http¥Controllers¥Auth¥RegisterController@register | web,guest | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ HTTPメソッド名 URI情報 Action情報 (Controller層) Middleware情報 (Filter層) 認証前に使うページに指定されているmiddleware web, guest

Slide 11

Slide 11 text

11 Copyright © Xchange Solutions All right reserved. 認証の仕組み(認証前) Controller層 Filter層 リクエスト レスポンス 認証情報があれば、/home にリダイレクトするmiddleware セッション情報を取り扱う middlewareグループ ※middlewareは、App¥Http¥Kernelにて定義 web guest

Slide 12

Slide 12 text

12 Copyright © Xchange Solutions All right reserved. ひな形のルーティング情報:認証後 +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | home | | App¥Http¥Controllers¥HomeController@index | web,auth | | | GET|HEAD | login | login | App¥Http¥Controllers¥Auth¥LoginController@showLoginForm | web,guest | | | POST | login | | App¥Http¥Controllers¥Auth¥LoginController@login | web,guest | | | POST | logout | | App¥Http¥Controllers¥Auth¥LoginController@logout | web | | | POST | password/email | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@sendResetLinkEmail | web,guest | | | GET|HEAD | password/reset | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@showLinkRequestForm | web,guest | | | POST | password/reset | | App¥Http¥Controllers¥Auth¥ResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset/{token} | | App¥Http¥Controllers¥Auth¥ResetPasswordController@showResetForm | web,guest | | | GET|HEAD | register | | App¥Http¥Controllers¥Auth¥RegisterController@showRegistrationForm | web,guest | | | POST | register | | App¥Http¥Controllers¥Auth¥RegisterController@register | web,guest | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ HTTPメソッド名 URI情報 Action情報 (Controller層) Middleware情報 (Filter層) 認証後に使うページに指定されているmiddleware web, auth

Slide 13

Slide 13 text

13 Copyright © Xchange Solutions All right reserved. 認証の仕組み(認証後) Controller層 Filter層 リクエスト レスポンス 認証情報がなければ、 AuthenticationExceptionを 投げるmiddleware その後、App¥Exceptions¥Handler.php でルーティング名 ‘login’へリダイレクト セッション情報を取り扱う middlewareグループ ※middlewareは、App¥Http¥Kernelにて定義 web auth

Slide 14

Slide 14 text

14 Copyright © Xchange Solutions All right reserved. 補足:ルーティング名とは? +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | home | | App¥Http¥Controllers¥HomeController@index | web,auth | | | GET|HEAD | login | login | App¥Http¥Controllers¥Auth¥LoginController@showLoginForm | web,guest | | | POST | login | | App¥Http¥Controllers¥Auth¥LoginController@login | web,guest | | | POST | logout | | App¥Http¥Controllers¥Auth¥LoginController@logout | web | | | POST | password/email | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@sendResetLinkEmail | web,guest | | | GET|HEAD | password/reset | | App¥Http¥Controllers¥Auth¥ForgotPasswordController@showLinkRequestForm | web,guest | | | POST | password/reset | | App¥Http¥Controllers¥Auth¥ResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset/{token} | | App¥Http¥Controllers¥Auth¥ResetPasswordController@showResetForm | web,guest | | | GET|HEAD | register | | App¥Http¥Controllers¥Auth¥RegisterController@showRegistrationForm | web,guest | | | POST | register | | App¥Http¥Controllers¥Auth¥RegisterController@register | web,guest | +--------+----------+------------------------+-------+------------------------------------------------------------------------+--------------+ ルーティング情報をチェック php artisan route:list ルーティング名。 ヘルパー関数 route() を使ってURLを呼び 出せるようになります。 例:route(‘login’)

Slide 15

Slide 15 text

15 Copyright © Xchange Solutions All right reserved. 補足: Routing Annotationの場合の指定例 /** * トップページ * @Get(“/", as="top.get") * @Post(“/", as="top.post") * @Get("/index.html", as="top.index.get") * @Post("/index.html", as="top.index.post") * @Middleware({"web", "auth:web"}) * @param Request $request * @return Response * @throws IllegalParameterException */ ルーティング名

Slide 16

Slide 16 text

16 Copyright © Xchange Solutions All right reserved. 独自実装する場合① config/auth.phpにGuardとProviderの設定を追加。 /* |----------------------------------------- | Authentication Guards |----------------------------------------- */ // 認証ガード 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', ], //追加 for admin 'admin' => [ 'driver' => 'session', // セッション認証 'provider' => 'admins', // 対応するプロバイダー ], ], /* |----------------------------------------- | User Providers |----------------------------------------- */ // 認証プロバイダー 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App¥User::class, ], 'admins' => [ 'driver' => 'eloquent', 'model' => App¥Admin::class, ], ], ※driverはeloquent/databaseをサポート ※driverはsession/tokenをサポート Guard(認証種別) Provider(Guardに対応する認証モデル情報)

Slide 17

Slide 17 text

17 Copyright © Xchange Solutions All right reserved. 独自実装する場合② 認証インターフェイス Authenticatable Illuminate¥Contracts¥Auth¥Authenticatable I 認証する対象モデルに対してAuthenticatableのインターフェイスを 適用&Authenticatableを実装したトレイトを組み込み Illuminate¥Auth¥Authenticatable as AuthenticableTrait 認証トレイト AuthenticatableTrait T ※モデルの対象となるキー名を設定する。 認証対象としたいモデル

Slide 18

Slide 18 text

18 Copyright © Xchange Solutions All right reserved. 独自実装する場合③ Guardに対応するログイン・ログアウトをControllerに実装。 /** * ログイン処理 * @Post("admin_tools/login" , as="admin.login.post") * @return View */ public function postLogin() { // 認証 $credential = [ 'login_id' => Input::get('login_id'), 'password' => Input::get('login_pw'), 'status' => 1, ]; if (Auth::guard('admin')->attempt($credential)) { // ログイン成功 return redirect(route(‘admin.top’)); } // ログイン失敗 $errors->add(‘login_id’, ‘ログインIDまたはパスワードに誤りがあります。’); return view("admin.login", compact('errors')); } /** * ログイン表示 * @Get("admin/login" , as="admin.login.get") * @return View */ public function login() { if (Auth::guard('admin')->check()) { // ログイン済みならメニューへ return redirect(route("admin.top")); } $errors = new MessageBag(); return view("admin.login", compact('errors')); } /** * ログアウト処理+表示 * @Get(“admin_tools/logout” , as=“admin.logout”) * @return View */ public function logout() { if (!Auth::guard('admin')->check()) { Log::debug('Not logined.'); return redirect(route("admin.login.get")); } Auth::guard('admin')->logout(); return view("admin.logout"); } ※guardの種別を指定しない場合、デフォルトのguardが使用される。 ログイン表示 ログイン処理+リダイレクト ログアウト表示

Slide 19

Slide 19 text

19 Copyright © Xchange Solutions All right reserved. 独自実装する場合④ auth middleware を拡張 /** * Handle an incoming request. * * @param ¥Illuminate¥Http¥Request $request * @param ¥Closure $next * @param string $guard * @return mixed * * @throws ¥Illuminate¥Auth¥AuthenticationException */ public function handle($request, Closure $next, $guard) { if ($this->auth->guard($guard)->check()) { return $next($request); } // $guard の種類によってログイン表示先を変更 return redirect(route($guard.".login")); } 参考:Illuminate¥Auth¥Middleware¥Authenticate Guardの種類に応じてログ インページをリダイレクト するような場合の実装例

Slide 20

Slide 20 text

20 Copyright © Xchange Solutions All right reserved. 独自実装する場合⑤ 認証をかけたいルーティング情報にmiddlewareを設定 * @Middleware({"web", "auth:admin"}) * @Middleware({"web", "auth:web"}) 設定で指定したGuardの種 類をmiddlewareの引数に指 定する。 ※上記は Routing Annotationで指定した例

Slide 21

Slide 21 text

21 Copyright © Xchange Solutions All right reserved. 認証の基本は、auth middleware Controller層 Filter層 リクエスト レスポンス 認証情報がなければ、対応するGuard に基づくログインページへリダイレク トするmiddleware。 セッション情報を取り扱う middlewareグループ ※middlewareは、App¥Http¥Kernelにて定義 web auth:(Guard種別)

Slide 22

Slide 22 text

22 Copyright © Xchange Solutions All right reserved. その他:BASIC認証のmiddleware Controller層 Filter層 リクエスト レスポンス BASIC認証を行うMiddleware ※middlewareは、App¥Http¥Kernelにて定義 auth.basic 対象となるURIのmiddlewareに指定。

Slide 23

Slide 23 text

23 Copyright © Xchange Solutions All right reserved. その他:OAuth client+Auth middleware composer require laravel/socialite インストール方法 config/app.phpに以下を追加 設定方法 'providers' => [ : // Other service providers... Laravel¥Socialite¥SocialiteServiceProvider::class, ], 'aliases' => [ : // Additional aliases 'Socialite' => Laravel¥Socialite¥Facades¥Socialite::class, ],

Slide 24

Slide 24 text

24 Copyright © Xchange Solutions All right reserved. その他:OAuth client+Auth middleware config/services.phpに以下を追加。.envにも対応する値を設定。 設定方法 'facebook' => [ 'client_id' => env('FACEBOOK_ID'), 'client_secret' => env('FACEBOOK_SECRET'), 'redirect' => env('FACEBOOK_CALLBACK_URL'), ],

Slide 25

Slide 25 text

25 Copyright © Xchange Solutions All right reserved. その他:OAuth client+Auth middleware OAuthクライアント OAuthサーバー redirect ログインページ client_id redirect_uri scope state ログインOKならば コールバック callback code (認可コード) state ① ② ③ ④ callback の中でユーザー情報を取得 し、会員登録・ログイン処理を行う。 redirectでOAuthサーバーへリダイ レクト

Slide 26

Slide 26 text

26 Copyright © Xchange Solutions All right reserved. その他:OAuth client+Auth middleware /** * OAuthサーバーへのリダイレクト * @Get(“facebook/redirect”, as=“facebook.redirect”) * @return response */ public function redirectToProvider() { return Socialite::driver('facebook')->redirect(); } /** * OAuthサーバーからのコールバック * @Get(“facebook/callback”, as=“facebook.callback”) * @return response */ public function handleProviderCallback(SocialAccountService $service) { // Oauthサーバーからユーザー情報の取得 $socialUser = Socialite::driver('facebook')->user(); // ユーザー情報の登録 $user = User::firstOrCreate([ ‘nickname’ => $socialUser->nickname, ‘email’ => $socialUser->email, ‘token’ => $socialUser->token, ‘refresh_token’ => $socialUser->refreshToken, ‘expires_in’ => $socialUser->expiresIn, ]); // ログイン状態とする Auth::guard(‘web’)->login($user); // リダイレクト return redirect()->to('/home'); } OAuthServerへのリダイレクト(Pg22①) OAuthServerからのコールバック(Pg22④) Controllerの実装例 Socialite::driver(Oauthサーバー種別)->user(); 以下が実行される。 (1) 認可コードよりアクセストークン取得 (2) アクセストークンを使ってユーザー情報 取得

Slide 27

Slide 27 text

27 Copyright © Xchange Solutions All right reserved. よくあるハマりどころ  “web“middlewareグループの指定漏れ →Sessionを使って認証情報を保持しているため、認証状態を チェックする必要のあるURIにおいては、必ず指定する必要が あります。  remember_tokenがないというエラーがでる。 →remember_tokenを無効化する対応を別途追加する必要があ ります。 ※http://laravel.io/forum/05-21-2014-how-to-disable-remember-token

Slide 28

Slide 28 text

28 Copyright © Xchange Solutions All right reserved. まとめ  Laravelの認証機構は、auth middlewareが基本。  OAuth認証やBASIC認証とも組み合わせることができる。  複数の認証方式(Multi-Auth)にも対応。  ひな形やTraitなど参考になるソースも多く、カスタマイズ がやりやすい。 Let’s use Laravel!