lumen 에서 Authorization 과 Authentication
lumen 에서 Authorization 과 Authentication 을 고려할 때 다음 2가지만 만들어 주면 될 듯 하다. 아직 제대로 파악하지 못한 부분이 있어 틀린 부분이 있을 수 있다.
- AuthServiceProvider::boot() 에서는 Authorization, Authentication 과 관련된 설정을 해준다.
- Authorization : 어떤 권한에 대한 정의, 예를 들면 'posting 할 수 있는 권한' 은 어떤 조건이 만족해야 하는지. 아래 source codes 에서 Gate::define() 으로 이것을 만들게 된다.
- Authentication : 이건 이 사람이 누군인지를 인증하기 위해 어떻게 해라라고 만들어주면 된다. 그래서 인증이 된 사람이면, User 를 return 해주고, 그렇지 않으면 null 을 return 해주면 된다.
- App/Http/Middleware/Authenticate.php 에서 어떤 회원일때(guest 등) 어떤 Unauthorized 를 줄 것인지 정해서 code 를 작성하면 된다. 이것을 적용해서 어떤 controller 의 동작은 Login 한 유저만 접근하게 하고 싶다. 등은 Controller::__construct() 에서 이 controller 는 middleware 'auth' 를 호출한다 라고 정해주면 된다.
- Controller 에서 이제 "어떤 권한(authorized)" 을 가진 녀석이 이 일을 하고, 어떤 권한은 이 동작을 못하게 하는 등의 작업을 해주면 된다. Gate::allow, Gate::deny 등으로 할 수 있다.
bootstrap/app.php
$app->withFacades();
...
$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class,
]);
...
$app->register(App\Providers\AuthServiceProvider::class);
App\Providers\AuthServiceProvider.php
namespace App\Providers; use App\User; use Illuminate\Support\Facades\Gate; use Illuminate\Support\ServiceProvider; class AuthServiceProvider extends ServiceProvider { ... /** * Boot the authentication services for the application. * * @return void */ public function boot() { // $this->registerPolicies(); Gate::define('retrieve-new', function ($user, $request) { return true; // anybody }); // Here you may define how you wish users to be authenticated for your Lumen // application. The callback which receives the incoming request instance // should return either a User instance or null. You're free to obtain // the User instance via an API token or any other method necessary. $this->app['auth']->viaRequest('api', function ($request) { // 'api' is the key for customCreators of the AuthManager // and the callback function which must return a User instance or null // because the RequestGuard save the return value of callback function // to the $this->$user variable. // Thus, this function can be used for authorization. // // This callback should have check routine whether the this request // is authorized and if so, retrieving the User data $header = $request->header('Api-Token'); if($header && $header == 'birds fly'){ if ($header) { return User::where('api_token', $header)->first(); } return new User(); } return null; }); } }
App/Http/Middleware/Authenticate.php
class Authenticate
{
...
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($this->auth->guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}
}
App/Http/Controller/NewEventController.php
namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Gate; use Illuminate\Http\Request; use App\G5Member; class NewEventController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth', ['only'=>[ 'authenticate' ]]); } public function authenticate(Request $request) { if (Gate::allows('retrieve-new', $request)) { $this->validate($request, [ 'email' => 'required', 'password' => 'required' ]); // check whether the User exists // ... if(is_null($isUser)){ // a id/pw pair does not exist return response()->json(['status' => 'fail'],401); } // if exists // generate the temporary apiKey and use only for this session $apikey = base64_encode(str_random(40)); User::where('mb_id', $request->input('email'))->update(['api_key' => "$apikey"]);; return response()->json(['status' => 'success','api_key' => $apikey]); } } }
- Gate::forUser(Auth::user())->allows(...
- Gate::allows(... : current user 에 적용할때
Policy
policy 는 Guard 의 설정을 모아놓은 class 라 봐도 될 듯 하다. 주로 Model 이랑 관련해서 만들기는 하지만 꼭 Model::class 에 적용할 필요는 없다.laravel 에서는 AuthServiceProvider::boot() 에서 $this->registerPolicies(); 를 호출해서 policy 들을 적용한다. 그런데 lumen 에서는 그렇지 않다..
// laravel source class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ Post::class => PostPolicy::class, ]; public function boot() { $this->registerPolicies(); // } }
lumen 에서는 아래처럼 적용하면 된다.
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::policy(Post::class, PostPolicy::class);
//
}
}
laravel 에서는 아래 command 를 사용해서 Policy class 를 만들 수 있다. 하지만 lumen 에서는 안된다.
php artisan make:policy PostPolicy
policy class 의 작성법은 Authorization - Laravel를 참고하자.
Policy 사용예
<?php namespace App\Policies; use App\User; use App\Product; class ProductPolicy { public function before(User $user, $ability) { if ($user->id == 'admin') { return true; } } /** * Determine if the given post can be updated by the user. * * @param \App\User $user * @param \App\Post $post * @return bool */ public function duplicate(User $user) { return $user->id == 'admin'; } }
class AuthServiceProvider extends ServiceProvider { public function boot() { Gate::policy(Product::class, ProductPolicy::class); // } }
// ProductHandleController.php public function duplicate(Request $request){ $this->validate($request, [ 'prod_id' => 'bail|integer|exists:product,id', ]); $user = Auth::user(); if ($user->can('duplicate', Product::class)) { ... } }
$user->can('duplicate', Product::class) 을 실행하면, Product::class 의 등록된 policy 를 찾고, 거기서 duplicate 가 있는지 찾게 된다.
댓글 없음:
댓글 쓰기