1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LaravelでシンプルなLDAP認証をシンプルに作る

Last updated at Posted at 2023-08-10

概要

Laravel関連の記事がややこしすぎるのでシンプルに書きたい。
Guardがなんじゃとか、Providerがどうのとか、そういった解説はせずに、
シンプルにコード類をまとめておきます。

  • Miracle Linux 9
  • php 8.0
  • Laravel 9.52
  • LDAPサーバー → ActiveDirectory

以下、今回のコードで作る仕組みの概略図です。
LDAP認証でログインできるシンプルなログイン画面とログイン後のページを実装します。

Webルーティング概要
image.png

LDAP認証周りの繋がり
image.png

作る必要があるもの

  • ログイン画面ログイン後の画面の表示
    • htmlの作成(resources/views配下)
      • auth/login.blade.php ... ログイン画面
      • dashboard.blade.php ... ログイン後の画面
    • 対応コントローラーの作成
      • AuthController...ログイン画面とログイン処理
      • DashboardContloller... ログイン後の画面
    • Webルーティングの設定
      • routes/web.php
  • LDAP認証周りの仕組み作成
    • LDAP認証ユーザー用のユーザーモデルを作成
      • app/Models/LdapUser.php
    • LDAP認証用のプロバイダーを作成
      • app/Providers/LdapUserProvider.php
    • 独自プロパイダ-を認識するように設定
      • app/Providers/AuthServiceProvider.php
    • 認証設定ファイルを更新
      • config/auth.php
    • 環境変数の設定
      • .env

詳細

ログイン画面・ログイン後の画面の表示

htmlの作成(resources/views配下)

それぞれのページに対応するHTMLを作成します。

auth/login.blade.php

# mkdir -p resources/views/auth
# vim resources/views/auth/login.blade.php
auth/login.blade.php
<form method="post" action="{{ route('login') }}">
    @csrf
    <label>
        ID:
        <input type="text" name="id" required>
    </label>
    <label>
        Password:
        <input type="password" name="password" required>
    </label>
    <button type="submit">Login</button>
</form>

dashboard.blade.php

# vim resources/views/dashboard.blade.php
resources/views/dashboard.blade.php
<h1>Welcome to Dashboard</h1>
<a href="{{ route('logout') }}">Logout</a>

対応コントローラーの作成

AuthController...ログイン画面の表示とログイン処理

ログイン画面の表示と、ログイン・ログアウト処理に関わるメソッドを作成します。

# php artisan make:controller AuthController
# vim app/Http/Controllers/AuthController.php 
app/Http/Controllers/AuthController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
        public function showLoginForm()
        {
                return view('auth.login');
        }

        public function login(Request $request)
        {
                $credentials = $request->only('id', 'password');

                if (Auth::guard('web')->attempt($credentials)) {
                        // デフォルトのリダイレクト先は/dashboard
                        return redirect()->route('dashboard');
                }

                return back()->withErrors(['id' => '認証に失敗しました。']);
        }


        public function logout()
        {
                Auth::logout();
                return redirect('/login');
        }
}

DashboardContloller

ログイン後の画面のコントローラーを開くための作成

# php artisan make:controller DashboardController
# vim app/Http/Controllers/DashboardController.php 
app/Http/Controllers/DashboardController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DashboardController extends Controller
{
    public function index()
    {
        return view('dashboard');
    }
}

Webルーティングの設定

作成したWebページを開けるようにルーティングを設定します。
また、dashboardに関してはmiddleware('auth')を紐づけておくことで認証が必要なページとなります。

# vim routes/web.php

routes/web.php

routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\DashboardController;

Route::get('/login', [AuthController::class, 'showLoginForm'])->name('login');
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard')->middleware('auth');
Route::post('/login', [AuthController::class, 'login']);
Route::get('/logout', [AuthController::class, 'logout'])->name('logout');

LDAP認証周りの仕組み作成

LDAP認証ユーザー用のユーザーモデルを作成

下記コマンドでモデルを作成します。

# php artisan make:model Models/LdapUser
# vim app/Models/LdapUser.php

