[Laravel] Authorization 구현 및 사용자별 권한 주기

[Laravel] Authorization 구현 및 사용자별 권한 주기 updated_at: 2024-08-30 11:20

Authorization

Policies

경로 app/Policies
포스트 같은 특정 콘텐츠에 대한 생성/수정/삭제 에 대한 권한을 제공

php artisan make:policy PostPolicy
<?php
namespace App\Policies;
use App\Models\Auth\User\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
  use HandlesAuthorization;
  public function __construct()
  {
      //
  }
}
<?php
namespace App\Policies;
use App\Models\Auth\User\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
  use HandlesAuthorization;
  public function __construct()
  {
    //
  }

//policy에 before가 있을 경우 가장 먼저 실행된다.
public function before($user, $ability)
{
  if ($user->isSuperAdmin()) {
    return true;
  }
}
}
php artisan make:policy PostPolicy --model=Post
<?php
namespace App\Policies;
use App\Models\Auth\User\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
  use HandlesAuthorization;
  public function view(User $user, Post $post){}
  public function create(User $user){}
  public function update(User $user, Post $post){}
  public function delete(User $user, Post $post){}
}

Registering Policies

<?php
namespace App\Providers;
use App\Post;
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
  protected $policies = [
    Post::class => PostPolicy::class,
    // Without models policies
    'backend' => BackendPolicy::class,
  ];
}

Writing Policies이전에 만든 policy를 재정의한다.

<?php

namespace App\Policies;

use App\User;
use App\Post;

class PostPolicy
{
  public function update(User $user, Post $post)
  {
    return $user->id === $post->user_id;
  }
}

action with model

if ($user->can('update', $post)) {
  //
}

action without model

use App\Post;

if ($user->can('create', Post::class)) {
  // Executes the ""create"" method on the relevant policy...
}
use Illuminate\Support\Facades\Auth;

// Get the currently authenticated user...
$user = Auth::user();

// Get the currently authenticated user's ID...
$id = Auth::id();

echo PHP_EOL.$user->id;
echo PHP_EOL.$user->email;
echo PHP_EOL.$user->password;
echo PHP_EOL.$user->remember_token;

echo PHP_EOL.$user->hasRole(""administrator"") ;"

강제 로그인

..

protected function guard()
{
  return \Auth::guard();
}
$this->guard()->login($user);

Auth (권한부여하기)

참조 : https://laravel.com/docs/10.x/authentication

php artisan make:auth

roles 테이블을 생성한다.

roles 테이블은 role 에 대한 이름을 정의한다(예, user, admin, ...)

php artisan make:migration create_roles_table --create=roles

user-roles 테이블을 생성한다.

user-roles 테이블에는 user 와 role을 맵핑한다(user_id: 1, role_id: 1)

php artisan make:migration create_users_roles_table --create=users_roles

socialite 테이블 생성

소셜로그인에 사용될때 사용하는 것이다. 이 부분은 소셜로그인 편에서 새로 다루겠습니다.

php artisan make:migration create_social_accounts_table --create=social_accounts
composer require laravel/socialite

기존 경로(App\User -> App\Models\Auth\User\User) 로 경로를 변경함에 따라 다른 곳의 경로도 변경

  • config/auth.php
'providers' => [
  'users' => [
    'driver' => 'eloquent',
    // 'model' => App\Models\User::class, //변경전
    'model' => App\Models\Auth\User\User::class, // 변경후
  ],
],

기존 Controllers/Auth 에 존재하는 파일을 수정/추가한다.

ForgotPasswordController.php
LoginController.php
RegisterController.php
ResetPasswordController.php
SocialLoginController.php  (추가 for social Login)
ConfirmController.php (추가 현재는 구현되지 않았으나 회원가입시 확인메일 발송처리단)
AppController.php (SocialLoginController 와 동일하나 앱에서 로그인 처리시 사용)

각각에 이벤트 달기

app/Providers/EventServiceProvider.php
app/Events\Auth\SocialLogin.php
app/Listeners/Auth/LoginListener.php
app/Listeners/Auth/LogoutListener.php
app/Listeners/Auth/RegisteredListener.php
app/Listeners/Auth/SocialLoginListener.php

socialite

config/services.php
.env

관리자단 구성

  1. 관리자단을 구성하기 위해서는 먼저 회원별 roll이 존재 하여야 한다. (상기 회원 구성에서 roll 참조)
  2. middleware 구성

