[PHP]Laravel-02 인증&인가

Dev_Honey·2022년 10월 25일
0

Laravel

목록 보기
2/5
post-thumbnail

Laravel 인증 & 인가

1. Athentication(인증)

어떤 사람이 누구인지 확인하고 시스템 내에서 그 사람이 활동하게 허용하는 것이다. 인증에는 로그인/로그아웃 절차와 사용자가 애플리케이션을 사용하는 동안 자신을 식별할 수 있게 하는 도구가 포함된다.

<?php
// App\Models\User

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
	use HasFactory, Notifiable;
    
    /**
    * 대량 할당 가능한 속성
    *
    * @var array
    */
    protected $fillable = [
    	'name',
        'email',
        'password',
    ];
    
    /**
    * 배열로 출력 시 제외되어야 하는 속성
    *
    * @var array
    */
    protected $hidden = [
    	'password',
        'remember_token'
    ];
    
    /**
    *	PHP 네이티브 타입으로 형변환되어야 하는 속성
    *	@var array
    */
    protected $casts = [
    	'email_verified_at' => 'datetime',
    ];
}

?>

2. auth() 글로벌 헬퍼와 Auth 퍼사드 사용하기

사용자가 로그인을 했는지 확인
로그인 했을 경우 : auth() -> check() 가 true를 반환
로그인을 안했을 경우 : auth() -> guest()는 true를 반환

#auth() 글러벌 헬퍼를 사용한 예
public function dashboard(){

	if (auth()->guest()) {
    	return redirect('sign-up')
    }
    return view('dashboard')
    	->with('user',auth()->user());
}
  • remember me 로 사용자 로그인 유지하기
    라라벨 7기준 스캐폴딩 기능은 패키지화되어 받아서 사용하면된다. 인증 스캐폴드는 인증 시스템을 아주 쉽게 준비하고 추가하도록 구현되어 있지만, 실제로 어떻게 작동하고 변경이 필요한 작업들을 어떻게 처리하는지 알아두는 게 좋다. 그중에서도 'remember me'라는 로그인 유지 기능을 어떻게 구현하는지 알아보자 !
if (auth()->attempt([
	'email' => request()->input('email'),
    'password' => request()->input('password'),
])) {
	// 로그인 성공 처리
    echo "로그인에 성공하셨습니다."
}

세션이 유지되는 동안은 로그인이 유지될 것이다. 만약, 쿠키를 사용해서 로그인 유지 기간을 무기한(사용자가 한 컴퓨터를 쓰고 로그아웃하지 않는 동안)으로 늘리고 싶으면,
auth() -> attempt() 메서드의 두 번째 파라미터에 boolean 값 true를 전달한다.

if (auth()->attempt([
	'email' => request()->input('email'),
    'password' => request()->input('password'),
], request()->filled('remember'))) {
	// 로그인 성공 처리
    echo "로그인에 성공하셨습니다."
}

이는 로그인 양식에 체크박스를 선택해서 사용자가 로그인을 계속 유지할지 결정할 수 있게 한다.
현재 사용자가 remember 토큰으로 인증한 것인지 여부를 수동으로 확인해야 할 필요가 있다면
auth()->viaRemember() 메서드를 사용!! auth()->viaRemember() 메서드는 현재 사용자가 remember 토큰을 통해 인증됐는지 여부를 true or false로 반환 해준다.

  • 비밀번호 재확인
    라우트에 password.confirm 미들웨어를 사용하여 사용자가 해당 라우트에 접근할 때 비밀번호를 추가적으로 요구할 수 있다. 추가로 비밀번호를 확인한 라우트는 세 시간 동안 비밀번호를 확인하는 과정이 비활성화된다.!!(시간 설정은 config/auth.php 설정 파일에서 password_timeout 설정을 변경한다.)
  • 수동으로 인증하기
    특수한 상황에서 사용자 강제 전환이 필요할 때 라라벨에서는 네 가지 메서드를 제공한다.
    • 명시적으로 사용자 ID를 넘기는 방식인다. 가장 직관적이면서 간단함
      auth()->loginUsingId(5);
    • 유저 객체를 전달하는 방식(Illuminate\Contracts\Auth\Authenticatable)
      auth()->login($user);
    • 세션이나 쿠키에는 영향을 주지않고 현재 요청에서만 인증시키는 방식으로 once(), onceUsingId()를 사용한다.
      auth()->once(['username' => 'mattstauffer']);
      또는
      auth()->onceUsingId(5);
      once() 메서드에 넘기는 배열에는 인증시키고자 하는 사용자를 식별하는 모든 키/값의 쌍이 들어갈 수 있다.
      auth()->once([
      	'last_name' => 'Stauffer',
        	'zip_code' => 90210,
      ])
  • 수동으로 로그아웃하기
    사용자를 수동으로 로그아웃시킬 필요가 있으면 logout()함수를 호출
    auth()->logout();
  • 다른 기기의 세션 무효화
    현재 세션 + 다른 기기에서도 로그아웃은 사용자의 비밀번호를 입력받아서 logoutOtherDevices()에 넘겨주면 된다. 이 기능을 사용하려면, AuthenticateSession 미들웨어를 app\Http\Kernel.php에 있는 web 그룹에서 주석 해제가 필요!
    #app\Http\Kernel.php
    'web' => [
    	// ...
      \Illuminate\Session\Middleware\AuthenticateSession::Class,
    ],
    그리고 나서 필요한 곳에서 다음과 같이 사용
    auth()->logoutOtherDevices($password);

