Laravel 5.5 - 로그인(Auth) 붙히기
이전 포스팅에서 데이터를 가져왔으니, 로그인을 구현해보자.
Basic Auth
라라벨에서 제공하는 회원가입, 로그인, 비밀번호 찾기 기능을 사용하고 싶다면 artisan 명령어로 간단하게 시작할 수 있다.
php artisan make:auth
명령어를 실행하면 resources/views/auth 폴더에 뷰가 app/Http/Controllers/Auth에 로직이 생성되고 routes/web.php에 라우팅이 등록된다. DB도 같이 만들고 싶다면 Docs를 따 라하자.
다른 테이블 사용
제공된 user 테이블을 안 쓰려면 커스터마이징이 필요하다.
설정 변경
config/auth.php 파일로 이동해 다른 모델을 등록하자.
<?php
'providers' => [
'users' => [
'driver' => 'eloquent',
// 여기에 사용할 모델을 등록한다.
'model' => App\Models\Member::class,
]
]
config 안의 파일을 변경하면 config:clear를 실행해 혹시 모를 캐시를 날려주자
그리고 app/Models/Member.php로 이동해 내 모델을 라라벨 기본 인증 모듈을 사용할 수 있게 추가해야한다.
<?
// 라라벨 인증 사용
use Illuminate\Foundation\Auth\User as Authenticatable;
// 비밀번호 변경 메일을 위해 필요한 trait
use Illuminate\Notifications\Notifiable;
// Authenticatable 를 상속받는다.
class Member extends Authenticatable {
// Notifiable trait를 추가한다.
use Notifiable;
protected $guarded = [
'member_id', 'remember_token'
];
protected $hidden = [
'password', 'remember_token',
];
}
인증 필드 변경
Basic Auth는 기본 필드를 email로 잡고 있기 때문에 id 필드를 사용하게 변경해야한다.
<?php
// username 메소드를 추가
public function username() {
// 반환할 필드를 선언한다.
return 'id';
}
회원가입 후 자동로그인
회원가입이 성공하면 세션을 생성해줘야한다.
<?php
// registered 메소드를 Override
protected function registered(Request $request, $user) {
// 세션 생성
Auth::attempt([
'id' => $request->input('id'),
'password' => $request->input('password')
]);
return response(null, 204);
}
ajax 처리
로그인
로그인을 ajax로 처리해야될 경우 커스터마이징이 필요하다.
<?php
// authenticated 메소드를 Override
protected function authenticated(Request $request, $user) {
// 인증이 된 경우 페이지 전환이 아닌 전환될 페이지를 json으로 반환한다.
if ($request->ajax()) {
return response()->json([
'href' => url()->previous()
]);
} else {
return abort(405);
}
}
비밀번호 찾기
비밀번호 찾기를 ajax로 처리해야될 경우 커스터마이징이 필요하다.
<?php
public function sendResetLinkEmail(Request $request) {
$this->validateId($request);
// email이 아닌 아이디로 검색을 해 메일을 찾고 싶다면
$data = Member::where('id', $request->only('id'))
->first(['email']);
$email = isset($data->email) ? $data->email : null;
// 여기서 email이 User Model(Member Model)에 바인딩된다.
// 아래의 sendPasswordResetNotification 메소드에서 $this->email 값이다.
$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 파일을 열어보자.
// 994 라인
public function auth()
{
// Authentication Routes...
$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController@login');
$this->post('logout', 'Auth\LoginController@logout')->name('logout');
// Registration Routes...
$this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
$this->post('register', 'Auth\RegisterController@register');
// Password Reset Routes...
$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은 사용자에게 빠르게 알림을 보낼 수 있는 기능이지만, 정해져 있는 템플릿을 사용하므로 커스터마이징이 되게 힘들다. 비밀번호 찾기시에 보낼 메일을 정해진 템플릿을 사용할 수 없다면 메소드를 수정하자.
<?php
// 이 메소드를 override해야한다.
// 첫 파라미터는 비밀번호 인증용 token이 들어온다.
public function sendPasswordResetNotification($token) {
Mail::to($this->email)->send(new PasswordReset($token));
}
Auth
Basic Auth를 사용하는데 건드려야 되는 곳이 많으므로 Auth 모듈만 사용하는게 정신건강에 좋다고 본다. (Bootstrap 기반의 Laravel에 딱 맞는 모양을 입은 프로젝트라면 기본 인증이 좋겠지만)
로그인
먼저 사용할 모델에 Authenticatable 클래스를 상속 받자 그리고 LoginController에서 Auth::attempt() 메소드를 실행하면 끝이다.
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를 사용하지 않게 처리해보자.
// 이 메소드를 override 해야한다.
public function getAuthPassword() {
// bcrypt 비교를 하지 않기 위해 강제로 해시를 생성한다.
return Hash::make($this->password);
}
이제 Auth::attempt() 메소드에 패스워드를 넘길 때 암호화를 해주고 넘기면 된다.