일반적인 방법

  • Create a Midlleware
php artisan make:middleware AnyNameYouWant
public function handle($request, Closure $next)
{
  if (\Auth::user()->role == 'admin') {
    return $next($request);
  }

    return redirect('home');
}
  • Use this in Kernel

app > Http > Kernel.php 파일을 아래와 같이 admin이라는 route용 미들웨어를 추가합니다..

protected $routeMiddleware = [
  'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
  ..........
  'admin' => \App\Http\Middleware\AnyNameYouWant::class,
]
  • Protect your routes

이제는 route 파일에서 위에정의한 admin을 middleware로 처리하면 처리됩니다.

Route::get('admin/profile', function () {
//
})->middleware('admin');

route->kernel->middleware 로 단순

내가 사용하는 방법

위의 방법은 각각의 롤마다 처리해야 되는데 roll이 다양할 경우는 조금 번그로와서 아래와 같이 처리하였습니다.

Create a Midlleware

CheckRole이라는 Middleware를 만든다.
app > Http > Middleware > CheckRole.php

php artisan make:middleware CheckRole
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
  public function handle($request, Closure $next, $role)
  {
    if (!$request->user()) {
      return redirect('login');
    }
    if (!$request->user()->hasRole($role)) {
      return redirect('/');
    }
    return $next($request);
  }
}

Use this in Kernel

app > Http > Kernel.php

protected $middlewareGroups = [
  ..........
  'admin' => [  // admin을 만들어 준다.
    'role:administrator',
  ],
];
 ..........
protected $routeMiddleware = [
   ..........
  'role' => \App\Http\Middleware\CheckRole::class, // role을 기존에 만들어 두었던 CheckRole로 정의한다.
];

Protect your routes

routes.php에서 아래와 같이 정의하여 사용하면 된다.

Route::get('admin/profile', function () {
//
})->middleware('admin');

여러가지의 권한을 부여할 경우

AuthorizesRequests를 사용하여 액션별 권한을 부여

  • Create a Midlleware
php artisan make:middleware Authorize

https://laravel.com/docs/5.7/middleware 참조

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

class Authorize
{
  public function handle($request, Closure $next, $ability, $attributes = [])
  {
    $this->authorize($ability, $attributes);
    return $next($request);
  }
}

Policy 설정

php artisan make:policy AdminPolicy
<?php

namespace App\Policies;

use App\Models\Auth\User\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class AdminPolicy
{
  use HandlesAuthorization;

  public function __construct()
  {
    //
  }
}

아래와 같이 변경한다.

public function view(User $user) // , Author $author
{
  return $user->hasRoles(['administrator']);
}

AuthServiceProvider 에 등록policy를 Service Provider 에 등록 (이것 없이 바로 커널에 적용해도 됨)

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Policies\AdminPolicy;

class AuthServiceProvider extends ServiceProvider
{
  protected $policies = [
    'App\Model' => 'App\Policies\ModelPolicy',
    'admin' => AdminPolicy::class
  ];

  public function boot()
  {
    $this->registerPolicies();
  }
}

Use this in Kernel

이제 만들어진 룰을 커널에 적용해 보자

protected $middlewareGroups = [
  'admin' => [
    'auth',
    'authorize:view,admin',
  ],
]
..........

protected $routeMiddleware = [
  'authorize' => \App\Http\Middleware\Authorize::class,
];
'미들웨어 명' => [
  'routeMiddleware 에 정의된 파트',
  'outeMiddleware 에 정의된 파트:인자값1,인자값2',
],

Protect your routes.

Route::get('admin/profile', function () {
//
})->middleware('admin');

이해를 돕기위해 실제실행 되는 순서를 간략하게 설명해 드립니다.

routesRoute::get('admin/profile', function () { }) -> middleware('admin');middlewareGroup의 admin호출
kernel$middlewareGroups = [  'admin' => [ 'authorize:view,admin', ]..],
kernelprotected $routeMiddleware = [ 'authorize' => \App\Http\Middleware\Authorize::class,];App\Http\Middleware\Authorize 호출

Authorize.php
public function handle($request, Closure $next, $ability, $attributes = []){
  $this->authorize($ability, $attributes);
} //authorize에 view, admin 으로 인자값 전달
평점을 남겨주세요
평점 : 5.0
총 투표수 : 1

질문 및 답글