3. 인증 미들웨어

protected $routeMiddleware = [
      'auth' => \App\Http\Middleware\Authenticate::class,
      'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
      'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
      'can' => \Illuminate\Auth\Middleware\Authorize::class,
      'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
      'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
      'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
      'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
      'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
  ];
  • 위의 함수를 호출하는 방식으로 모든 컨트롤러에서 호출하여 사용하는 반복을 거치면 매우 귀찮고 코드가 길어질 것이다. 그래서 라라벨에서는 이런 반복 작업을 줄이고 손쉽게 처리할 수 있는 미들웨어를 지원한다.
    App\Http\Kernel.php에서 확인 할 수 있다.
    기본 라우트 미들웨어 중 다음 5개는 인증과 관련된 것이다.
  • auth : 인증된 사용자만 접근하게 제한한다.
  • auth.basic : HTTP 기본 인증을 사용해 인증된 사용자만 접근하게 제한한다.
  • guest : 인증되지 않은 사용자만 접근하게 제한한다.
  • can : 라우트에 접근한 사용자를 인가하는 데 사용된다.
  • password.confirm : 비밀번호를 재확인한 사용자만 접근하게 제한한다.
    • 인증된 사용자 전용 구역에서는 auth를 인증된 사용자가 볼 수 없는(로그인 양식 같은 곳) 고은 guest를 사용하는 게 일반적 auth.basic은 많이 사용하지 않는다.
Route::middleware('auth')->group(function(){
	Route::get('account', 'AccountController@dashboard');
});
Route::get('login', 'Auth\LoginController@getLogin') -> middelware('guest');
  • 이메일 검증
    라라벨 7 위의 버전부터 지원되는 젯스트림 패키지, 그리고 포티파이를 사용하면 이메일 검증 기능을 사용할 수 있다. 이메일 검증 기능을 활성화하려면 config\fortify.php 파일에서 Features::emailVerification() 항목의 주석을 해제해서 기능을 활성화 해야한다.
    • 라라벨 8 미만에서의 이메일 검증
      • 이메일 검증 기능은 라라벨 5.7부터 사용 가능하다. 라라벨 7까지는 이메일 검증 기능이 별도 패키지(포티파이)로 분리되지않고, 라라벨에 내장되어 있었다. 라라벨 7까지는 이메일 검증을 활성화 하기 위해서는 라우트 파일에서 Auth::routes()에 verify 파라미터를 true로 넘겨주는 게 가장 쉬운 방법이다.
        Auth::routes(['verify => true']);
#Illuminate\Contracts\Auth\MustVerifyEmail 클래스 수정
class User extends Authenticatable implements MustVerifyEmail
{
	use Notifiable;
    // ...
}

이메일 검증이 안된 사용자가 접근하는 것을 막는 코드

Route::get('posts/create', function(){
	// 검증된 사용자에게만 코드가 실행됨...
})->middleware('verified');
  • 블레이드(VIEW)단에서 사용하는 인증 지시어
@auth
#인증된 사용자
@endauth
@guest
#인증되지 않은 사용자
@endguest
# auth와 guest 메서드 둘 다 가드를 파라미터로 넘겨서 가드를 지정할 수 있다.
@auth('trainees')
#인증된 사용자
@endauth
@guest('trainees')
#인증되지않은 사용자
@endguest