app/Models/LdapUser.php

Authenticatableクラスをimplementsする関係上、これらの関数は使う使わないに関わらず作成しておいてください。作成しておかないとエラーが出ます。

app/Models/LdapUser.php
<?php
namespace App\Models;

use Illuminate\Contracts\Auth\Authenticatable;

class LdapUser implements Authenticatable
{
    private $username;

    public function __construct($username)
    {
        $this->username = $username;
    }

    public function getAuthIdentifierName()
    {
        return 'username';
    }

    public function getAuthIdentifier()
    {
        return $this->username;
    }

    public function getAuthPassword()
    {
        return '';
    }

    public function getRememberToken()
    {
        return null; 
    }

    public function setRememberToken($value)
    {   
    }

    public function getRememberTokenName()
    {
        return null; 
    }
}

LDAP認証用のプロバイダーを作成

下記コマンドでLDAP認証用のプロパイダーを独自に作成します。

vim app/Providers/LdapUserProvider.php

app/Providers/LdapUserProvider.php

内容を記載します。特にretrieveByIdを正しく実装するようにしてください。
ここを実装しないと、認証済チェックがうまく動かず、ログインができません。

retrieveByIdメソッドが呼び出されることにより、Auth:check()等の認証済チェックが行われています。これがnullだと認証されていない扱いになります。

app/Providers/LdapUserProvider.php
<?php
namespace App\Providers;

use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Auth\Authenticatable;

class LdapUserProvider implements UserProvider
{
        public function retrieveById($identifier)
        {
                // キーに対応するユーザーモデルを返す
                return new \App\Models\LdapUser($identifier);
        }

        public function retrieveByToken($identifier, $token)
        {
        }

        public function updateRememberToken(Authenticatable $user, $token)
        {

        }

        public function retrieveByCredentials(array $credentials)
        {
                // LDAP接続とバインドの試行。
                $ldapconn = ldap_connect(env('LDAP_HOST'), env('LDAP_PORT'));
                if ($ldapconn) {
                        ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
                        $ldapbind = @ldap_bind(LDAPバインドの処理を書く);
                        if ($ldapbind) {
                                return new \App\Models\LdapUser($credentials['id']);
                        }
                }
                return null;
        }

        public function validateCredentials(Authenticatable $user, array $credentials)
        {
                return $user !== null;
        }
}

独自プロパイダ-を認識するように設定

独自に作ったプロパイダーをLaravelに認識させるように処理を書く必要がある。

app/Providers/AuthServiceProvider.php

boot()関数に、独自のプロパイダを登録する。今回を**「ldap-provider」**という名前で登録しています。

app/Providers/AuthServiceProvider.php
// これを追加
use Illuminate\Support\Facades\Auth;
...
...

    public function boot()
    {
            // ここから
            Auth::provider('ldap-provider', function($app, array $config) {
                    return $app->make(LdapUserProvider::class);
                    return new LdapUserProvider();
            });
            // ここまで

            $this->registerPolicies();
    }

認証設定ファイルを更新

最後に認証にLDAP認証用プロパイダを使うように設定します。

vim config/auth.php

config/auth.php

Guardsのproviderに「ldap-provider」を設定します。これは任意の名称でいいです。
Providersにそれぞれ対応するプロパイダ-名(driver)とモデルを設定します。

auth.php
    'guards' => [
            'web' => [
                'driver' => 'session',
                'provider' => 'ldap',
        ],
    ],

    'providers' => [
            'ldap' => [
                'driver' => 'ldap-provider',
                'model' => App\Models\LdapUser::class,
            ],
    ],

環境変数の設定

LDAPサーバーへの接続関連の環境変数を追加します。

.env

# vim .env
下記それぞれを環境に合わせて設定
LDAP_HOST=""
LDAP_PORT=
LDAP_BIND_DN=""
LDAP_BIND_PASSWORD=""
LDAP_BASE_DN=""

試す

おわり

Laravel、わかってしまえばすごく使いやすいけど、わかるまでが大変な印象・・・
あとはデータベースから情報引いたりとかも試してみましょうかね。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?