라라벨 Policy로 다른 사용자의 글 수정 및 삭제 차단하기

포스트 썸네일 이미지

이전 포스트까지 게시글의 수정과 삭제 로직을 구현하며 CRUD의 기능을 전부 완성했다.

하지만 남의 글도 수정하거나 삭제할 수 있는 치명적인 문제가 남아있었다.

오늘은 PostPolicy 파일을 생성해서 글의 작성자만 글을 수정하거나 삭제할 수 있도록 방어벽을 세워보겠다.




이전 포스트




전체적인 코드 수정은 이 깃허브 링크를 통해서 확인할 수 있다.




PostPolicy를 생성하는 명령어


make bash #컨테이너 안으로 들어간다.
php artisan make:policy PostPolicy --model=Post

VSCode의 터미널에서 이 명령어들을 실행한다.

그러면 app/Policies 폴더에 PostPolicy.php 파일이 생성된다.

이 파일은 특정 데이터(여기서는 Post)에 대한 사용자들의 권한 부여를 담당하는 파일이다.


--model=Post 옵션을 붙이면 라라벨 엔진이 Post 모델을 기반으로 한 CRUD(생성, 조회, 수정, 삭제) 관련 권한 검증 메서드들을 파일 내부에 자동으로 채워준다.

이 옵션을 빼면 아무런 메서드가 없는 빈 클래스 파일만 생성되므로, 생산성을 위해 반드시 이 옵션을 붙여서 생성하도록 하자.





PostController에 추가할 코드들


PostController.php의 edit와 update 메서드에 추가할 코드

Gate::authorize('update', $post);

edit 메서드와 update 메서드 내부의 가장 상단에 이 코드를 추가한다.


Gate::authorize() 메서드는 Laravel의 권한 게이트 시스템을 사용하여 사용자의 권한을 검사하는 데 사용된다.

edit와 update 메서드에 들어간 위의 코드는 update 정책 메서드가 정의된 PostPolicy 파일을 참조해서 현재의 사용자가 PostPolicy의 update 메서드에서 정의된 권한을 가지고 있는지 확인한다.

update 메서드에 이 코드를 넣으면 권한이 없는 사용자가 글의 수정 버튼을 클릭하면 403 에러가 뜨게 되고, edit 메서드에 이 코드를 넣으면 권한이 없는 사용자가 글 수정 페이지로 이동하는 것도 차단한다.




PostController.php의 destroy 메서드에 추가할 코드

Gate::authorize('delete', $post);

마찬가지로 destroy 메서드 내부의 가장 상단에 이 코드를 추가한다.

설명은 위와 같다.




use Illuminate\Support\Facades\Gate;

Gate를 임포트Import 하는 것도 잊지 말자.




브라우저에 403 에러가 떴다

여기까지 저장한 다음에 글을 수정하거나 삭제하려고 하면 이렇게 403 에러가 뜨게 된다.

남이 쓴 글뿐만 아니라 내가 쓴 글도 수정하거나 삭제할 수 없다.

왜냐하면 현재 PostPolicy의 모든 메서드가 return false; 상태이기 때문이다.





PostPolicy에서 수정과 삭제의 권한 부여


PostPolicy.php에 추가할 코드

return $user->id === $post->user_id;

update와 delete 메서드의 return false;를 삭제하고 이 코드를 넣자.

이 코드는 로그인한 유저의 ID와 글을 쓴 유저의 ID가 일치할 때만 true를 반환한다.




PostPolicy에는 update와 delete 메서드 이외에도 여러 메서드들이 있다.

각 메서드의 역할은 다음과 같다.


  • viewAny: 사용자가 전체 글 목록을 조회할 권한이 있는지 검증한다. (예: 특정 등급 회원만 목록을 보게 할 때)
  • view: 사용자가 특정 글($post)을 상세 조회할 권한이 있는지 검증한다. (예: 비밀글 기능)
  • create: 사용자가 새로운 글을 작성할 권한이 있는지 검증한다. (예: 차단된 유저의 글쓰기 금지)
  • update: 사용자가 이 특정 글을 수정할 수 있는지 검증한다.
  • delete: 사용자가 이 특정 글을 삭제할 수 있는지 검증한다.
  • restore: 사용자가 이미 삭제되어 휴지통에 가 있는 특정 게시글을 다시 원상태로 복구할 권한이 있는지 검증한다. (예: 자신이 썼다가 지운 글은 자기 자신만 복구 가능 or 관리자(Admin)만 복구 가능)
  • forceDelete: Soft Delete 되어 휴지통에 있는 글을 데이터베이스에서 완전히 지워버리는 영구 삭제 권한이 있는지 검증한다. 이 메서드를 통과하여 처리가 완료되면 데이터가 복구 불가능한 상태로 디스크에서 날아간다.


restore와 forceDelete 메서드는 Soft Delete 기능과 연관된 권한 검증 메서드다.

아직 Soft Delete에 대해서 설명한 적이 없는데, 다음에 언젠가 다룰 예정이다.




여기까지 저장하면 이제 본인이 쓴 글만 수정하거나 삭제할 수 있게 된다.





본인의 글만 드롭다운 메뉴가 보이도록 index.blade.php 수정


@canany(['update', 'delete'], $post)
<x-dropdown>
    <x-slot name="trigger">
        {{-- 생략 --}}
    </x-slot>
</x-dropdown>
@endcanany

드롭다운 메뉴 전체를 @canany(['update', 'delete'], $post)@endcanany로 감싼다.


@canany 디렉티브는 여러 권한 중 하나라도 현재 사용자에게 있으면 블레이드 블록의 내용을 렌더링 한다.

즉, update나 delete 권한 중 하나라도 사용자에게 있으면 블록이 렌더링 된다.




내가 쓴 글만 드롭다운 메뉴가 표시되고 있다

저장하고 브라우저를 확인하면, 본인의 쓴 글의 미트볼 메뉴(드롭다운 메뉴)만 표시되는 걸 볼 수 있다.




이번 포스트에서 다룬 내용 외에, 라라벨의 권한 부여에 대한 내용은 이 공식 문서를 통해 확인할 수 있다.

이 글이 도움이 됐거나 유익했다면 스크롤을 조금만 더 내려서 댓글을 남겨주세요. (비로그인도 가능합니다!)
응원이나 피드백이 담긴 댓글은 제가 계속 블로그를 해나갈 수 있는 원동력이 됩니다. 😊

지인에게 보여주고 싶은 글이었다면 URL을 복사해서 메신저나 소셜 미디어에 공유해 주세요.
이전 포스트 다음 포스트

댓글 쓰기

0 Comments

문의하기 양식