4. Guard(가드)

라라벨의 인증 시스템은 모든 부분이 가드를 통하도록 되어있다.
가드가 뭔지 예시로 알아보자
성의 출입구를 지키며 들어오려는 사람의 신원을 확인하는 경비병이 있다. 경비병의 역할은 신원이 확인되지 않은 사람이 성에 들어갈 수 없도록 막는 것이다. 영어에서는 이러한 경비병을 '가드'라고 하고 이와 마찬가지로 애플리케이션에서 사용자의 신원을 확인하여 서비스 이용을 허가하는 기능을 가드라고 부른다. 애플리케이션에서도 필요에 따라 여러 유형의 가드를 사용한다. 라라벨은 기본적으로 web 가드와 api 가드를 제공한다.
가드는 드라이버(driver)프로바이더(provider) 조합으로 이루어진다. 드라이버는 인증 상태를 어떻게 저장하고 조회할 것인지 정의한다. 프로바이더는 어떤 기준으로 사용자 정보를 가져오는지 정의한다.(예를 들어 users 테이블에서 정보를 가져오게 한다 라는 정의처럼)
web가드는 세션(session) 드라이버와 기본 사용자 프로바이더를 사용하는 전통적인 인증방식
api가드는 같은 사용자 프로바이더를 사용하지만 사용자의 요청을 인증하는 데 세션 대신 토큰(token) 드라이버를 사용한다.이름 그대로, web가드는 웹페이지 인증, api가드는 API 인증을 위한 가드이다.
사용자를 식별하고 이를 저장하는 방식을 변경(세션 대신 페이지를 로드할 때마다 제공되는 토큰과 같이) 하기 위해서는 드라이버를, 저장소 타입이나 사용자를 조회하는 방법을 변경(Mysql 대신 MongoDB로와같이)하기 위해서는 프로바이더를 바꾸면 된다.

  • 기본 가드 바꾸기
    config\auth.php 에서 가드 설정을 바꿀 수 있다.

    일반적으로 라라벨 애플리케이션은 하나의 가드를 사용하므로 자주 수정하지는 않는다.
    인증 기능을 사용할 때 별도로 가드를 지정하지 않으면 defaults 가드가 사용된다.

    auth()->user()을 사용하면 기본 가드를 통해 인증된 사용자를 가져온다. config\auth.php의 auth.defaults.guard의 설정을 바꿔서 기본 가드를 바꿀 수 있다.

    주석으로 설명이 아주 잘 되어있다.
    'defaults' => [
        'guard' => 'web',		// 여기서 기본값을 바꿀 수 있다.
        'passwords' => 'users',
    ],

코드 상에서 다른 가드를 사용하기
$apiUser = auth()->guard('api')->user();
기본 가드인 web가드가 아닌 api가드를 사용하겠다고 코드에 명시하고 있다.
새로운 가드 추가하기
config\auth.php에서 추가하면된다.

'guards' => [
	'trainees' => [
    	'driver' => 'session',
        'provider' => 'trainees',
    ]
]
# trainees라는 이름으로 새 가드를 만들었다.
#가드만드는 예시를 보면, 헬스장에 헬스 트레이너가 있다. 헬스 트레이너는 고객 관리를 위해서 어플리케이션을 만
#든다. 각 트레이너는 고객(trainee)을 보유하며 이들은 서브도메인으로 로그인한다. 그래서 헬스 트레이너와
#고객용 가드를 분리할 필요가 있다. 
#드라이버 옵션은 token과 session 둘 뿐이다. 기본적으로 주어지는 프로바이더는 
#users 테이블을 이용한 인증을 지원하는 users뿐이지만, 자체 프로바이더도 쉽게 만들 수 있다.

클로저 요청 가드
간단한 커스텀 가드를 사용하고 싶다면 클래스를 생성하는 대신 클로저에 사용자를 조회하는 코드를 넣어서 사용할 수 있다.
viaRequest() 메서드를 이용하면 클로저를 사용하여 커스텀 가드를 정의할 수 있다. 메서드의 첫 번째 파라미터에는 커스텀 가드를 식별할 이름, 두 번째 파라미터에는 동작할 코드를 전달한다. 가드는 HTTP 요청을 받아 적절한 사용자를 되돌려준다. 클로저 요청 가드는 AuthServiceProvider의 boot() 메서드에서 viaRequest()를 호출해서 등록한다.

