ตัวอย่างการ login โดยใช้ Active Directory ( AD ) หรือ LDAP version ของ Microsoft ทำการ authentication แทนข้อมูลผู้ใช้ในตาราง users
- ติดตั้ง Adldap2/Adldap2-Laravel โดยใช้ command
command 12cd D:\xampp\htdocs\laravel_dev
composer require adldap2/adldap2-laravel
- ลงทะเบียน Adldap facade โดยเปิดไฟล์ config/app.php
config/app.php 12345'aliases'
=> [
'Adldap'
=> Adldap\Laravel\Facades\Adldap::
class
,
],
- Publish Adldap service providers โดยใช้ command
command 12php artisan vendor:publish --provider="Adldap\Laravel\AdldapServiceProvider"
php artisan vendor:publish --provider="Adldap\Laravel\AdldapAuthServiceProvider"
- เปลี่ยน driver ของ user provider ในไฟล์ config/auth.php จาก eloquent เป็น ldap
config/auth.php 12345'providers'
=> [
'users'
=> [
'driver'
=>
'ldap'
,
// eloquent
'model'
=> App\User::
class
,
],
- เพิ่ม config .env ถ้าใช้ synology จะได้ LDAP Server ประมาณ
- IP
- 192.168.1.101
- Base DN:
- dc=phunsanit
- Bind DN:
- uid=root,cn=users,dc=phunsanit
ก็จะเพิ่มไปประมาณ
.env 1234567LDAP_SCHEMA=ActiveDirectory
LDAP_HOSTS=192.168.1.101
LDAP_LOGGING=true
LDAP_BASE_DN=dc=phunsanit
LDAP_USER_ATTRIBUTE=uid
LDAP_USER_FORMAT=uid=%s,cn=users,dc=phunsanit
LDAP_CONNECTION=default
โดยหลักการคือ
- LDAP_BASE_DN
- คือจุดเริ่มต้นข้อมูลที่เราสนใจ
- LDAP_USER_FORMAT
- จะโดน replace กับ user ที่ผู้ใช้กรอกข้อมูลเข้ามาเช่น user: pitt.p แทนที่ uid=%s,cn=users,dc=phunsanit จะได้ uid=pitt.p,cn=users,dc=phunsanit
โดยมีที่มาจาการทดลอง login ได้โดยใช้โปรแกรม Apache Directory Studio โดยชั้นของข้อมูลจะเป็น dc=phunsanit > cn=users > uid=pitt.p > ข้อมูลของ user นี้
- แก้ ตาราง user อาจจะใช้ database/migrations/2014_10_12_000000_create_users_table.php
database/migrations/2014_10_12_000000_create_users_table.php 123456789101112131415161718public
function
up()
{
Schema::create(
'users'
,
function
(Blueprint
$table
) {
$table
->bigIncrements(
'id'
);
$table
->string(
'name'
);
/* remove
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
*/
//add
$table
->string(
'phone'
);
$table
->string(
'password'
);
$table
->rememberToken();
$table
->timestamps();
});
}
และใช้ command
command 1php artisan migrate
(ถ้าไม่ได้เช็คให้ดีว่า connect database ถูกต้อง)
- แก้ config/ldap.php ประมาณ
config/ldap.php 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243<?php
return
[
/*
|--------------------------------------------------------------------------
| Logging
|--------------------------------------------------------------------------
|
| This option enables logging all LDAP operations on all configured
| connections such as bind requests and CRUD operations.
|
| Log entries will be created in your default logging stack.
|
| This option is extremely helpful for debugging connectivity issues.
|
*/
'logging'
=> env(
'LDAP_LOGGING'
, false),
/*
|--------------------------------------------------------------------------
| Connections
|--------------------------------------------------------------------------
|
| This array stores the connections that are added to Adldap. You can add
| as many connections as you like.
|
| The key is the name of the connection you wish to use and the value is
| an array of configuration settings.
|
*/
'connections'
=> [
'default'
=> [
/*
|--------------------------------------------------------------------------
| Auto Connect
|--------------------------------------------------------------------------
|
| If auto connect is true, Adldap will try to automatically connect to
| your LDAP server in your configuration. This allows you to assume
| connectivity rather than having to connect manually
| in your application.
|
| If this is set to false, you **must** connect manually before running
| LDAP operations. Otherwise, you will receive exceptions.
|
*/
'auto_connect'
=> env(
'LDAP_AUTO_CONNECT'
, true),
/*
|--------------------------------------------------------------------------
| Connection
|--------------------------------------------------------------------------
|
| The connection class to use to run raw LDAP operations on.
|
| Custom connection classes must implement:
|
| Adldap\Connections\ConnectionInterface
|
*/
'connection'
=> Adldap\Connections\Ldap::
class
,
/*
|--------------------------------------------------------------------------
| Connection Settings
|--------------------------------------------------------------------------
|
| This connection settings array is directly passed into the Adldap constructor.
|
| Feel free to add or remove settings you don't need.
|
*/
'settings'
=> [
/*
|--------------------------------------------------------------------------
| Schema
|--------------------------------------------------------------------------
|
| The schema class to use for retrieving attributes and generating models.
|
| You can also set this option to `null` to use the default schema class.
|
| For OpenLDAP, you must use the schema:
|
| Adldap\Schemas\OpenLDAP::class
|
| For FreeIPA, you must use the schema:
|
| Adldap\Schemas\FreeIPA::class
|
| Custom schema classes must implement Adldap\Schemas\SchemaInterface
|
*/
'schema'
=> Adldap\Schemas\ActiveDirectory::
class
,
/*
|--------------------------------------------------------------------------
| Account Prefix
|--------------------------------------------------------------------------
|
| The account prefix option is the prefix of your user accounts in LDAP directory.
|
| This string is prepended to all authenticating users usernames.
|
*/
'account_prefix'
=> env(
'LDAP_ACCOUNT_PREFIX'
,
''
),
/*
|--------------------------------------------------------------------------
| Account Suffix
|--------------------------------------------------------------------------
|
| The account suffix option is the suffix of your user accounts in your LDAP directory.
|
| This string is appended to all authenticating users usernames.
|
*/
'account_suffix'
=> env(
'LDAP_ACCOUNT_SUFFIX'
,
''
),
/*
|--------------------------------------------------------------------------
| Domain Controllers
|--------------------------------------------------------------------------
|
| The domain controllers option is an array of servers located on your
| network that serve Active Directory. You can insert as many servers or
| as little as you'd like depending on your forest (with the
| minimum of one of course).
|
| These can be IP addresses of your server(s), or the host name.
|
*/
'hosts'
=>
explode
(
' '
, env(
'LDAP_HOSTS'
,
'corp-dc1.corp.acme.org corp-dc2.corp.acme.org'
)),
/*
|--------------------------------------------------------------------------
| Port
|--------------------------------------------------------------------------
|
| The port option is used for authenticating and binding to your LDAP server.
|
*/
'port'
=> env(
'LDAP_PORT'
, 389),
/*
|--------------------------------------------------------------------------
| Timeout
|--------------------------------------------------------------------------
|
| The timeout option allows you to configure the amount of time in
| seconds that your application waits until a response
| is received from your LDAP server.
|
*/
'timeout'
=> env(
'LDAP_TIMEOUT'
, 5),
/*
|--------------------------------------------------------------------------
| Base Distinguished Name
|--------------------------------------------------------------------------
|
| The base distinguished name is the base distinguished name you'd
| like to perform query operations on. An example base DN would be:
|
| dc=corp,dc=acme,dc=org
|
| A correct base DN is required for any query results to be returned.
|
*/
'base_dn'
=> env(
'LDAP_BASE_DN'
,
'dc=corp,dc=acme,dc=org'
),
/*
|--------------------------------------------------------------------------
| LDAP Username & Password
|--------------------------------------------------------------------------
|
| When connecting to your LDAP server, a username and password is required
| to be able to query and run operations on your server(s). You can
| use any user account that has these permissions. This account
| does not need to be a domain administrator unless you
| require changing and resetting user passwords.
|
*/
'username'
=> env(
'LDAP_USERNAME'
),
'password'
=> env(
'LDAP_PASSWORD'
),
/*
|--------------------------------------------------------------------------
| Follow Referrals
|--------------------------------------------------------------------------
|
| The follow referrals option is a boolean to tell active directory
| to follow a referral to another server on your network if the
| server queried knows the information your asking for exists,
| but does not yet contain a copy of it locally.
|
| This option is defaulted to false.
|
*/
'follow_referrals'
=> false,
/*
|--------------------------------------------------------------------------
| SSL & TLS
|--------------------------------------------------------------------------
|
| If you need to be able to change user passwords on your server, then an
| SSL or TLS connection is required. All other operations are allowed
| on unsecured protocols.
|
| One of these options are definitely recommended if you
| have the ability to connect to your server securely.
|
*/
'use_ssl'
=> env(
'LDAP_USE_SSL'
, false),
'use_tls'
=> env(
'LDAP_USE_TLS'
, false),
],
],
],
];
จุดสำคัญคือ
- schema
- จะบอกว่าใช้ protocal อะไร เช่นถ้าใช้ AD จะต้องเลือก Adldap\Schemas\ActiveDirectory::class, ถ้าใช้ LDAP ชนิดอื่นต้องเปลี่ยนจุดนี้
- username
- user ที่มีสิทธิแก้ข้อมูลใน LDAP server ถ้าไม่มีหรือไม่ต้องการแก้ข้อมูลเข้าไป (ห้ามใช้เด็ดขาด) เพราะจะทำให้ login ไม่สำเร็จ
- password
- password ของ user ที่มีสิทธิแก้ข้อมูลใน LDAP server ถ้าไม่มีหรือไม่ต้องการแก้ข้อมูลเข้าไป (ห้ามใช้เด็ดขาด) เพราะจะทำให้ login ไม่สำเร็จ
- แก้ config/ldap_auth.php ประมาณ
config/ldap_auth.php 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362<?php
return
[
/*
|--------------------------------------------------------------------------
| Connection
|--------------------------------------------------------------------------
|
| The LDAP connection to use for Laravel authentication.
|
| You must specify connections in your `config/ldap.php` configuration file.
|
*/
'connection'
=> env(
'LDAP_CONNECTION'
,
'default'
),
/*
|--------------------------------------------------------------------------
| Provider
|--------------------------------------------------------------------------
|
| The LDAP authentication provider to use depending
| if you require database synchronization.
|
| For synchronizing LDAP users to your local applications database, use the provider:
|
| Adldap\Laravel\Auth\DatabaseUserProvider::class
|
| Otherwise, if you just require LDAP authentication, use the provider:
|
| Adldap\Laravel\Auth\NoDatabaseUserProvider::class
|
*/
'provider'
=> Adldap\Laravel\Auth\DatabaseUserProvider::
class
,
/*
|--------------------------------------------------------------------------
| Model
|--------------------------------------------------------------------------
|
| The model to utilize for authentication and importing.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'model'
=> App\User::
class
,
/*
|--------------------------------------------------------------------------
| Rules
|--------------------------------------------------------------------------
|
| Rules allow you to control user authentication requests depending on scenarios.
|
| You can create your own rules and insert them here.
|
| All rules must extend from the following class:
|
| Adldap\Laravel\Validation\Rules\Rule
|
*/
'rules'
=> [
// Denys deleted users from authenticating.
Adldap\Laravel\Validation\Rules\DenyTrashed::
class
,
// Allows only manually imported users to authenticate.
// Adldap\Laravel\Validation\Rules\OnlyImported::class,
],
/*
|--------------------------------------------------------------------------
| Scopes
|--------------------------------------------------------------------------
|
| Scopes allow you to restrict the LDAP query that locates
| users upon import and authentication.
|
| All scopes must implement the following interface:
|
| Adldap\Laravel\Scopes\ScopeInterface
|
*/
'scopes'
=> [
// Only allows users with a user principal name to authenticate.
// Suitable when using ActiveDirectory.
// Adldap\Laravel\Scopes\UpnScope::class,
// Only allows users with a uid to authenticate.
// Suitable when using OpenLDAP.
// Adldap\Laravel\Scopes\UidScope::class,
],
'identifiers'
=> [
/*
|--------------------------------------------------------------------------
| LDAP
|--------------------------------------------------------------------------
|
| Locate Users By:
|
| This value is the users attribute you would like to locate LDAP
| users by in your directory.
|
| For example, using the default configuration below, if you're
| authenticating users with an email address, your LDAP server
| will be queried for a user with the a `userprincipalname`
| equal to the entered email address.
|
| Bind Users By:
|
| This value is the users attribute you would
| like to use to bind to your LDAP server.
|
| For example, when a user is located by the above attribute,
| the users attribute you specify below will be used as
| the 'username' to bind to your LDAP server.
|
| This is usually their distinguished name.
|
*/
'ldap'
=> [
'locate_users_by'
=>
'userprincipalname'
,
'bind_users_by'
=>
'distinguishedname'
,
],
'database'
=> [
/*
|--------------------------------------------------------------------------
| GUID Column
|--------------------------------------------------------------------------
|
| The value of this option is the database column that will contain the
| LDAP users global identifier. This column does not need to be added
| to the sync attributes below. It is synchronized automatically.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'guid_column'
=>
'objectguid'
,
/*
|--------------------------------------------------------------------------
| Username Column
|--------------------------------------------------------------------------
|
| The value of this option is the database column that contains your
| users login username.
|
| This column must be added to your sync attributes below to be
| properly synchronized.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'username_column'
=>
'email'
,
],
/*
|--------------------------------------------------------------------------
| Windows Authentication Middleware (SSO)
|--------------------------------------------------------------------------
|
| Local Users By:
|
| This value is the users attribute you would like to locate LDAP
| users by in your directory.
|
| For example, if 'samaccountname' is the value, then your LDAP server is
| queried for a user with the 'samaccountname' equal to the value of
| $_SERVER['AUTH_USER'].
|
| If a user is found, they are imported (if using the DatabaseUserProvider)
| into your local database, then logged in.
|
| Server Key:
|
| This value represents the 'key' of the $_SERVER
| array to pull the users account name from.
|
| For example, $_SERVER['AUTH_USER'].
|
*/
'windows'
=> [
'locate_users_by'
=>
'samaccountname'
,
'server_key'
=>
'AUTH_USER'
,
],
],
'passwords'
=> [
/*
|--------------------------------------------------------------------------
| Password Sync
|--------------------------------------------------------------------------
|
| The password sync option allows you to automatically synchronize users
| LDAP passwords to your local database. These passwords are hashed
| natively by Laravel using the Hash::make() method.
|
| Enabling this option would also allow users to login to their accounts
| using the password last used when an LDAP connection was present.
|
| If this option is disabled, the local database account is applied a
| random 16 character hashed password upon first login, and will
| lose access to this account upon loss of LDAP connectivity.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'sync'
=> env(
'LDAP_PASSWORD_SYNC'
, false),
/*
|--------------------------------------------------------------------------
| Column
|--------------------------------------------------------------------------
|
| This is the column of your users database table
| that is used to store passwords.
|
| Set this to `null` if you do not have a password column.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'column'
=>
'password'
,
],
/*
|--------------------------------------------------------------------------
| Login Fallback
|--------------------------------------------------------------------------
|
| The login fallback option allows you to login as a user located in the
| local database if active directory authentication fails.
|
| Set this to true if you would like to enable it.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'login_fallback'
=> env(
'LDAP_LOGIN_FALLBACK'
, false),
/*
|--------------------------------------------------------------------------
| Sync Attributes
|--------------------------------------------------------------------------
|
| Attributes specified here will be added / replaced on the user model
| upon login, automatically synchronizing and keeping the attributes
| up to date.
|
| The array key represents the users Laravel model key, and
| the value represents the users LDAP attribute.
|
| You **must** include the users login attribute here.
|
| This option is only applicable to the DatabaseUserProvider.
|
*/
'sync_attributes'
=> [
// 'field_in_local_db' => 'attribute_in_ldap_server',
'username'
=>
'uid'
,
'email'
=>
'userprincipalname'
,
'name'
=>
'cn'
,
'phone'
=>
'telephonenumber'
,
],
/*
|--------------------------------------------------------------------------
| Logging
|--------------------------------------------------------------------------
|
| User authentication attempts will be logged using Laravel's
| default logger if this setting is enabled.
|
| No credentials are logged, only usernames.
|
| This is usually stored in the '/storage/logs' directory
| in the root of your application.
|
| This option is useful for debugging as well as auditing.
|
| You can freely remove any events you would not like to log below,
| as well as use your own listeners if you would prefer.
|
*/
'logging'
=> [
'enabled'
=> env(
'LDAP_LOGGING'
, true),
'events'
=> [
\Adldap\Laravel\Events\Importing::
class
=> \Adldap\Laravel\Listeners\LogImport::
class
,
\Adldap\Laravel\Events\Synchronized::
class
=> \Adldap\Laravel\Listeners\LogSynchronized::
class
,
\Adldap\Laravel\Events\Synchronizing::
class
=> \Adldap\Laravel\Listeners\LogSynchronizing::
class
,
\Adldap\Laravel\Events\Authenticated::
class
=> \Adldap\Laravel\Listeners\LogAuthenticated::
class
,
\Adldap\Laravel\Events\Authenticating::
class
=> \Adldap\Laravel\Listeners\LogAuthentication::
class
,
\Adldap\Laravel\Events\AuthenticationFailed::
class
=> \Adldap\Laravel\Listeners\LogAuthenticationFailure::
class
,
\Adldap\Laravel\Events\AuthenticationRejected::
class
=> \Adldap\Laravel\Listeners\LogAuthenticationRejection::
class
,
\Adldap\Laravel\Events\AuthenticationSuccessful::
class
=> \Adldap\Laravel\Listeners\LogAuthenticationSuccess::
class
,
\Adldap\Laravel\Events\DiscoveredWithCredentials::
class
=> \Adldap\Laravel\Listeners\LogDiscovery::
class
,
\Adldap\Laravel\Events\AuthenticatedWithWindows::
class
=> \Adldap\Laravel\Listeners\LogWindowsAuth::
class
,
\Adldap\Laravel\Events\AuthenticatedModelTrashed::
class
=> \Adldap\Laravel\Listeners\LogTrashedModel::
class
,
],
],
'usernames'
=> [
'ldap'
=> [
// replace this line:
// 'discover' => 'userprincipalname',
// with this one:
'discover'
=> env(
'LDAP_USER_ATTRIBUTE'
,
'userprincipalname'
),
// replace this line:
// 'authenticate' => 'distinguishedname',
// with this one:
'authenticate'
=> env(
'LDAP_USER_ATTRIBUTE'
,
'distinguishedname'
),
],
// replace this line:
// 'eloquent' => 'email',
// with this one:
'eloquent'
=>
'username'
,
],
];
จุดสำคัญคือ
- sync_attributes
- บอกให้ copy ค่าจาก attribute อะไรไปเก็บในตาราง users
- usernames
- คือการผูก username ในระบบ login ในตาราง ใน LDAP เข้าไว้ด้วยกัน
- สร้างระบบ login โดย command
command 1php artisan make:auth
- แก้ login template ให้ใช้ username แทน email เปิด resources/views/auth/login.blade.php จาก
resources/views/auth/login.blade.php 12345678910111213<div
class
=
"form-group row"
>
<label
for
=
"email"
class
=
"col-md-4 col-form-label text-md-right"
>{{ __(
'E-Mail Address'
) }}</label>
<div
class
=
"col-md-6"
>
<input id=
"email"
type=
"email"
class
=
"form-control @error('email') is-invalid @enderror"
name=
"email"
value=
"{{ old('email') }}"
required autocomplete=
"email"
autofocus>
@error(
'email'
)
<span
class
=
"invalid-feedback"
role=
"alert"
>
<strong>{{
$message
}}</strong>
</span>
@enderror
</div>
</div>
เป็น
resources/views/auth/login.blade.php 12345678910111213<div
class
=
"form-group row"
>
<label
for
=
"username"
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 @error('username') is-invalid @enderror"
name=
"username"
value=
"{{ old('username') }}"
required autocomplete=
"username"
autofocus>
@error(
'username'
)
<span
class
=
"invalid-feedback"
role=
"alert"
>
<strong>{{
$message
}}</strong>
</span>
@enderror
</div>
</div>
หลักๆ คือ replace email แทนที่โดย username นั่นละ ลบ link เกี่ยวกับการ reset password ใน
user link 123<a
class
=
"btn btn-link"
href=
""
>
</a>
- แก้ app/Http/Controllers/Auth/LoginController.php โดยจะเป็นส่วนที่ทำการ login และทำหน้าที่ insert / update ข้อมูลกลับไปให้ตาราง users แก้ประมาณ
app/Http/Controllers/Auth/LoginController.php 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204<?php
namespace
App\Http\Controllers\Auth;
use
Adldap\Laravel\Facades\Adldap;
use
App\Http\Controllers\Controller;
use
Illuminate\Foundation\Auth\AuthenticatesUsers;
use
Illuminate\Http\Request;
use
Illuminate\Support\Facades\Auth;
class
LoginController
extends
Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use
AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected
$redirectTo
=
'/home'
;
/**
* Create a new controller instance.
*
* @return void
*/
public
function
__construct()
{
$this
->middleware(
'guest'
)->except(
'logout'
);
}
/* cusstom */
/**
* Handle a login request to the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*
* @throws \Illuminate\Validation\ValidationException
*/
public
function
login(Request
$request
)
{
$this
->validateLogin(
$request
);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if
(
$this
->hasTooManyLoginAttempts(
$request
)) {
$this
->fireLockoutEvent(
$request
);
return
$this
->sendLockoutResponse(
$request
);
}
if
(
$this
->attemptLogin(
$request
)) {
return
$this
->sendLoginResponse(
$request
);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this
->incrementLoginAttempts(
$request
);
return
$this
->sendFailedLoginResponse(
$request
);
}
/**
* Attempt to log the user into the application.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected
function
attemptLogin(Request
$request
)
{
$credentials
=
$request
->only(
$this
->username(),
'password'
);
$username
=
$credentials
[
$this
->username()];
$password
=
$credentials
[
'password'
];
$user_format
= env(
'LDAP_USER_FORMAT'
,
'cn=%s,'
. env(
'LDAP_BASE_DN'
,
''
));
$userdn
= sprintf(
$user_format
,
$username
);
// you might need this, as reported in
// Adldap::auth()->bind($userdn, $password);
if
(Adldap::auth()->attempt(
$userdn
,
$password
,
$bindAsUser
= true)) {
// the user exists in the LDAP server, with the provided password
$user
= \App\User::where(
$this
->username(),
$username
)->first();
if
(!
$user
) {
// the user doesn't exist in the local database, so we have to create one
$user
=
new
\App\User();
$user
->username =
$username
;
$user
->password =
''
;
// you can skip this if there are no extra attributes to read from the LDAP server
// or you can move it below this if(!$user) block if you want to keep the user always
// in sync with the LDAP server
$sync_attrs
=
$this
->retrieveSyncAttributes(
$username
);
foreach
(
$sync_attrs
as
$field
=>
$value
) {
$user
->
$field
=
$value
!== null ?
$value
:
''
;
}
}
// by logging the user we create the session, so there is no need to login again (in the configured time).
// pass false as second parameter if you want to force the session to expire when the user closes the browser.
// have a look at the section 'session lifetime' in `config/session.php` for more options.
$this
->guard()->login(
$user
, true);
return
true;
}
// the user doesn't exist in the LDAP server or the password is wrong
// log error
return
false;
}
protected
function
retrieveSyncAttributes(
$username
)
{
$ldapuser
= Adldap::search()->where(env(
'LDAP_USER_ATTRIBUTE'
),
'='
,
$username
)->first();
if
(!
$ldapuser
) {
// log error
return
false;
}
// if you want to see the list of available attributes in your specific LDAP server:
// var_dump($ldapuser->attributes); exit;
// needed if any attribute is not directly accessible via a method call.
// attributes in \Adldap\Models\User are protected, so we will need
// to retrieve them using reflection.
$ldapuser_attrs
= null;
$attrs
= [];
foreach
(config(
'ldap_auth.sync_attributes'
)
as
$local_attr
=>
$ldap_attr
) {
if
(
$local_attr
==
'username'
) {
continue
;
}
$method
=
'get'
.
$ldap_attr
;
if
(method_exists(
$ldapuser
,
$method
)) {
$attrs
[
$local_attr
] =
$ldapuser
->
$method
();
continue
;
}
if
(
$ldapuser_attrs
=== null) {
$ldapuser_attrs
= self::accessProtected(
$ldapuser
,
'attributes'
);
}
if
(!isset(
$ldapuser_attrs
[
$ldap_attr
])) {
// an exception could be thrown
$attrs
[
$local_attr
] = null;
continue
;
}
if
(!
is_array
(
$ldapuser_attrs
[
$ldap_attr
])) {
$attrs
[
$local_attr
] =
$ldapuser_attrs
[
$ldap_attr
];
}
if
(
count
(
$ldapuser_attrs
[
$ldap_attr
]) == 0) {
// an exception could be thrown
$attrs
[
$local_attr
] = null;
continue
;
}
// now it returns the first item, but it could return
// a comma-separated string or any other thing that suits you better
$attrs
[
$local_attr
] =
$ldapuser_attrs
[
$ldap_attr
][0];
//$attrs[$local_attr] = implode(',', $ldapuser_attrs[$ldap_attr]);
}
return
$attrs
;
}
protected
static
function
accessProtected(
$obj
,
$prop
)
{
$reflection
=
new
\ReflectionClass(
$obj
);
$property
=
$reflection
->getProperty(
$prop
);
$property
->setAccessible(true);
return
$property
->getValue(
$obj
);
}
/**
* Get the login username to be used by the controller.
*
* @return string
*/
public
function
username()
{
return
'username'
;
}
}
จุดสำคัญคือ
- use AuthenticatesUsers
- ต้นแบบของระบบ login ที่เอามา overwrite ถ้าทำตามทั้งหมดแล้วใช้ไม่ได้ จะเป็นผู้ต้องสงสัยอันดับหนึ่งว่า แกเปลี่ยนไปใช่มั๋ยสาด
- public function login
- function ที่เขียนมา overwrite function login ใน AuthenticatesUsers เป็นแกนกลางของระบบ login ที่ข้อมูลของฟอร์ม login จะถูกส่งเข้ามาที่ function นี้เป็นที่แรก
- protected function attemptLogin
- เป็น function ที่จะใช้ตรวจสอบว่า username และ password ถูกต้องจริงรึเปล่า ถ้าถูกจะ return ค่าจากตาราง users กลับไปโดย code ตัวนี้จะอ่านค่าจาก LDAP จากกนั้นจะ insert / update ไปที่ตาราง users ด้วย
- public function username()
- เป็น function ที่บอกใช้ laravel ใช้ username แทน email ในการ login ที่แก้ใน login template
- ทดลอง login ถ้าไม่ได้กลับไปทำขั้นตอนแรกใหม่
- แก้ routes ให้ router ที่ต้องการจำเป็นต้องมีการ login ก่อนจึงใช้ได้ เปิดไฟล์ routes/web.php ลบ Auth::routes(); ออกแทนที่ด้วย
routes/web.php 1234// Auth::routes();
Route::get(
'login'
,
'Auth\LoginController@showLoginForm'
)->name(
'login'
);
Route::post(
'login'
,
'Auth\LoginController@login'
);
Route::post(
'logout'
,
'Auth\LoginController@logout'
)->name(
'logout'
);
และครอบ routes ที่ต้องการให้ต้อง login ถึงจะใช้ได้โดย
routes/web.php 12345Route::middleware(
'auth'
)->group(
function
() {
...
Route::get(
'/home'
,
'HomeController@index'
)->name(
'home'
);
...
});
- ลบส่วนที่ไม่จำเป็นออกเพื่อความปลอดภัย
- app/Http/Controllers/Auth/ForgotPasswordController.php
- app/Http/Controllers/Auth/RegisterController.php
- app/Http/Controllers/Auth/ResetPasswordController.php
- app/Http/Controllers/Auth/VerificationController.php
- database/migrations/2014_10_12_100000_create_password_resets_table.php
- resources/views/auth/passwords
- resources/views/auth/register.blade.php
- resources/views/auth/verify.blade.php
ขอบคุณ José Luis Salinas ที่เขียน laravel-simple-ldap-auth Howto: adminless LDAP authentification in Laravel ที่ช่วยไขความกระจ่างให้ config ครั้งนี้สำเร็จ