최신판 |
당신의 편집 |
55번째 줄: |
55번째 줄: |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
|
| ===액션 인가=== | | ===액션 인가=== |
| 게이트를 사용하여 액션를 승인하려면, <code>Gate</code> 파사드가 제공하는 <code>allows</code> 또는 <code>denies</code> 메소드를 사용해야 합니다. 현재 인증된 사용자를 이 메소드에 전달할 필요는 없습니다. Laravel이 게이트 클로저로 사용자를 자동으로 전달하기 때문입니다. 인가가 필요한 액션을 수행하기 전에 애플리케이션의 컨트롤러에서 게이트 인가 메소드를 호출하는 것이 일반적입니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| <?php
| |
| | |
| namespace App\Http\Controllers;
| |
| | |
| use App\Http\Controllers\Controller;
| |
| use App\Models\Post;
| |
| use Illuminate\Http\RedirectResponse;
| |
| use Illuminate\Http\Request;
| |
| use Illuminate\Support\Facades\Gate;
| |
| | |
| class PostController extends Controller
| |
| {
| |
| /**
| |
| * 주어진 포스트를 업데이트합니다.
| |
| */
| |
| public function update(Request $request, Post $post): RedirectResponse
| |
| {
| |
| if (! Gate::allows('update-post', $post)) {
| |
| abort(403);
| |
| }
| |
| | |
| // 포스트를 업데이트합니다...
| |
| | |
| return redirect('/posts');
| |
| }
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| 현재 인증된 사용자 외에 다른 사용자가 액션을 수행할 수 있는지 확인하려면 <code>Gate</code> 파사드의 <code>forUser</code> 메소드를 사용할 수 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| if (Gate::forUser($user)->allows('update-post', $post)) {
| |
| // 사용자가 포스트를 업데이트할 수 있습니다...
| |
| }
| |
| | |
| if (Gate::forUser($user)->denies('update-post', $post)) {
| |
| // 사용자가 포스트를 업데이트할 수 없습니다...
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| 한 번에 여러 액션을 인가하려면 <code>any</code> 또는 <code>none</code> 메소드를 사용할 수 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| if (Gate::any(['update-post', 'delete-post'], $post)) {
| |
| // 사용자가 포스트를 업데이트하거나 삭제할 수 있습니다...
| |
| }
| |
| | |
| if (Gate::none(['update-post', 'delete-post'], $post)) {
| |
| // 사용자가 포스트를 업데이트하거나 삭제할 수 없습니다...
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| ;예외를 던지며 인가
| |
| 액션을 인가하려 시도하고 사용자가 주어진 행위를 수행할 수 없는 경우 <code>Illuminate\Auth\Access\AuthorizationException</code>을 자동으로 던지려면 <code>Gate</code> 퍼사드의 <code>authorize</code> 메소드를 사용할 수 있습니다. <code>AuthorizationException</code> 인스턴스는 Laravel에 의해 자동으로 403 HTTP 응답으로 변환됩니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| Gate::authorize('update-post', $post);
| |
| | |
| // 액션이 인가되었습니다...
| |
| </syntaxhighlight>
| |
| | |
| ;추가 컨텍스트 제공
| |
| 인가 기능을 위한 게이트 메소드(<code>allow</code>, <code>deny</code>, <code>check</code>, <code>any</code>, <code>none</code>, <code>authorize</code>, <code>can</code>, <code>cannot</code>)와 인가 [[#Blade 템플릿을 통해|Blade 지시문]](<code>@can</code>, <code>@cannot</code>, <code>@canany</code>)은 두 번째 인수로 배열을 받을 수 있습니다. 이 배열 요소는 게이트 클로저에 매개변수로 전달되며, 인가 결정을 내릴 때 추가 컨텍스트로 사용할 수 있습니다:
| |
| | |
| <syntaxhighlight lang='php'>
| |
| use App\Models\Category;
| |
| use App\Models\User;
| |
| use Illuminate\Support\Facades\Gate;
| |
| | |
| Gate::define('create-post', function (User $user, Category $category, bool $pinned) {
| |
| if (! $user->canPublishToGroup($category->group)) {
| |
| return false;
| |
| } elseif ($pinned && ! $user->canPinPosts()) {
| |
| return false;
| |
| }
| |
| | |
| return true;
| |
| });
| |
| | |
| if (Gate::check('create-post', [$category, $pinned])) {
| |
| // 사용자가 포스트를 생성할 수 있습니다...
| |
| }
| |
| </syntaxhighlight>
| |
| | |
| ===게이트 응답=== | | ===게이트 응답=== |
| 지금까지는, 단순한 불리언 값을 반환하는 게이트만 살펴보았습니다. 하지만 때로는 오류 메시지를 포함한 더 자세한 응답을 반환하고 싶을 때가 있습니다. 이를 위해 게이트에서 <code>Illuminate\Auth\Access\Response</code>를 반환할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
| use Illuminate\Auth\Access\Response;
| |
| use Illuminate\Support\Facades\Gate;
| |
|
| |
| Gate::define('edit-settings', function (User $user) {
| |
| return $user->isAdmin
| |
| ? Response::allow()
| |
| : Response::deny('You must be an administrator.');
| |
| });
| |
| </syntaxhighlight>
| |
|
| |
| 게이트에서 인가 응답을 반환할 때에도 <code>Gate::allows</code> 메소드는 여전히 단순한 불리언 값을 반환하지만, <code>Gate::inspect</code> 메소드를 사용하여 게이트에서 반환된 전체 인가 응답을 얻을 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| $response = Gate::inspect('edit-settings');
| |
|
| |
| if ($response->allowed()) {
| |
| // 액션이 허가되었습니다...
| |
| } else {
| |
| echo $response->message();
| |
| }
| |
| </syntaxhighlight>
| |
|
| |
| 게이트에서 인가되지 않은 액션에 대해 <code>AuthorizationException</code>을 던지는 <code>Gate::authorize</code> 메소드를 사용할 때, 인가 응답에서 제공한 오류 메시지는 HTTP 응답으로 전달됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| Gate::authorize('edit-settings');
| |
|
| |
| // 액션이 인가되었습니다...
| |
| </syntaxhighlight>
| |
|
| |
| ;HTTP 응답 상태 커스터마이징
| |
| 게이트를 통해 액션이 거부될 때 403 HTTP 응답이 반환되지만, 때로는 대체 HTTP 상태 코드를 반환하는 것이 유용할 수 있습니다. 실패한 인가 확인에 대한 HTTP 상태 코드를 커스터마이징하려면 <code>Illuminate\Auth\Access\Response</code> 클래스의 <code>denyWithStatus</code> 정적 생성자를 사용할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
| use Illuminate\Auth\Access\Response;
| |
| use Illuminate\Support\Facades\Gate;
| |
|
| |
| Gate::define('edit-settings', function (User $user) {
| |
| return $user->isAdmin
| |
| ? Response::allow()
| |
| : Response::denyWithStatus(404);
| |
| });
| |
| </syntaxhighlight>
| |
|
| |
| 리소스를 404 응답으로 숨기는 것은 웹 애플리케이션에서 매우 흔한 패턴이기 때문에, 이를 위한 편리한 메소드인 <code>denyAsNotFound</code>가 제공됩니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
| use Illuminate\Auth\Access\Response;
| |
| use Illuminate\Support\Facades\Gate;
| |
|
| |
| Gate::define('edit-settings', function (User $user) {
| |
| return $user->isAdmin
| |
| ? Response::allow()
| |
| : Response::denyAsNotFound();
| |
| });
| |
| </syntaxhighlight>
| |
|
| |
| ===게이트 체크 가로채기=== | | ===게이트 체크 가로채기=== |
| 때로는 특정 사용자에게 모든 권한을 부여하고자 할 때가 있습니다. <code>before</code> 메소드를 사용하여 다른 모든 권한 검사 전에 실행되는 클로저를 정의할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
| use Illuminate\Support\Facades\Gate;
| |
|
| |
| Gate::before(function (User $user, string $ability) {
| |
| if ($user->isAdministrator()) {
| |
| return true;
| |
| }
| |
| });
| |
| </syntaxhighlight>
| |
|
| |
| <code>before</code> 클로저가 null이 아닌 결과를 반환하면, 그 결과가 권한 검사 결과로 간주됩니다.
| |
|
| |
| <code>after</code> 메소드를 사용하여 다른 모든 권한 검사 후에 실행되는 클로저를 정의할 수도 있습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
|
| |
| Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
| |
| if ($user->isAdministrator()) {
| |
| return true;
| |
| }
| |
| });
| |
| </syntaxhighlight>
| |
|
| |
| <code>before</code> 메소드와 마찬가지로, <code>after</code> 클로저가 null이 아닌 결과를 반환하면, 그 결과가 권한 검사 결과로 간주됩니다.
| |
|
| |
| ===인라인 인가=== | | ===인라인 인가=== |
| 때로는, 특정 작업에 해당하는 전용 게이트를 작성하지 않고 현재 인증된 사용자가 주어진 작업을 수행할 권한이 있는지 확인하고 싶을 때가 있습니다. Laravel은 <code>Gate::allowIf</code>와 <code>Gate::denyIf</code> 메소드를 통해 이러한 유형의 "인라인" 인가를 수행할 수 있습니다. 인라인 인가는 정의된 [[#게이트 체크 가로채기|"before" 또는 "after" 인가 훅]]을 실행하지 않습니다:
| |
|
| |
| <syntaxhighlight lang='php'>
| |
| use App\Models\User;
| |
| use Illuminate\Support\Facades\Gate;
| |
|
| |
| Gate::allowIf(fn (User $user) => $user->isAdministrator());
| |
|
| |
| Gate::denyIf(fn (User $user) => $user->banned());
| |
| </syntaxhighlight>
| |
|
| |
| 작업이 인가되지 않았거나 현재 인증된 사용자가 없는 경우, Laravel은 자동으로 <code>Illuminate\Auth\Access\AuthorizationException</code> 예외를 던집니다. <code>AuthorizationException</code> 인스턴스는 Laravel의 예외 처리기에 의해 자동으로 403 HTTP 응답으로 변환됩니다.
| |
|
| |
| ==정책 생성== | | ==정책 생성== |
| ===정책 생성하기=== | | ===정책 생성하기=== |
| 정책은 특정 모델이나 리소스와 관련된 인가 로직을 구성하는 클래스입니다. 예를 들어, 애플리케이션이 블로그라면, <code>App\Models\Post</code> 모델과 해당 모델에 대한 사용자 액션(예: 게시물 작성 또는 업데이트)을 승인하는 <code>App\Policies\PostPolicy</code>가 있을 수 있습니다.
| |
|
| |
| <code>make:policy</code> Artisan 명령어를 사용하여 정책을 생성할 수 있습니다. 생성된 정책은 <code>app/Policies</code> 디렉토리에 배치됩니다. 이 디렉토리가 없으면 Laravel이 생성합니다:
| |
|
| |
| <syntaxhighlight lang='bash'>
| |
| php artisan make:policy PostPolicy
| |
| </syntaxhighlight>
| |
|
| |
| <code>make:policy</code> 명령어는 빈 정책 클래스를 생성합니다. 리소스 보기, 작성, 업데이트, 삭제와 관련된 예제 정책 메소드가 포함된 클래스를 생성하려면 명령을 실행할 때 <code>--model</code> 옵션을 제공할 수 있습니다:
| |
|
| |
| <syntaxhighlight lang='bash'>
| |
| php artisan make:policy PostPolicy --model=Post
| |
| </syntaxhighlight>
| |
|
| |
| ===정책 등록하기=== | | ===정책 등록하기=== |
| ;정책 발견 | | ;정책 발견 |