이전 포스팅에서 데이터를 가져왔으니, 로그인을 구현해보자.
Basic Auth
라라벨에서 제공하는 회원가입, 로그인, 비밀번호 찾기 기능을 사용하고 싶다면 artisan 명령어로 간단하게 시작할 수 있다.
명령어를 실행하면 resources/views/auth 폴더에 뷰가 app/Http/Controllers/Auth에 로직이 생성되고 routes/web.php에 라우팅이 등록된다.
DB도 같이 만들고 싶다면 Docs를 따라하자.
다른 테이블 사용
제공된 user 테이블을 안 쓰려면 커스터마이징이 필요하다.
설정 변경
config/auth.php 파일로 이동해 다른 모델을 등록하자.
config/auth.php
<?php
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\Member::class,
]
]
config 안의 파일을 변경하면 config:clear를 실행해 혹시 모를 캐시를 날려주자
그리고 app/Models/Member.php로 이동해 내 모델을 라라벨 기본 인증 모듈을 사용할 수 있게 추가해야한다.
app/Models/Member.php
<?
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Member extends Authenticatable {
use Notifiable;
protected $guarded = [
'member_id', 'remember_token'
];
protected $hidden = [
'password', 'remember_token',
];
}
인증 필드 변경
Basic Auth는 기본 필드를 email로 잡고 있기 때문에 id 필드를 사용하게 변경해야한다.
app/Http/Controllers/Auth/LoginController.php
<?php
public function username() {
return 'id';
}
회원가입 후 자동로그인
회원가입이 성공하면 세션을 생성해줘야한다.
app/Http/Controllers/Auth/RegisterController.php
<?php
protected function registered(Request $request, $user) {
Auth::attempt([
'id' => $request->input('id'),
'password' => $request->input('password')
]);
return response(null, 204);
}
ajax 처리
로그인
로그인을 ajax로 처리해야될 경우 커스터마이징이 필요하다.
app/Http/Controllers/Auth/LoginController.php
<?php
protected function authenticated(Request $request, $user) {
if ($request->ajax()) {
return response()->json([
'href' => url()->previous()
]);
} else {
return abort(405);
}
}
비밀번호 찾기
비밀번호 찾기를 ajax로 처리해야될 경우 커스터마이징이 필요하다.
app/Http/Controllers/Auth/ForgotPasswordController.php
<?php
public function sendResetLinkEmail(Request $request) {
$this->validateId($request);
$data = Member::where('id', $request->only('id'))
->first(['email']);
$email = isset($data->email) ? $data->email : null;
$response = $this->broker()->sendResetLink([
'email' => $email
]);
return response()->json([
'email' => $email
], $response == Password::RESET_LINK_SENT ? 200 : 500 );
}
routing 예외
ajax 요청으로 바꿨다면 굳이 필요없는 기본 route는 등록할 필요가 없다. (예를 들면 로그인 페이지)
먼저 routes/web.php에서 Auth::routes();
를 지워주고 라라벨 route 파일을 열어보자.
vendor/laravel/Illuminate/Routing/Router.php
public function auth()
{
$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController@login');
$this->post('logout', 'Auth\LoginController@logout')->name('logout');
$this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
$this->post('register', 'Auth\RegisterController@register');
$this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
$this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
$this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
$this->post('password/reset', 'Auth\ResetPasswordController@reset');
}
입맛에 맞게 web.php로 가져와 사용하자.
notification 예외
Noticifation은 사용자에게 빠르게 알림을 보낼 수 있는 기능이지만, 정해져 있는 템플릿을 사용하므로 커스터마이징이 되게 힘들다.
비밀번호 찾기시에 보낼 메일을 정해진 템플릿을 사용할 수 없다면 메소드를 수정하자.
app/Models/Member.php
<?php
public function sendPasswordResetNotification($token) {
Mail::to($this->email)->send(new PasswordReset($token));
}
Auth
Basic Auth를 사용하는데 건드려야 되는 곳이 많으므로 Auth 모듈만 사용하는게 정신건강에 좋다고 본다.
(Bootstrap 기반의 Laravel에 딱 맞는 모양을 입은 프로젝트라면 기본 인증이 좋겠지만)
로그인
먼저 사용할 모델에 Authenticatable 클래스를 상속 받자
그리고 LoginController에서 Auth::attempt() 메소드를 실행하면 끝이다.
app/Http/Controllers/LoginController.php
public function login(Request $request) {
$password = $request->password;
if(Auth::attempt([ 'id' => $request->id, 'password' => $password ])){
return response(null, 200);
}else{
return abort(401);
}
}
not bcrypt
Auth 모듈은 기본으로 bcrypt를 사용해 비밀번호를 암호화하고 비교하는데 다른 암호화 방식을 사용해야하는 경우가 있다.
bcrypt를 사용하지 않게 처리해보자.
app/Models/Member.php
public function getAuthPassword() {
return Hash::make($this->password);
}
이제 Auth::attempt() 메소드에 패스워드를 넘길 때 암호화를 해주고 넘기면 된다.
N개의 세션
관리자와 회원은 같은 세션을 사용하면 안 된다. 세션을 분기해보자.
모델 생성
먼저 모델을 하나 만들고 Authenticatable 클래스를 상속받는다.
app/Models/Admin.php
<?php
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable {
}
설정 추가
만든 모델을 Laravel Auth에서 사용한다고 등록을 해줘야한다.
config/auth.php
<?php
return [
'guards' => [
...
'admin' => [
'driver' => 'session',
'provider' => 'admin'
]
],
'providers' => [
...
'admin' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class
]
],
];
passowrds 속성은 제공되는 password_resets 기능을 사용할 경우에만 추가해주면 된다.
미들웨어
관리자 세션이 인증된 사람만 관리자 페이지에 접근할 수 있어야한다.
php artisan make:middleware Admin 명령어를 실행해 Admin Middleware를 만들자.
app/Http/Middleware/Admin.php
<?php
use Auth;
use Closure;
class Admin {
public function handle($request, Closure $next) {
if (Auth::guard('admin')->check()) {
return $next($request);
}
return redirect()->route('admin.login');
}
}
그리고 Http Kernel에 방금 만든 Admin Middleware를 라우팅에서 사용할 수 있게 등록해준다.
app/Http/Kernel.php
<?php
...
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'admin' => \App\Http\Middleware\Admin::class,
];
새로운 라우팅 파일로 관리하기 위해 RouteServiceProvider에 설정을 추가한다.
app/Providers/RouteServiceProvider.php
<?php
...
public function map() {
...
$this->mapAdminRoutes();
}
protected function mapAdminRoutes() {
Route::prefix('admin')
->middleware('web')
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
}
마지막으로 라우팅 파일에 미들웨어를 넣어준다.
routes/admin.php
<?php
Route::group(['middleware' => 'admin', 'as' => 'admin.'], function() {
Route::get('/', 'AdminController@index')->name('main');
});
기존 Auth 메소드들에 guard만 추가해주면 쉽게 사용 가능하다.
<?php
Auth::guard('admin')->attepmt();
Auth::guard('admin')->check();
Auth::guard('admin')->user();
Auth::guard('admin')->logout();
로그아웃
Auth::logout() 메소드를 호출하면 된다.
세션 아이디
라라벨에선 로그인을 할 때 세션아이디를 새로운 값으로 엎어쳐버린다.
따라서 같은 환경에서 접근했는데, 로그인을 하면 다른 사용자가 되는 경우가 생긴다.
(로그아웃시에는 그대로다.)
<?php
$old_session_id = Session::getId();
소셜 로그인
laravel/socialite
패키지를 설치하고 아주 쉽게 연동이 가능하다.