public function boot()
{
	$this->registerPolicies();
    
    Auth::viaRequest('token-hash', function ($request){
    	return User::where('token-hash',$request->token)->first();
    });
}

커스텀 유저 프로바이더 만들기
config\auth.php 파일의 가드를 정의하는 곳 바로 아래에 사용 가능한 프로바이더를 정의하는 섹션인 auth.providers가 있다.

trainees라는 provider를 만들어 보자!

 'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Model\User::class,
        ],
        
        'trainees' => [
            'driver' => 'eloquent',
            'model' => App\Model\Trainee::class,
        ],
 ],

driver에 넣을 수 있는 값은 eloquent와 database이다. eloquent를 사용하면 model 속성이 필요하고, database를 사용하면 table 속성이 필요하다.model 속성에는 eloquent 클래스명(User 클래스로 사용할 모델)을 적고, table 속성에는 인증에 사용하는 테이블명을 적는다.
어떤 프로바이더를 쓰냐에 따라서 코드는 auth()->guard('users')와 auth()->guard('trainees')로 달라진다. auth 라우트 미들웨어는 가드명을 파라미터로 받을 수 있다!

Route::middleware('auth:trainees')->group(function(){
# Trainee 가드의 인증이 필요한 전용 라우트 그룹
 });
  • 관계형 데이터베이스를 사용하지 않는 커스텀 유저 프로바이더
    앞서 프로바이더를 만든 방법은 UserProvider 클래스에 의존적, 관계형 데이터베이스에서 식별 정보를 가져온다고 가정. 만약, 몽고DB나 Riak 같이 관계형 데이터베이스를 사용하지 않는다면, 프로바이더를 위한 클래스를 직접 만들어야 한다.
    Illuminate\Contracts\Auth\UserProvider를 구현하는 인터페이스를 만들고, AuthServiceProvider@boot에서 바인드한다.
auth() -> provider('riak', function($app, array $config){
	// Illuminate\Contracts\Auth\UserProvider 인스턴스를 반환
    return new RiakUserProvider($app['riak.connection']);
});

5. Authorization(인가)

인증된 사용자에게 특정 행동을 허용할지 말지 결정하는 것이다 예를 들어 관리자가 아닌 사람은 웹사이트의 관리자 대시보드를 볼 수 없게 제한하는 것이 있다.

라라벨 인가시스템을 예시로 들어보면,
앞서 인증시스템에서 출입구를 지키는 경비병은 가드이고, 신원 인증을 받은 방문객은 인가된 장소에만 출입할 수 있다. 이처럼 인가된 행위만 허용하고 나머지는 허용하지 않도록 하는 것을 인가 시스템이라고 한다.
라라벨에서는 인가를 Gate Facade를 사용해서 처리한다. Gate 퍼사드는 몇 가지 메서드 can, cannot, allows, denies를 사용해 사용자가 특정한 행위를 할 수 있는지 없는지 판단.
인가 기능은 Controller, Model, Middleware, Blade에서 사용된다. 간단한 코드로 알아보자.

if (Gate::denies('edit-contact', $contact)) {
	abort(403);
}

if(! Gate::allows('create-contact', Contact::class)) {
	abort(403);
}

인가 규칙 정의하기
인가 규칙을 정의하는 기본 위치는 AuthServiceProvider의 boot() 메서드이다.
인가 규칙은 ability라고 부르며, 문자열 key와 Boolean값을 반환하는 클로저로 구성된다.
코드로 보면,

class AuthServiceProvider extends ServiceProvider
{
	public function boot()
    {
    	$this->registerPolicies();
    	Gate::define('update-contact', function($user,$contact){
        	return $user -> id == $contact->user_id;
        });
    }
}

위의 ability를 정의하는 단계를 하나씩 살펴보면,

  • 첫 번째, 키를 정의한다.
    • 키를 정의할 때는 사용자에게 부여하고자 하는 인가 행위와 대상을 표현하는 문자열이 잘 어우러져야 함
  • 두 번째, 클로저를 정의한다.
    • 첫 번째 파라미터는 현재 인증된 사용자, 그 뒤로 나오는 모든 파라미터는 접근 가능 여부를 확인하고자 하는 객체 이다.

