پاسپورت لاراول
- معرفی
- ارتقاء پاسپورت
- نصب و راه اندازی
- پیکربندی
- صدور توکن های دسترسی
- اعطای کد مجوز با PKCE
- رمزهای اعطای رمز عبور
- توکن های اعطای ضمنی
- توکن های اعطای اعتبار مشتری
- توکن های دسترسی شخصی
- حفاظت از مسیرها
- محدوده توکن
- مصرف API خود با جاوا اسکریپت
- مناسبت ها
- آزمایش کردن
معرفی
لاراول در حال حاضر انجام احراز هویت از طریق فرم های ورود به سیستم سنتی را آسان می کند، اما در مورد API ها چطور؟ APIها معمولاً از نشانهها برای احراز هویت کاربران استفاده میکنند و وضعیت جلسه را بین درخواستها حفظ نمیکنند. لاراول احراز هویت API را با استفاده از Laravel Passport آسان می کند، که در عرض چند دقیقه اجرای کامل سرور OAuth2 را برای برنامه لاراول شما فراهم می کند. پاسپورت بر روی سرور League OAuth2 ساخته شده است که توسط اندی میلینگتون و سایمون هامپ نگهداری می شود.
این مستندات فرض میکند که شما قبلاً با OAuth2 آشنا هستید. اگر چیزی در مورد OAuth2 نمی دانید، قبل از ادامه با اصطلاحات و ویژگی های کلی OAuth2 آشنا شوید.
ارتقاء پاسپورت
هنگام ارتقاء به نسخه اصلی جدید پاسپورت، مهم است که راهنمای ارتقا را به دقت مرور کنید .
نصب و راه اندازی
برای شروع، Passport را از طریق مدیریت بسته Composer نصب کنید:
composer require laravel/passport
ارائه دهنده خدمات پاسپورت دایرکتوری مهاجرت پایگاه داده خود را با فریم ورک ثبت می کند، بنابراین باید پس از نصب بسته، پایگاه داده خود را مهاجرت کنید. مهاجرت پاسپورت جداول مورد نیاز برنامه شما را برای ذخیره مشتریان و دسترسی به نشانه ها ایجاد می کند:
php artisan migrate
بعد، شما باید
passport:install
دستور را اجرا کنید. این دستور کلیدهای رمزگذاری مورد نیاز برای تولید توکن های دسترسی ایمن را ایجاد می کند. علاوه بر این، این دستور کلاینت های «دسترسی شخصی» و «اعطای رمز عبور» را ایجاد می کند که برای تولید نشانه های دسترسی استفاده می شود:
php artisan passport:install
پس از اجرای این دستور،
Laravel\Passport\HasApiTokens
ویژگی را به مدل خود اضافه کنید
App\User
. این ویژگی چند روش کمکی به مدل شما ارائه می دهد که به شما امکان می دهد توکن و محدوده کاربر تأیید شده را بررسی کنید:
<?php namespace App; use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Laravel\Passport\HasApiTokens; class User extends Authenticatable{ use HasApiTokens, Notifiable;}
در مرحله بعد، باید
Passport::routes
متد را در
boot
متد خود فراخوانی کنید
AuthServiceProvider
. این روش مسیرهای لازم برای صدور توکن های دسترسی و لغو توکن های دسترسی، کلاینت ها و نشانه های دسترسی شخصی را ثبت می کند:
<?php namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;use Illuminate\Support\Facades\Gate;use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider{ /** * The policy mappings for the application. * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes(); }}
در نهایت، در فایل پیکربندی خود
config/auth.php
، باید
driver
گزینه ی
api
authentication guard را روی
passport
. این به برنامه شما دستور می دهد تا
TokenGuard
هنگام احراز هویت درخواست های API ورودی
از Passport استفاده کند :
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ],],
سفارشی سازی مهاجرت
اگر نمیخواهید از مهاجرتهای پیشفرض Passport استفاده کنید، باید متد موجود
Passport::ignoreMigrations
در
register
متد خود را فراخوانی کنید
AppServiceProvider
. می توانید مهاجرت های پیش فرض را با استفاده از صادر کنید
php artisan vendor:publish --tag=passport-migrations
.
به طور پیش فرض، Passport از یک ستون عدد صحیح برای ذخیره سازی استفاده می کند
user_id
. اگر برنامه شما از نوع ستون متفاوتی برای شناسایی کاربران استفاده میکند (به عنوان مثال: UUID)، باید پس از انتشار آنها، مهاجرتهای پیشفرض Passport را تغییر دهید.
Frontend Quick Start
برای استفاده از اجزای Passport Vue، باید از چارچوب جاوا اسکریپت Vue استفاده کنید . این کامپوننت ها از فریم ورک Bootstrap CSS نیز استفاده می کنند. با این حال، حتی اگر از این ابزارها استفاده نمی کنید، مؤلفه ها به عنوان یک مرجع ارزشمند برای پیاده سازی frontend خودتان عمل می کنند.
پاسپورت دارای یک JSON API است که میتوانید از آن برای ایجاد مشتری و نشانههای دسترسی شخصی به کاربران خود استفاده کنید. با این حال، کدنویسی یک فرانت اند برای تعامل با این API ها می تواند زمان بر باشد. بنابراین، Passport همچنین شامل اجزای Vue از پیش ساخته شده است که میتوانید به عنوان نمونه پیادهسازی یا نقطه شروع برای پیادهسازی خود استفاده کنید.
برای انتشار اجزای Passport Vue، از
vendor:publish
دستور Artisan استفاده کنید:
php artisan vendor:publish --tag=passport-components
اجزای منتشر شده در
resources/js/components
دایرکتوری شما قرار خواهند گرفت. پس از انتشار کامپوننت ها، باید آنها را در
resources/js/app.js
فایل خود ثبت کنید:
Vue.component( 'passport-clients', require('./components/passport/Clients.vue').default); Vue.component( 'passport-authorized-clients', require('./components/passport/AuthorizedClients.vue').default); Vue.component( 'passport-personal-access-tokens', require('./components/passport/PersonalAccessTokens.vue').default);
قبل از Laravel نسخه 5.7.19، الحاق
.default
در هنگام ثبت اجزا منجر به خطای کنسول می شود. توضیحی برای این تغییر را می توان در یادداشت های انتشار Laravel Mix v4.0.0 یافت .
پس از ثبت کامپوننت ها، مطمئن شوید که
npm run dev
برای کامپایل مجدد دارایی های خود اجرا کنید. هنگامی که دارایی های خود را مجدداً کامپایل کردید، می توانید مؤلفه ها را در یکی از قالب های برنامه خود قرار دهید تا شروع به ایجاد کلاینت ها و نشانه های دسترسی شخصی کنید:
<passport-clients></passport-clients><passport-authorized-clients></passport-authorized-clients><passport-personal-access-tokens></passport-personal-access-tokens>
استقرار پاسپورت
هنگام استقرار Passport برای اولین بار در سرورهای تولیدی خود، احتمالاً باید این
passport:keys
دستور را اجرا کنید. این دستور کلیدهای رمزگذاری مورد نیاز Passport را برای تولید رمز دسترسی ایجاد می کند. کلیدهای تولید شده معمولاً در کنترل منبع نگهداری نمی شوند:
php artisan passport:keys
در صورت لزوم، میتوانید مسیری را که کلیدهای پاسپورت باید از آنجا بارگیری شوند، تعیین کنید.
Passport::loadKeysFrom
برای انجام این کار
می توانید از روش زیر استفاده کنید :
/** * Register any authentication / authorization services. * * @return void */public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::loadKeysFrom('/secret-keys/oauth');}
علاوه بر این، میتوانید فایل پیکربندی Passport را با استفاده از، منتشر کنید
php artisan vendor:publish --tag=passport-config
، که سپس گزینه بارگیری کلیدهای رمزگذاری را از متغیرهای محیطی شما ارائه میکند:
PASSPORT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----<private key here>-----END RSA PRIVATE KEY-----" PASSPORT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----<public key here>-----END PUBLIC KEY-----"
پیکربندی
طول عمر رمز
به طور پیش فرض، پاسپورت توکن های دسترسی طولانی مدت را صادر می کند که پس از یک سال منقضی می شوند. اگر میخواهید طول عمر توکن طولانیتر/کوتاهتر را پیکربندی کنید، میتوانید از روشهای
tokensExpireIn
،
refreshTokensExpireIn
و و استفاده کنید
personalAccessTokensExpireIn
. این متدها باید از
boot
متد شما
فراخوانی شوند
AuthServiceProvider
:
/** * Register any authentication / authorization services. * * @return void */public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::tokensExpireIn(now()->addDays(15)); Passport::refreshTokensExpireIn(now()->addDays(30)); Passport::personalAccessTokensExpireIn(now()->addMonths(6));}
نادیده گرفتن مدل های پیش فرض
شما می توانید مدل های استفاده شده داخلی توسط پاسپورت را گسترش دهید:
use Laravel\Passport\Client as PassportClient; class Client extends PassportClient{ // ...}
سپس، می توانید به Passport دستور دهید که از مدل های سفارشی شما از طریق
Passport
کلاس استفاده کند:
use App\Models\Passport\AuthCode;use App\Models\Passport\Client;use App\Models\Passport\PersonalAccessClient;use App\Models\Passport\Token; /** * Register any authentication / authorization services. * * @return void */public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::useTokenModel(Token::class); Passport::useClientModel(Client::class); Passport::useAuthCodeModel(AuthCode::class); Passport::usePersonalAccessClientModel(PersonalAccessClient::class);}
صدور توکن های دسترسی
استفاده از OAuth2 با کدهای مجوز، روشی است که اکثر توسعه دهندگان با OAuth2 آشنا هستند. هنگام استفاده از کدهای مجوز، یک برنامه مشتری کاربر را به سرور شما هدایت می کند، جایی که آنها درخواست صدور رمز دسترسی به مشتری را تأیید یا رد می کنند.
مدیریت مشتریان
ابتدا، توسعهدهندگانی که برنامههایی را میسازند که نیاز به تعامل با API برنامه شما دارند، باید برنامه خود را با ایجاد یک «کلینت» در اپلیکیشن شما ثبت کنند. به طور معمول، این شامل ارائه نام برنامه و یک URL است که برنامه شما می تواند پس از تأیید درخواست مجوز توسط کاربران، به آن هدایت شود.
دستور
passport:client
_
ساده ترین راه برای ایجاد مشتری استفاده از
passport:client
دستور Artisan است. این دستور ممکن است برای ایجاد کلاینت های خود برای آزمایش عملکرد OAuth2 استفاده شود. هنگامی که دستور را اجرا می کنید
client
، Passport از شما می خواهد اطلاعات بیشتری در مورد مشتری خود دریافت کنید و یک شناسه مشتری و راز را در اختیار شما قرار می دهد:
php artisan passport:client
تغییر مسیر URL ها
اگر میخواهید چندین URL تغییر مسیر را برای مشتری خود در لیست سفید قرار دهید، میتوانید آنها را با استفاده از یک لیست محدود شده با کاما مشخص کنید وقتی که با دستور از شما خواسته شد URL را انتخاب کنید
passport:client
:
http://example.com/callback,http://examplefoo.com/callback
هر URL که حاوی کاما است باید کدگذاری شود.
JSON API
از آنجایی که کاربران شما نمی توانند از این
client
دستور استفاده کنند، Passport یک API JSON ارائه می دهد که می توانید از آن برای ایجاد کلاینت استفاده کنید. این کار شما را از مشکل کدنویسی دستی کنترلرها برای ایجاد، بهروزرسانی و حذف کلاینتها نجات میدهد.
با این حال، باید API JSON Passport را با ظاهر خود جفت کنید تا داشبوردی برای کاربران خود فراهم کنید تا مشتریان خود را مدیریت کنند. در زیر، همه نقاط پایانی API را برای مدیریت مشتریان بررسی میکنیم. برای راحتی، از Axios برای نشان دادن درخواست های HTTP به نقاط پایانی استفاده می کنیم .
JSON API توسط میان افزار
web
و
auth
میان افزار محافظت می شود. بنابراین، ممکن است فقط از برنامه خود شما فراخوانی شود. امکان فراخوانی از منبع خارجی وجود ندارد.
اگر نمیخواهید کل فرانتاند مدیریت مشتری را خودتان پیادهسازی کنید، میتوانید از راهاندازی سریع frontend استفاده کنید تا در عرض چند دقیقه یک ظاهر کاملاً کاربردی داشته باشید.
GET /oauth/clients
این مسیر همه کلاینت ها را برای کاربر احراز هویت شده برمی گرداند. این در درجه اول برای فهرست کردن همه مشتریان کاربر مفید است تا آنها بتوانند آنها را ویرایش یا حذف کنند:
axios.get('/oauth/clients') .then(response => { console.log(response.data); });
POST /oauth/clients
این مسیر برای ایجاد مشتریان جدید استفاده می شود. به دو داده نیاز دارد: مشتری
name
و
redirect
URL. URL
redirect
جایی است که کاربر پس از تأیید یا رد درخواست مجوز هدایت می شود.
هنگامی که یک کلاینت ایجاد می شود، شناسه مشتری و راز مشتری برای آن صادر می شود. این مقادیر هنگام درخواست نشانه های دسترسی از برنامه شما استفاده می شود. مسیر ایجاد مشتری، نمونه مشتری جدید را برمی گرداند:
const data = { name: 'Client Name', redirect: 'http://example.com/callback'}; axios.post('/oauth/clients', data) .then(response => { console.log(response.data); }) .catch (response => { // List errors on response... });
PUT /oauth/clients/{client-id}
این مسیر برای به روز رسانی کلاینت ها استفاده می شود. به دو داده نیاز دارد: مشتری
name
و
redirect
URL. URL
redirect
جایی است که کاربر پس از تأیید یا رد درخواست مجوز هدایت می شود. مسیر نمونه مشتری به روز شده را برمی گرداند:
const data = { name: 'New Client Name', redirect: 'http://example.com/callback'}; axios.put('/oauth/clients/' + clientId, data) .then(response => { console.log(response.data); }) .catch (response => { // List errors on response... });
DELETE /oauth/clients/{client-id}
این مسیر برای حذف کلاینت ها استفاده می شود:
axios.delete('/oauth/clients/' + clientId) .then(response => { // });
درخواست توکن
تغییر مسیر برای مجوز
هنگامی که یک کلاینت ایجاد شد، توسعه دهندگان ممکن است از شناسه مشتری و راز خود برای درخواست کد مجوز و رمز دسترسی از برنامه شما استفاده کنند. ابتدا، برنامه مصرف کننده باید یک درخواست تغییر مسیر به مسیر برنامه شما
/oauth/authorize
مانند زیر ارسال کند:
Route::get('/redirect', function (Request $request) { $request->session()->put('state', $state = Str::random(40)); $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'code', 'scope' => '', 'state' => $state, ]); return redirect('http://your-app.com/oauth/authorize?'.$query);});
به یاد داشته باشید،
/oauth/authorize
مسیر قبلاً باPassport::routes
روش تعریف شده است. نیازی به تعریف دستی این مسیر ندارید.
تایید درخواست
هنگام دریافت درخواست های مجوز، پاسپورت به طور خودکار یک الگو را به کاربر نمایش می دهد که به کاربر اجازه می دهد درخواست مجوز را تأیید یا رد کند. اگر آنها درخواست را تأیید کنند، به همان چیزی که
redirect_uri
توسط برنامه مصرف کننده مشخص شده است هدایت می شوند. باید با
URL که هنگام ایجاد مشتری مشخص شده بود
redirect_uri
مطابقت داشته باشد .
redirect
اگر میخواهید صفحه تأیید مجوز را سفارشی کنید، میتوانید نماهای پاسپورت را با استفاده از
vendor:publish
دستور Artisan منتشر کنید. نماهای منتشر شده در
resources/views/vendor/passport
:
php artisan vendor:publish --tag=passport-views
گاهی اوقات ممکن است بخواهید از درخواست مجوز صرفنظر کنید، مانند زمانی که یک مشتری شخص اول را مجوز می دهید. شما می توانید این کار را با
گسترش
Client
مدل
و تعریف یک
skipsAuthorization
روش انجام دهید. در صورت
skipsAuthorization
بازگرداندن
true
مشتری تأیید می شود و کاربر
redirect_uri
بلافاصله به آدرس زیر هدایت می شود:
<?php namespace App\Models\Passport; use Laravel\Passport\Client as BaseClient; class Client extends BaseClient{ /** * Determine if the client should skip the authorization prompt. * * @return bool */ public function skipsAuthorization() { return $this->firstParty(); }}
تبدیل کدهای مجوز به توکن ها
اگر کاربر درخواست مجوز را تأیید کند، به برنامه مصرف کننده هدایت می شود. مصرف کننده ابتدا باید
state
پارامتر را در برابر مقداری که قبل از تغییر مسیر ذخیره شده بود تأیید کند. اگر پارامتر حالت مطابقت داشته باشد، مصرف کننده باید
POST
درخواستی برای درخواست توکن دسترسی به برنامه شما ارسال کند. درخواست باید شامل کد مجوزی باشد که زمانی که کاربر درخواست مجوز را تأیید کرد توسط برنامه شما صادر شده است. در این مثال، از کتابخانه HTTP Guzzle برای ارسال درخواست استفاده می کنیم
POST
:
Route::get('/callback', function (Request $request) { $state = $request->session()->pull('state'); throw_unless( strlen($state) > 0 && $state === $request->state, InvalidArgumentException::class ); $http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'authorization_code', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'redirect_uri' => 'http://example.com/callback', 'code' => $request->code, ], ]); return json_decode((string) $response->getBody(), true);});
این مسیر یک پاسخ JSON حاوی
,
و ویژگی ها
/oauth/token
را برمی گرداند
. این
ویژگی حاوی تعداد ثانیه هایی است که تا زمانی که نشانه دسترسی منقضی شود.
access_token
refresh_token
expires_in
expires_in
مانند
/oauth/authorize
مسیر،/oauth/token
مسیر نیز با روش برای شما تعریف می شودPassport::routes
. نیازی به تعریف دستی این مسیر نیست. به طور پیش فرض، این مسیر با استفاده از تنظیمات میان افزار کاهش می یابدThrottleRequests
.
نشانه های تازه کردن
اگر برنامه شما توکنهای دسترسی کوتاهمدت صادر میکند، کاربران باید توکنهای دسترسی خود را از طریق توکن تازهسازی که هنگام صدور توکن دسترسی در اختیار آنها قرار داده بود، تازهسازی کنند. در این مثال، از کتابخانه HTTP Guzzle برای بهروزرسانی توکن استفاده میکنیم:
$http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'refresh_token', 'refresh_token' => 'the-refresh-token', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'scope' => '', ],]); return json_decode((string) $response->getBody(), true);
این مسیر یک پاسخ JSON حاوی
,
و ویژگی ها
/oauth/token
را برمی گرداند
. این
ویژگی حاوی تعداد ثانیه هایی است که تا زمانی که نشانه دسترسی منقضی شود.
access_token
refresh_token
expires_in
expires_in
پاکسازی توکن ها
هنگامی که توکن ها باطل یا منقضی شدند، ممکن است بخواهید آنها را از پایگاه داده پاک کنید. پاسپورت با دستوری ارسال می شود که می تواند این کار را برای شما انجام دهد:
# Purge revoked and expired tokens and auth codes...php artisan passport:purge # Only purge revoked tokens and auth codes...php artisan passport:purge --revoked # Only purge expired tokens and auth codes...php artisan passport:purge --expired
همچنین میتوانید یک
کار زمانبندیشده را
در کلاس کنسول خود پیکربندی کنید
Kernel
تا بهطور خودکار توکنهایتان را بر اساس یک زمانبندی هرس کند:
/** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */protected function schedule(Schedule $schedule){ $schedule->command('passport:purge')->hourly();}
اعطای کد مجوز با PKCE
اعطای کد مجوز با "کلید اثبات برای تبادل کد" (PKCE) راهی امن برای احراز هویت برنامه های کاربردی تک صفحه ای یا برنامه های کاربردی بومی برای دسترسی به API شما است. این کمک هزینه زمانی باید استفاده شود که نمیتوانید تضمین کنید که راز مشتری بهطور محرمانه ذخیره میشود یا به منظور کاهش خطر رهگیری کد مجوز توسط مهاجم. ترکیبی از "تأیید کننده کد" و "چالش کد" جایگزین رمز مشتری در هنگام مبادله کد مجوز برای یک نشانه دسترسی می شود.
ایجاد مشتری
قبل از اینکه برنامه شما بتواند از طریق اعطای کد مجوز با PKCE توکن صادر کند، باید یک کلاینت با قابلیت PKCE ایجاد کنید. می توانید این کار را با استفاده از
passport:client
دستور با
--public
گزینه زیر انجام دهید:
php artisan passport:client --public
درخواست توکن
تأیید کننده کد و چالش کد
از آنجایی که این مجوز یک راز مشتری ارائه نمیکند، توسعهدهندگان باید ترکیبی از تأییدکننده کد و چالش کد را ایجاد کنند تا یک رمز را درخواست کنند.
تأیید کننده کد باید یک رشته تصادفی بین 43 تا 128 کاراکتر باشد که شامل حروف، اعداد و
،،،،
همانطور
"-"
که
در
مشخصات RFC 7636
تعریف شده است باشد .
"."
"_"
"~"
چالش کد باید یک رشته رمزگذاری شده Base64 با URL و کاراکترهای ایمن برای نام فایل باشد. کاراکترهای
انتهایی
'='
باید حذف شوند و هیچ خط شکنی، فضای خالی یا سایر کاراکترهای اضافی نباید وجود داشته باشد.
$encoded = base64_encode(hash('sha256', $code_verifier, true)); $codeChallenge = strtr(rtrim($encoded, '='), '+/', '-_');
تغییر مسیر برای مجوز
پس از ایجاد مشتری، میتوانید از شناسه مشتری و تأییدکننده کد تولید شده و چالش کد برای درخواست کد مجوز و رمز دسترسی از برنامه خود استفاده کنید. ابتدا، برنامه مصرف کننده باید یک درخواست تغییر مسیر به
/oauth/authorize
مسیر برنامه شما ارسال کند:
Route::get('/redirect', function (Request $request) { $request->session()->put('state', $state = Str::random(40)); $request->session()->put('code_verifier', $code_verifier = Str::random(128)); $codeChallenge = strtr(rtrim( base64_encode(hash('sha256', $code_verifier, true)) , '='), '+/', '-_'); $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'code', 'scope' => '', 'state' => $state, 'code_challenge' => $codeChallenge, 'code_challenge_method' => 'S256', ]); return redirect('http://your-app.com/oauth/authorize?'.$query);});
تبدیل کدهای مجوز به توکن ها
اگر کاربر درخواست مجوز را تأیید کند، به برنامه مصرف کننده هدایت می شود. مصرف کننده باید
state
پارامتر را در برابر مقداری که قبل از تغییر مسیر ذخیره شده است، تأیید کند، همانطور که در اعطای کد مجوز استاندارد وجود دارد.
اگر پارامتر حالت مطابقت داشته باشد، مصرف کننده باید
POST
درخواستی برای درخواست توکن دسترسی به برنامه شما صادر کند. این درخواست باید شامل کد مجوزی باشد که زمانی که کاربر درخواست مجوز را تأیید کرد توسط برنامه شما صادر شده است به همراه تأییدکننده کد اولیه ایجاد شده:
Route::get('/callback', function (Request $request) { $state = $request->session()->pull('state'); $codeVerifier = $request->session()->pull('code_verifier'); throw_unless( strlen($state) > 0 && $state === $request->state, InvalidArgumentException::class ); $response = (new GuzzleHttp\Client)->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'authorization_code', 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'code_verifier' => $codeVerifier, 'code' => $request->code, ], ]); return json_decode((string) $response->getBody(), true);});
رمزهای اعطای رمز عبور
اعطای رمز عبور OAuth2 به دیگر مشتریان شخص اول شما، مانند یک برنامه تلفن همراه، اجازه می دهد تا با استفاده از آدرس ایمیل / نام کاربری و رمز عبور، رمز دسترسی به دست آورند. این به شما امکان میدهد تا توکنهای دسترسی را به طور ایمن برای مشتریان شخص اول خود صادر کنید، بدون اینکه کاربران خود را ملزم به گذراندن کل جریان تغییر مسیر کد مجوز OAuth2 کنید.
ایجاد مشتری اعطای رمز عبور
قبل از اینکه برنامه شما بتواند از طریق اعطای رمز عبور توکن صادر کند، باید یک کلاینت اعطای رمز عبور ایجاد کنید. می توانید این کار را با استفاده از
passport:client
دستور با
--password
گزینه انجام دهید. اگر قبلاً دستور را اجرا کرده اید
passport:install
، نیازی به اجرای این دستور ندارید:
php artisan passport:client --password
درخواست توکن
هنگامی که یک کلاینت اعطای رمز عبور ایجاد کردید، می توانید با ارسال یک
POST
درخواست به
/oauth/token
مسیر با آدرس ایمیل و رمز عبور کاربر، یک نشانه دسترسی درخواست کنید. به یاد داشته باشید، این مسیر قبلاً توسط
Passport::routes
روش ثبت شده است، بنابراین نیازی به تعریف دستی آن نیست. اگر درخواست موفقیت آمیز باشد، پاسخ JSON را از سرور دریافت خواهید
access_token
کرد
refresh_token
:
$http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '', ],]); return json_decode((string) $response->getBody(), true);
به یاد داشته باشید که توکن های دسترسی به طور پیش فرض عمر طولانی دارند. با این حال، در صورت نیاز می توانید حداکثر طول عمر رمز دسترسی خود را پیکربندی کنید .
درخواست همه دامنه ها
هنگام استفاده از اعطای رمز عبور یا اعطای اعتبار مشتری، ممکن است بخواهید توکن را برای همه حوزههای پشتیبانی شده توسط برنامه خود تأیید کنید. شما می توانید این کار را با درخواست
*
دامنه انجام دهید. اگر دامنه را درخواست کنید
*
،
can
متد موجود در نمونه توکن همیشه برمیگردد
true
. این محدوده ممکن است فقط به یک توکن اختصاص داده شود که با استفاده از
password
یا
client_credentials
کمک مالی صادر می شود:
$response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '*', ],]);
سفارشی کردن فیلد نام کاربری
هنگام احراز هویت با استفاده از اعطای رمز عبور، Passport از
email
ویژگی مدل شما به عنوان "نام کاربری" استفاده می کند. با این حال، می توانید این رفتار را با تعریف
findForPassport
روشی در مدل خود سفارشی کنید:
<?php namespace App; use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Laravel\Passport\HasApiTokens; class User extends Authenticatable{ use HasApiTokens, Notifiable; /** * Find the user instance for the given username. * * @param string $username * @return \App\User */ public function findForPassport($username) { return $this->where('username', $username)->first(); }}
سفارشی کردن اعتبارسنجی رمز عبور
هنگام احراز هویت با استفاده از اعطای رمز عبور، Passport
password
از ویژگی مدل شما برای تأیید اعتبار رمز عبور داده شده استفاده می کند. اگر مدل شما ویژگی ندارد
password
یا میخواهید منطق اعتبارسنجی رمز عبور را سفارشی کنید، میتوانید
validateForPassportPasswordGrant
روشی را بر روی مدل خود تعریف کنید:
<?php namespace App; use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Illuminate\Support\Facades\Hash;use Laravel\Passport\HasApiTokens; class User extends Authenticatable{ use HasApiTokens, Notifiable; /** * Validate the password of the user for the Passport password grant. * * @param string $password * @return bool */ public function validateForPassportPasswordGrant($password) { return Hash::check($password, $this->password); }}
توکن های اعطای ضمنی
کمک هزینه ضمنی مشابه اعطای کد مجوز است. با این حال، توکن بدون تبادل کد مجوز به مشتری بازگردانده می شود. این کمک هزینه بیشتر برای جاوا اسکریپت یا برنامه های تلفن همراه استفاده می شود که در آنها اعتبار مشتری نمی تواند به طور ایمن ذخیره شود. برای فعال کردن کمک هزینه،
enableImplicitGrant
روش موجود در خود را فراخوانی کنید
AuthServiceProvider
:
/** * Register any authentication / authorization services. * * @return void */public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::enableImplicitGrant();}
هنگامی که کمک مالی فعال شد، توسعه دهندگان ممکن است از شناسه مشتری خود برای درخواست رمز دسترسی از برنامه شما استفاده کنند. برنامه مصرف کننده باید یک درخواست تغییر مسیر به مسیر برنامه شما
/oauth/authorize
مانند زیر ارسال کند:
Route::get('/redirect', function (Request $request) { $request->session()->put('state', $state = Str::random(40)); $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'token', 'scope' => '', 'state' => $state, ]); return redirect('http://your-app.com/oauth/authorize?'.$query);});
به یاد داشته باشید،
/oauth/authorize
مسیر قبلاً باPassport::routes
روش تعریف شده است. نیازی به تعریف دستی این مسیر ندارید.
توکن های اعطای اعتبار مشتری
اعطای اعتبار مشتری برای احراز هویت ماشین به ماشین مناسب است. برای مثال، ممکن است از این کمک هزینه در یک کار برنامه ریزی شده استفاده کنید که وظایف تعمیر و نگهداری را از طریق یک API انجام می دهد.
قبل از اینکه برنامه شما بتواند از طریق اعطای اعتبار مشتری، توکن صادر کند، باید یک مشتری اعطای اعتبار مشتری ایجاد کنید. می توانید این کار را با استفاده از
--client
گزینه
passport:client
دستور انجام دهید:
php artisan passport:client --client
در مرحله بعد، برای استفاده از این نوع کمک هزینه، باید
CheckClientCredentials
میان افزار را به
$routeMiddleware
ویژگی فایل خود اضافه کنید
app/Http/Kernel.php
:
use Laravel\Passport\Http\Middleware\CheckClientCredentials; protected $routeMiddleware = [ 'client' => CheckClientCredentials::class,];
سپس میان افزار را به یک مسیر وصل کنید:
Route::get('/orders', function (Request $request) { ...})->middleware('client');
client
برای محدود کردن دسترسی به مسیر به محدودههای خاص، میتوانید هنگام اتصال میانافزار به مسیر
، فهرستی از محدودههای مورد نیاز با کاما ارائه دهید :
Route::get('/orders', function (Request $request) { ...})->middleware('client:check-status,your-scope');
بازیابی توکن ها
برای بازیابی یک نشانه با استفاده از این نوع کمک هزینه، یک درخواست به
oauth/token
نقطه پایانی ارسال کنید:
$guzzle = new GuzzleHttp\Client; $response = $guzzle->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'client_credentials', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'scope' => 'your-scope', ],]); return json_decode((string) $response->getBody(), true)['access_token'];
توکن های دسترسی شخصی
گاهی اوقات، کاربران شما ممکن است بخواهند بدون عبور از جریان تغییر مسیر کد مجوز معمولی، توکن های دسترسی را برای خود صادر کنند. اجازه دادن به کاربران برای صدور نشانه برای خود از طریق UI برنامه شما می تواند برای اجازه دادن به کاربران برای آزمایش با API شما مفید باشد یا ممکن است به عنوان یک رویکرد ساده تر برای صدور توکن های دسترسی به طور کلی باشد.
ایجاد مشتری دسترسی شخصی
قبل از اینکه برنامه شما بتواند توکن های دسترسی شخصی صادر کند، باید یک کلاینت دسترسی شخصی ایجاد کنید. می توانید این کار را با استفاده از
passport:client
دستور با
--personal
گزینه انجام دهید. اگر قبلاً دستور را اجرا کرده اید
passport:install
، نیازی به اجرای این دستور ندارید:
php artisan passport:client --personal
اگر قبلاً یک کلاینت دسترسی شخصی تعریف کردهاید، میتوانید به Passport دستور دهید تا با استفاده از این
personalAccessClientId
روش از آن استفاده کند. به طور معمول، این متد باید از
boot
متد شما
فراخوانی شود
AuthServiceProvider
:
/** * Register any authentication / authorization services. * * @return void */public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::personalAccessClientId('client-id');}
مدیریت توکن های دسترسی شخصی
هنگامی که یک کلاینت دسترسی شخصی ایجاد کردید، می توانید با استفاده از
createToken
روش موجود در
User
نمونه مدل، توکن هایی را برای یک کاربر مشخص صادر کنید. این
createToken
متد نام نشانه را به عنوان اولین آرگومان خود و یک آرایه اختیاری از
دامنه ها
را به عنوان آرگومان دوم می پذیرد:
$user = App\User::find(1); // Creating a token without scopes...$token = $user->createToken('Token Name')->accessToken; // Creating a token with scopes...$token = $user->createToken('My Token', ['place-orders'])->accessToken;
JSON API
پاسپورت همچنین دارای یک API JSON برای مدیریت توکن های دسترسی شخصی است. میتوانید این را با ظاهر خود جفت کنید تا به کاربران خود داشبوردی برای مدیریت نشانههای دسترسی شخصی ارائه دهید. در زیر، تمام نقاط پایانی API را برای مدیریت نشانههای دسترسی شخصی بررسی میکنیم. برای راحتی، از Axios برای نشان دادن درخواست های HTTP به نقاط پایانی استفاده می کنیم .
JSON API توسط میان افزار
web
و
auth
میان افزار محافظت می شود. بنابراین، ممکن است فقط از برنامه خود شما فراخوانی شود. امکان فراخوانی از منبع خارجی وجود ندارد.
اگر نمیخواهید خودتان frontend توکن دسترسی شخصی را پیادهسازی کنید، میتوانید از frontend Quick Start استفاده کنید تا در عرض چند دقیقه یک ظاهر کاملاً کاربردی داشته باشید.
GET /oauth/scopes
این مسیر تمام محدوده های تعریف شده برای برنامه شما را برمی گرداند. میتوانید از این مسیر برای فهرست کردن دامنههایی که کاربر ممکن است به یک نشانه دسترسی شخصی اختصاص دهد استفاده کنید:
axios.get('/oauth/scopes') .then(response => { console.log(response.data); });
GET /oauth/personal-access-tokens
این مسیر تمام نشانه های دسترسی شخصی را که کاربر احراز هویت شده ایجاد کرده است، برمی گرداند. این در درجه اول برای فهرست کردن تمام نشانه های کاربر مفید است تا آنها بتوانند آنها را ویرایش یا حذف کنند:
axios.get('/oauth/personal-access-tokens') .then(response => { console.log(response.data); });
POST /oauth/personal-access-tokens
این مسیر توکن های دسترسی شخصی جدیدی ایجاد می کند. به دو قطعه داده نیاز دارد: نشانه
name
و داده ای
scopes
که باید به توکن اختصاص داده شود:
const data = { name: 'Token Name', scopes: []}; axios.post('/oauth/personal-access-tokens', data) .then(response => { console.log(response.data.accessToken); }) .catch (response => { // List errors on response... });
DELETE /oauth/personal-access-tokens/{token-id}
این مسیر ممکن است برای حذف نشانه های دسترسی شخصی استفاده شود:
axios.delete('/oauth/personal-access-tokens/' + tokenId);
حفاظت از مسیرها
از طریق Middleware
پاسپورت شامل یک
محافظ احراز هویت
است که توکن های دسترسی را در درخواست های دریافتی تأیید می کند. هنگامی که
api
محافظ را برای استفاده از درایور
پیکربندی کردید
passport
، فقط باید
auth:api
میان افزار را در مسیرهایی که به یک نشانه دسترسی معتبر نیاز دارند، مشخص کنید:
Route::get('/user', function () { //})->middleware('auth:api');
عبور از رمز دسترسی
هنگام فراخوانی مسیرهایی که توسط پاسپورت محافظت می شوند، مصرف کنندگان API برنامه شما باید توکن دسترسی خود را به عنوان یک
Bearer
توکن در
Authorization
هدر درخواست خود مشخص کنند. به عنوان مثال، هنگام استفاده از کتابخانه HTTP Guzzle:
$response = $client->request('GET', '/api/user', [ 'headers' => [ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$accessToken, ],]);
محدوده توکن
Scopes به مشتریان API شما اجازه می دهد هنگام درخواست مجوز برای دسترسی به یک حساب، مجموعه خاصی از مجوزها را درخواست کنند. به عنوان مثال، اگر در حال ساخت یک برنامه تجارت الکترونیک هستید، همه مصرف کنندگان API به توانایی سفارش دادن نیاز نخواهند داشت. درعوض، میتوانید به مصرفکنندگان اجازه دهید فقط برای دسترسی به وضعیت ارسال سفارش مجوز درخواست کنند. به عبارت دیگر، دامنه ها به کاربران برنامه شما اجازه می دهند تا اقداماتی را که یک برنامه شخص ثالث می تواند از طرف آنها انجام دهد محدود کنند.
تعریف محدوده ها
شما می توانید محدوده های API خود را با استفاده از
Passport::tokensCan
روش موجود در
boot
متد خود تعریف کنید
AuthServiceProvider
. این
tokensCan
روش مجموعهای از نامهای محدوده و توصیفهای محدوده را میپذیرد. شرح محدوده ممکن است هر چیزی باشد که شما بخواهید و در صفحه تایید مجوز برای کاربران نمایش داده می شود:
use Laravel\Passport\Passport; Passport::tokensCan([ 'place-orders' => 'Place orders', 'check-status' => 'Check order status',]);
محدوده پیش فرض
اگر یک کلاینت دامنه خاصی را درخواست نکرد، میتوانید سرور پاسپورت خود را پیکربندی کنید تا با استفاده از روش، یک محدوده پیشفرض به توکن متصل شود
setDefaultScope
. به طور معمول، شما باید این متد را از
boot
متد خود فراخوانی کنید
AuthServiceProvider
:
use Laravel\Passport\Passport; Passport::setDefaultScope([ 'check-status', 'place-orders',]);
اختصاص دامنه به توکن ها
هنگام درخواست کدهای مجوز
هنگام درخواست رمز دسترسی با استفاده از اعطای کد مجوز، مصرف کنندگان باید محدوده مورد نظر خود را به عنوان
scope
پارامتر رشته پرس و جو مشخص کنند. پارامتر
scope
باید فهرستی از محدودهها با فاصله محدود باشد:
Route::get('/redirect', function () { $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'code', 'scope' => 'place-orders check-status', ]); return redirect('http://your-app.com/oauth/authorize?'.$query);});
هنگام صدور توکن های دسترسی شخصی
اگر نشانههای دسترسی شخصی را با استفاده از روش
User
مدل صادر میکنید
createToken
، میتوانید آرایه دامنههای مورد نظر را به عنوان آرگومان دوم به متد ارسال کنید:
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
بررسی محدوده ها
پاسپورت شامل دو میانافزار است که ممکن است برای تأیید اعتبار درخواست ورودی با توکنی استفاده شود که محدوده مشخصی به آن داده شده است. برای شروع، میان افزار زیر را به
$routeMiddleware
ویژگی فایل خود اضافه کنید
app/Http/Kernel.php
:
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
همه دامنه ها را بررسی کنید
میانافزار
scopes
ممکن است به مسیری اختصاص داده شود تا تأیید کند که رمز دسترسی درخواست ورودی دارای
تمام
دامنههای فهرست شده است:
Route::get('/orders', function () { // Access token has both "check-status" and "place-orders" scopes...})->middleware(['auth:api', 'scopes:check-status,place-orders']);
برای هر محدوده بررسی کنید
میان
scope
افزار ممکن است به مسیری اختصاص داده شود تا تأیید کند که نشانه دسترسی درخواست ورودی
حداقل یکی
از حوزه های فهرست شده را دارد:
Route::get('/orders', function () { // Access token has either "check-status" or "place-orders" scope...})->middleware(['auth:api', 'scope:check-status,place-orders']);
بررسی محدوده ها در یک نمونه توکن
tokenCan
هنگامی که یک درخواست احراز هویت توکن دسترسی وارد برنامه شما شد، همچنان میتوانید با استفاده از روش موجود در
User
نمونه احراز هویت شده
، بررسی کنید که آیا توکن دارای محدوده مشخصی است :
use Illuminate\Http\Request; Route::get('/orders', function (Request $request) { if ($request->user()->tokenCan('place-orders')) { // }});
روش های دامنه اضافی
متد
scopeIds
آرایه ای از همه شناسه ها / نام های تعریف شده را برمی گرداند:
Laravel\Passport\Passport::scopeIds();
متد
scopes
آرایه ای از تمام محدوده های تعریف شده را به عنوان نمونه های زیر برمی گرداند
Laravel\Passport\Scope
:
Laravel\Passport\Passport::scopes();
این
scopesFor
روش آرایهای از
Laravel\Passport\Scope
نمونههای مطابق با شناسهها/نامهای داده شده را برمیگرداند:
Laravel\Passport\Passport::scopesFor(['place-orders', 'check-status']);
شما می توانید تعیین کنید که آیا یک محدوده معین با استفاده از روش تعریف شده است
hasScope
:
Laravel\Passport\Passport::hasScope('place-orders');
مصرف API خود با جاوا اسکریپت
هنگام ساختن یک API، این می تواند بسیار مفید باشد که بتوانید API خود را از برنامه جاوا اسکریپت خود مصرف کنید. این رویکرد برای توسعه API به برنامه کاربردی شما اجازه میدهد تا همان API را که با جهان به اشتراک میگذارید، مصرف کند. همان API ممکن است توسط برنامه های کاربردی وب، برنامه های تلفن همراه، برنامه های شخص ثالث و هر SDK که ممکن است در مدیران بسته های مختلف منتشر کنید مصرف شود.
به طور معمول، اگر می خواهید API خود را از برنامه جاوا اسکریپت خود مصرف کنید، باید به صورت دستی یک نشانه دسترسی به برنامه ارسال کنید و آن را با هر درخواست به برنامه خود ارسال کنید. با این حال، Passport شامل یک میان افزار است که می تواند این کار را برای شما انجام دهد. تنها کاری که باید انجام دهید این است که
CreateFreshApiToken
میان افزار را به
web
گروه میان افزار خود در
app/Http/Kernel.php
فایل خود اضافه کنید:
'web' => [ // Other middleware... \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,],
باید اطمینان حاصل کنید که
CreateFreshApiToken
میان افزار آخرین میان افزار لیست شده در پشته میان افزار شما باشد.
این میان افزار Passport یک
laravel_token
کوکی به پاسخ های خروجی شما متصل می کند. این کوکی حاوی یک JWT رمزگذاری شده است که پاسپورت از آن برای احراز هویت درخواست های API از برنامه جاوا اسکریپت شما استفاده می کند. اکنون، میتوانید بدون ارسال صریح نشانه دسترسی، درخواستهایی را به API برنامه خود ارسال کنید:
axios.get('/api/user') .then(response => { console.log(response.data); });
سفارشی کردن نام کوکی
در صورت نیاز، می توانید
laravel_token
نام کوکی را با استفاده از
Passport::cookie
روش سفارشی کنید. به طور معمول، این متد باید از
boot
متد شما
فراخوانی شود
AuthServiceProvider
:
/** * Register any authentication / authorization services. * * @return void */public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::cookie('custom_name');}
حفاظت CSRF
هنگام استفاده از این روش احراز هویت، باید اطمینان حاصل کنید که یک هدر توکن معتبر CSRF در درخواستهای شما گنجانده شده است. داربست پیشفرض جاوا اسکریپت لاراول شامل یک نمونه Axios است که بهطور خودکار از
XSRF-TOKEN
مقدار کوکی رمزگذاریشده برای ارسال
X-XSRF-TOKEN
هدر در درخواستهای با منبع مشابه استفاده میکند.
X-CSRF-TOKEN
اگر بجای ارسال هدر انتخاب کنیدX-XSRF-TOKEN
، باید از رمز رمزگذاری نشده ارائه شده توسط استفاده کنیدcsrf_token()
.
مناسبت ها
پاسپورت رویدادها را هنگام صدور توکن های دسترسی و رفرش توکن ها افزایش می دهد. می توانید از این رویدادها برای هرس کردن یا لغو سایر نشانه های دسترسی در پایگاه داده خود استفاده کنید. شما می توانید شنوندگان را به این رویدادها در برنامه خود پیوست کنید
EventServiceProvider
:
/** * The event listener mappings for the application. * * @var array */protected $listen = [ 'Laravel\Passport\Events\AccessTokenCreated' => [ 'App\Listeners\RevokeOldTokens', ], 'Laravel\Passport\Events\RefreshTokenCreated' => [ 'App\Listeners\PruneOldTokens', ],];
آزمایش کردن
روش پاسپورت
actingAs
ممکن است برای مشخص کردن کاربر تأیید شده فعلی و همچنین محدوده آن استفاده شود. اولین آرگومان داده شده به
actingAs
متد، نمونه کاربر است و دومی آرایه ای از دامنه است که باید به توکن کاربر اعطا شود:
use App\User;use Laravel\Passport\Passport; public function testServerCreation(){ Passport::actingAs( factory(User::class)->create(), ['create-servers'] ); $response = $this->post('/api/create-server'); $response->assertStatus(201);}
روش پاسپورت
actingAsClient
ممکن است برای مشخص کردن مشتری تأیید شده فعلی و همچنین محدوده آن استفاده شود. اولین آرگومان ارائه شده به
actingAsClient
متد، نمونه مشتری است و دومی آرایه ای از دامنه است که باید به توکن مشتری اعطا شود:
use Laravel\Passport\Client;use Laravel\Passport\Passport; public function testGetOrders(){ Passport::actingAsClient( factory(Client::class)->create(), ['check-status'] ); $response = $this->get('/api/orders'); $response->assertStatus(200);}