로그인을 만들기 전에 다시 게시판 목록 파일을 좀 보자.
/resources/views/boards/index.blade.php
@extends('boards.layout')
@section('header')
<div class="d-flex flex-column flex-md-row align-items-center pb-3 mb-4 border-bottom">
<span class="fs-4">게시판 목록</span>
<nav class="d-inline-flex mt-2 mt-md-0 ms-md-auto">
@guest()
<a href="{{route('auth.login')}}" class="text-xl">로그인</a> /
<a href="{{route('auth.signup')}}" class="text-xl">회원가입</a>
@endguest
@auth()
<form action="/logout" method="post" class="inline-block">
@csrf
<span class="text-xl text-blue-500">{{auth()->user()->userid}}</span> /
<a href="/logout"><button class="text-xl">로그아웃</button></a>
</form>
@endauth
</nav>
</div>
@endsection
@section('content')
<div style="text-align:right;">
<button class="text-xl">등록</button></a>
</div>
<table class="table table-striped table-hover">
<colgroup>
<col width="10%"/>
<col width="15%"/>
<col width="45%"/>
<col width="15%"/>
<col width="15%"/>
</colgroup>
<thead>
<tr>
<th scope="col">번호</th>
<th scope="col">이름</th>
<th scope="col">제목</th>
<th scope="col">조회수</th>
<th scope="col">등록일</th>
</tr>
</thead>
<tbody>
<?php
$pagenumber = $_GET["page"]??1;
$idx = $boards->total()-(($boards->currentPage()-1) * 20);
?>
@foreach ($boards as $board)
<tr>
<th scope="row">{{ $idx-- }}</th>
<td>{{ $board->userid }}</td>
<td><a href="/boards/show/{{$board->bid}}/{{$pagenumber}}">{{ $board->subject }}</a></td>
<td>{{ number_format($board->cnt) }}</td>
<td>{{ date("Y-m-d",strtotime($board->regdate)) }}</td>
</tr>
@endforeach
</tbody>
</table>
<div>
{!! $boards->withQueryString()->links() !!}
</dvi>
@endsection
기존거와 조금 달라졌다. 기존 소스를 위에걸로 바꾸도록 하자.
상단에 보면
@guest()
<a href="{{route('auth.login')}}" class="text-xl">로그인</a> /
<a href="{{route('auth.signup')}}" class="text-xl">회원가입</a>
@endguest
@auth()
<form action="/logout" method="post" class="inline-block">
@csrf
<span class="text-xl text-blue-500">{{auth()->user()->userid}}</span> /
<a href="/logout"><button class="text-xl">로그아웃</button></a>
</form>
@endauth
이 부분이 로그인과 비로그인의 차이를 보여준다. guest()가 비로그인이고 auth()가 로그인이 된 상태다. 즉 로그인이라는건 auth()에 값을 넣는 다고 보면 된다.
로그인 페이지를 만들어보자. 라우터와 콘트롤러는 이미 만들어 놓았다.
/resources/views/member/login.blade.php
@extends('boards.layout')
@section('content')
<style>
html,
body {
height: 100%;
}
body {
display: flex;
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
max-width: 330px;
padding: 15px;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
.b-example-divider {
height: 3rem;
background-color: rgba(0, 0, 0, .1);
border: solid rgba(0, 0, 0, .15);
border-width: 1px 0;
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
}
.b-example-vr {
flex-shrink: 0;
width: 1.5rem;
height: 100vh;
}
.bi {
vertical-align: -.125em;
fill: currentColor;
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: flex;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
</style>
<main class="form-signin w-100 m-auto">
<form method="post" action="/loginok">
@csrf
<div style="text-align:center;">
<img class="mb-4" src="/images/bootstrap-logo.svg" alt="" width="72" height="57">
<h1 class="h3 mb-3 fw-normal">로그인 페이지</h1>
</div>
<div class="form-floating">
<input type="email" name="email" class="form-control" id="floatingInput" placeholder="name@example.com">
<label for="floatingInput">아이디(이메일)</label>
</div>
<div class="form-floating">
<input type="password" name="passwd" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">암호</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="1" name="remember"> Remember me
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">로그인</button>
</form>
</main>
@if(Session::has('loginFail'))
<script type="text/javascript" >
alert("{{ session()->get('loginFail') }}");
</script>
@endif
@endsection
회원가입과는 다르게 ajax로 안하고 그냥 submit으로 해보려고 한다.
맨 아래에 보면 loginFail 에 값이 없으면 알럿창을 띄우도록 해 놓았다. 콘트롤러에서 로그인을 처리할때 아이디나 암호가 틀리면 loginFail에 값을 넣어서 다시 로그인 페이지로 넘어가게 처리할 것이다.
그럼 로그인을 처리할 콘트롤러를 만들자. 우선 라우터부터.
/routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BoardController;
use App\Http\Controllers\MemberController;
Route::get('/', function () {
return view('welcome');
});
//게시판
Route::get('/boards', [BoardController::class, 'index'])->name('boards.index');
Route::get('/boards/show/{id}/{page}', [BoardController::class, 'show'])->name('boards.show');
//회원
Route::get('/login', [MemberController::class, 'login'])->name('auth.login');
Route::get('/signup', [MemberController::class, 'signup'])->name('auth.signup');
Route::post('/signupok', [MemberController::class, 'signupok'])->name('auth.signupok');
Route::post('/emailcheck', [MemberController::class, 'emailcheck'])->name('auth.emailcheck');
Route::post('/loginok', [MemberController::class, 'loginok']) -> name('auth.loginok');
/app/Http/Controllers/MemberController.php
public function loginok(Request $request){
$email = $request->email;
$passwd = $request->passwd;
$passwd = hash('sha512',$passwd);
$remember = $request->remember;
$loginInfo = array(
'email' => $email,
'passwd' => $passwd
);
$ismember = Members::where($loginInfo)->first();
if($ismember){
Auth::login($ismember, $remember);
return redirect() -> route('boards.index');
}else{
return redirect() -> route('auth.login')->with('loginFail', '아이디나 비밀번호가 틀렸습니다.');
}
}
해당 부분만 보도록 하자. 기존 MemberController.php에 추가하면 된다. 로그인을 실패하면 loginFail에 값을 줘서 다시 로그인 페이지로 가도록 해주었다.
분명 일반적인 라라벨 로그인과는 다르다. 기존에 있던 members 테이블을 이용하기때문에 조금 다르게 해주어야 한다.
그리고 아래 링크를 참조해서 추가적인 작업을 해주어야 한다.
https://programmerdaddy.tistory.com/401
이렇게 해주어야지만 라라벨이 지정하지 않은 members 테이블로 로그인을 할 수 있다. 아래에 수정한 소스도 올려 놓겠다.
/config/auth.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\Members::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
| The throttle setting is the number of seconds a user must wait before
| generating more password reset tokens. This prevents the user from
| quickly generating a very large amount of password reset tokens.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_reset_tokens',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
이 파일에서 Members 모델을 등록해 준다.
/app/Models/Members.php
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Model;
class Members extends Authenticatable
{
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'members';
/**
* The primary key for the model.
*
* @var string
*/
protected $primaryKey = 'mid';
/**
* Attributes that should be mass-assignable.
*
* @var array
*/
protected $fillable = [
'email', 'passwd', 'regdate', 'userid', 'username','remember_token'
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts = [
'mid' => 'int', 'email' => 'string', 'passwd' => 'string', 'regdate' => 'datetime', 'userid' => 'string', 'username' => 'string'
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = [
'regdate'
];
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = false;
// Scopes...
// Functions ...
// Relations ...
}
Members 모델도 위와 같이 변경한다.
이제 로그인페이지에서 로그인을 해보자.
http://localhost:8000/login
회원가입 페이지에서 등록한 아이디와 로그인을 가지고 로그인을 해보자.
이렇게 로그아웃 버튼이 나오면 성공이다.
로그아웃 버튼을 누르면 로그아웃이 되도록 해보자.
/routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BoardController;
use App\Http\Controllers\MemberController;
Route::get('/', function () {
return view('welcome');
});
//게시판
Route::get('/boards', [BoardController::class, 'index'])->name('boards.index');
Route::get('/boards/show/{id}/{page}', [BoardController::class, 'show'])->name('boards.show');
//회원
Route::get('/login', [MemberController::class, 'login'])->name('auth.login');
Route::get('/signup', [MemberController::class, 'signup'])->name('auth.signup');
Route::post('/signupok', [MemberController::class, 'signupok'])->name('auth.signupok');
Route::post('/emailcheck', [MemberController::class, 'emailcheck'])->name('auth.emailcheck');
Route::post('/loginok', [MemberController::class, 'loginok']) -> name('auth.loginok');
Route::post('/logout', [MemberController::class, 'logout']) -> name('auth.logout');
/app/Http/Controllers/MemberController.php
public function logout(){
auth() -> logout();
return redirect() -> route('boards.index');
}
로그아웃은 간단하다.