라우트를 정의할 때처럼 클로저 대신 클래스와 메서드를 사용할 수 있다.

use App\Policies\ContactACLChecker;
$gate->define('update-contact', [ContactACLChecker::class,'updateContact']);

Gate Facade & Gate Interface
잘 작동하는지 확인해보자!!
Gate Facade를 사용해 볼 것이다.

if (Gate::allows('update-contact',$contact)){
	// contact 업데이트
}
//또는
if (Gate::denies('update-contact', $contact)){
	abort(403);
}
//여러 파라미터를 갖는 ability를 정의할 수도 있다.
//정의
Gate::define('add-contact-go-group', function($user, $contact, $group){
	return $user->id == $contact->user_id && $user->id == $group->user_id;
});
// 사용
if (Gate::denies('add-contact-to-group', [$contact, $group])) {
	abort(403);
}
//현재 사용자가 아닌 다른 사용자의 인가 여부를 확인
//forUser()를 사용
if (Gate::forUser($user)->denies('create-contact')){
	abort(403);
    }

Resource Gate
인가 기능의 흔한 사용법은 리소스별로 접근 권한을 정의 하는 것
Gate Facade의 resource() 메서드는 하나의 자원에 대해 가장 일반적인 행위인 view, create, update, delete를 한번에 적용할 수 있게 해줌

use App\Policies\PhotoPolicy;
Gate::resource('photos', PhotoPolicy::class);
//resource()-> view,create,update,delete

는 다음과 같이 정의하는 것과 같다

use App\Policies\PhotoPolicy;
//
Gate::define('photos.viewAny', [PhotoPolicy::class, 'view'Any]);
Gate::define('photos.view', [PhotoPolicy::class, 'view']);
Gate::define('photos.create', [PhotoPolicy::class, 'create']);
Gate::define('photos.update', [PhotoPolicy::class, 'update']);
Gate::define('photos.delete', [PhotoPolicy::class, 'delete']);

인증 미들웨어
라우터 전체를 인가하기!! Authorize 미들웨어(별칭으로 can이라는 것을 가지고 있음)를 사용!

Route::get('people/create', function(){
	// 인물을 생성한다.
})->middleware('can:create-person');
//
Route::get('people/{person}/edit', function(){
	// 인물 수정
})->middleware('can:edit-person');

Controller 인가
App\Http\Controllers\Controller는 모든 Controller의 부모 클래스인데, AuthorizesRequests 트레이트를 사용한다. AuthorizesRequests 트레이트는 authorize(), authorizeForUser(),authorizeResource() 세 가지 메서드를 제공한다.

// 이 코드가
public function edit(Contact $contact)
{
	if (Gate::cannot('update-contact', $contact)) {
    	abort(403);
    }
    return view('contacts.edit', ['contact' => $contact]);
}
//이렇게 된다.(로직 단순화)
public function edit(Contact $contact)
{
	$this->authorize('update-contact', $contact);
    //authorize() 사용
    return view('contacts.edit', ['contact' => $contact]);
    }

authorizeForUser()도 마찬가지로 현재 인증된 사용자 대신 User 객체를 넘겨줄 수 있다.
$this->authorizeForUser($user, 'update-contact',$contact);
authorizeResource()는 컨트롤러의 생성자에서 한 번만 호출하면 RESTful 컨트롤러 메서드별로 미리 정의된 인가 규칙을 적용한다.

class ContactController extends Controller
{
		public function __construct()
    	{
    	// 이렇게 호출하면 아래 매서드 전체를 호출하는 것과 같다.
        // 개별 메서드의 authorize() 호출을 모두 제거할 수 있다.
        	$this->authorizeResource(Contact::class);
        }
        //
        public function index(){
        	$this -> authorize('viewAny', Contact::class);
        }
        public function create(){
        	$this -> authorize('create', Contact::class);
        }
        public function store(Request $request){
        	$this -> authorize('create', Contact::class);
        }
        public function show(Contact $contact){
        	$this -> authorize('view', $contact);
        }
        public function edit(Contact $contact){
        	$this -> authorize('update', $contact);
        }
        public function update(Request $request, Contact $contact){
        	$this -> authorize('update', $contact);
        }
        public function destroy(Contact $contact){
        	$this -> authorize('delete', $contact);
        }

User 인스턴스를 사용하여 권한 확인
User 클래스의 Authorizable trait에서는 세 가지 메서드를 제공
$user -> can( ), $user -> cant( ), $user ->cannot( ) 이다.

$user = User::find(1);
if ($user->can('create-contact')){
	//code
}

Authorizable 트레이트를 조금 더 들여다보면 세 메서드는 그저 Gate Facade에 파라미터를 넘겨주는 역할!! 이렇게 쓸 수 있다.
Gate::forUser($user)->check('create-contact')

트레이트(trait)
트레이트(trait)는 PHP 5.4.0 부터 지원되는 코드 재사용 방법이다.
트레이트는 PHP와 같은 단일 상속 언어에서 다중 상속의 문제점을 줄이고 장점을 얻을 수 있다. 트레이트에는 여러 클래스에서 재사용될 수 있는 메서드들을 모아둘 수 있다. 하나의 클래스는 여러 개의 트레이트를 결합할 수 있으며, 트레이트는 상호 간에 상속받을 수 있다.
트레이트는 클래스와 유사한 방법으로 생성하되, trait 키워드를 사용

trait logger 
{
   public function logmessage($message, $level = 'DEBUG')
   {
       //$message 문자열을 로그 파일에 쓴다.
    }
  }
class Storage 
{
 use logger;
 //
 function store($data) {
     //...
  $this -> logmessage($msg);
   }
}

블레이드 템플릿에서 권한 확인
blade.php에서는 @can 지시어라는 간편한 헬퍼를 제공한다.

<nav>
	<a href="/">Home</a>
    @can('edit-contact', $contact)
    	<a href="{{ route('contacts.edit', [$contact->id]) }}">Edit this Contact</a>
    @endcan
</nav>

@can 과 @endcan 사이에 @else를 사용할 수도 있고, @cannot @endcannot도 사용할 수 있다.

<h1>{{ $contact->name }}</h1>
@cannot('edit-contact', $contact)
	LOCKED
@endcannot

권한 확인 가로채기
슈퍼유저와 같은 기능을 라라벨에서 제공하는데 권한 확인을 가로채는 기능이다.
AuthServiceProvider에는 before( ) 메서드를 추가 할 수 있다.
before( )메서드는 다른 권한 확인 메서드보다 먼저 실행되는데, 여기에 등록된 로직은 다른 권한 확인 메서드를 덮어 쓰는 효과!

Gate::before(function ($user, $ability){
	if ($user->isOwner()){
    	return true;
    }
})

6. 정책

php artisan make:policy ContactPolicy
AuthServiceProvider의 $policies 속성은 생성한 정책 클래스를 등록하는 배열이다. 이 배열의 키는 접근하고자하는 리소스의 클래스명, 값은 정책 클래스명이다.

class AuthServiceProvider extends ServiceProvider
{
	protected $policies = [
    	Contact::class => ContactPolicy::class,
        //(리소스 클래스명)     (정책 클래스명)
    ];
}

update( ) 메서드의 사용

<?php
namespace APp\Policies;
//
class ContactPolicy
{
	public function update($user, $contact)
    {
    	return $user->id == $contact->user_id;
    }
}
?>

정책 확인 하기
어떤 리소스 타입에 정책의 정의되어 있으면 Gate Facade는 첫 번쨰 파라미터를 정책 클래스의 어떤 메서드를 실행할 것인지
만약, Gate::allows('update',$contact)를 실행하면 ContactPolicy@update 메서드를 이용해서 인가 여부를 확인

// Gate
if (Gate::denies('update',$contact)){
	abort(403);
}
// 명시적인 인스턴스가 없을 때
if (! Gate::check('create', Contact::class)){
	abort(403);
}
// User
if ($user->can('update',$contact)){
	// 무엇인가 수행한다.
}
//블레이드
@can('update',$contact)
// 여기 있는 내용을 보여준다.
@endcan

policy( ) helper

if (policy($contact)->update($user, $contact)){
	// 무엇인가 수행한다.
}

일반적인 ability 정의 처럼 before() 메서드로 오버라이드할 수 있다.

public function before($user, $ability)
{
	if ($user->isAdmin()) {
    	return true;
    }
}

참조

O'REILLY Laravel Up&Running 처음부터 제대로 배우는 라라벨
https://m.blog.naver.com/hongyou022/221627089422 trait

profile
자습서 같은 공부 블로그 만들기!

0개의 댓글