본 튜토리얼에서는 대부분의 사이트에 기본적으로 필요한 기능을 익히는데 목적이 있습니다. 예제에서는 관리자로 로그인/로그아웃하고, 관리자를 등록/수정/삭제 등을 할 수 있는 기본적인 기능을 포함하는 예제를 만들어봅니다. 그리고, 비밀번호의 단방향 암호화(SHA-256)를 해보는 기능도 포함됩니다. DB사용시, Laravel에서 제공하는 Model 메소드(ORM)를 사용하 않고, 직접 쿼리(스토어드 프로시저)를 사용하여 처리할 것입니다.

 

1. 라라벨 시작(설치)
2. 첫페이지 만들어보기
3. MySQL 설치와 연결
4. 관리자 목록 보여주기
5. 관리자 추가하기
6. 관리자 비밀번호 변경하기
7. 관리자 수정하기
8. 관리자 삭제하기
9. 비밀번호 단방향암호화(SHA256) 하기
10. 로그인/로그아웃 처리하기

 

 

명색이 관리자 화면인데, 아무나 들어와서 조작하면 안되겠지요? 이제는 마지막으로 로그인/로그아웃 처리를 해보겠습니다. 로그인/로그아웃은 세션을 이용해서 구현합니다.

 

1. 로그인 화면을 구성합니다. xyz/resources/views/mgmt/index.blade.php 을 작성합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
 
<div class="container" style="margin-top: 20px">
  <form action="/mgmt/login" method="post" class="form-horizontal" style="margin: 0 auto; max-width: 360px;">
    @csrf
    <div class="form-group">
      <label for="userid" class="col-sm-3 control-label">아이디</label>
      <div class="col-sm-9">
        <input type="text" id="userid" name="userid" class="form-control" placeholder="당신의 ID를 입력하세요..." required autofocus>
      </div>
    </div>
    <div class="form-group">
      <label for="passwd" class="col-sm-3 control-label">비밀번호</label>
      <div class="col-sm-9">
        <input type="password" id="passwd" name="passwd" class="form-control" placeholder="비밀번호를 입력하세요..." required>
      </div>
    </div>
    <input type="submit" class="btn btn-primary btn-block" value="로그인" />
  </form>
</div>
 
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>

 

2. xyz/app/Http/Controllers/Mgmt/Main.php 를 생성합니다.

<?php
 
namespace App\Http\Controllers\Mgmt;
 
use App\Http\Controllers\Controller;
 
class Main extends Controller
{
    public function index()
    {
        return view('mgmt.index');
    }
}

 

3. xyz/routes/web.php 다음을 추가합니다.

...
use App\Http\Controllers\Mgmt\Main as MgmtMain;
...
  Route::get('/', [MgmtMain::class, 'index']);
...

 

4. http://xyz.test.com/mgmt 에 접속하면 로그인화면이 나올 것입니다.

 

5. MySQL Function 작성할 수 있도록 설정 변경

$ sudo mysql -u root
mysql> SET GLOBAL log_bin_trust_function_creators = 1;
mysql> exit
$

 

6. MySQL에서 isMember Function 생성

$ mysql -u xyz -pxyz123 xyz
DELIMITER $$
CREATE FUNCTION isMember (
  i_userid VARCHAR(255),
  i_password VARCHAR(255)
) RETURNS INT
BEGIN
  DECLARE CNT INT;
 
  SELECT COUNT(*) INTO CNT FROM admins 
  WHERE userid = i_userid AND password = SHA2(i_password, 256);
   
  RETURN CNT;
END $$
DELIMITER ;

현재 Admin 목록 확인

mysql> CALL listAdmins();
+-----+---------+------------------------------------------------------------------+-------+
| sno | userid  | password                                                         | nick  |
+-----+---------+------------------------------------------------------------------+-------+
|  10 | userid1 | 3b1d7e9a7c37141350fb473fa099b8b18030cde1909f363e3758e52d4ea1a7b4 | nick1 |
|  11 | userid2 | 5a7d362627a891441ee34012b087915f03a6958c1062fe4cf01de24abecee053 | nick2 |
|  12 | userid3 | 44f1471b4598a6f5577221f7caf011743343b8b3b29c9675738cd225055563b7 | nick3 |
|  13 | userid4 | 34344e4d60c2b6d639b7bd22e18f2b0b91bc34bf0ac5f9952744435093cfb4e6 | nick4 |
+-----+---------+------------------------------------------------------------------+-------+

isMember Function 테스트

mysql> SELECT isMember('userid1', 'passwd1');
+--------------------------------+
| isMember('userid1', 'passwd1') |
+--------------------------------+
|                              1 |
+--------------------------------+
1 ROW IN SET (0.00 sec)
 
mysql> SELECT isMember('userid1', 'password2');
+----------------------------------+
| isMember('userid1', 'password2') |
+----------------------------------+
|                                0 |
+----------------------------------+
1 ROW IN SET (0.00 sec)
 
mysql>

 

7. xyz/app/Http/Controllers/Mgmt/Main.php 에 다음을 추가한다.

...
 
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
 
...
 
    // 로그인
    public function login (Request $request) {
        $userid = $request->input('userid');
        $passwd = $request->input('passwd');
 
        $result = collect(DB::select('SELECT isMember(?, ?) as is_member', [$userid, $passwd]))->first();
 
        if ($result->is_member == 1) {
            $request->session()->put('mgmt-login', true);
            return redirect('/mgmt/admin');
        }
        return redirect('/mgmt');
    }
 
 
...

 

8. xyz/routes/web.php 에 다음을 추가한다.

...
 
    Route::post('/login', [MgmtMain::class, 'login']);
 
...

 

9. xyz/resources/views/mgmt/admin$/index.blade.php 에 다음을 적당한 곳에 추가한다.

...
 
<a href="/mgmt/logout">[로그아웃]</a>
 
...

 

10. xyz/app/Http/Controllers/Mgmt/Main.php 에 다음을 추가한다.

...
 
    // 로그아웃
    public function logout (Request $request) {
        $request->session()->forget('mgmt-login');
        return redirect('/mgmt');
    }
 
 
...

 

11. xyz/routes/web.php 에 다음을 추가한다.

...
 
    Route::get('/logout', [MgmtMain::class, 'logout']);
 
...

이제, 로그인도 해보고, 로그아웃도 해보세요. ^^

 

12. AuthMgmt 미들웨어를 생성한다.

$ cd xyz
$ php artisan make:middleware AuthMgmt
Middleware created successfully.
$

 

13. xyz/app/Http/Middleware/AuthMgmt.php 내용은 아래와 같이 작성한다.

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
 
class AuthMgmt
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $mgmt_login = $request->session()->get('mgmt-login');
        if ($mgmt_login != true) {
              return redirect('/mgmt');
        }
        return $next($request);
    }
}

 

14. xyz/app/Http/Kernel.php 에 AuthMgmt 를 등록한다.

...
 
    protected $routeMiddleware = [
...
        'auth.mgmt' => \App\Http\Middleware\AuthMgmt::class,
...
    ];
 
...

 

15. xyz/routes/web.php 파일을 아래처럼 수정한다.

<?php
 
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Main;
use App\Http\Controllers\Mgmt\Main as MgmtMain;
use App\Http\Controllers\Mgmt\Admin;
 
Route::get('/', [Main::class, 'index']);
 
Route::prefix('mgmt')->group(function () {
    Route::get('/', [MgmtMain::class, 'index']);
    Route::post('/login', [MgmtMain::class, 'login']);
    Route::get('/logout', [MgmtMain::class, 'logout']);
});
 
Route::prefix('mgmt')->middleware('auth.mgmt')->group(function () {
    Route::get('admin', [Admin::class, 'index']);
    Route::get('admin/insert_form', [Admin::class, 'insert_form']);
    Route::post('admin/insert', [Admin::class, 'insert']);
    Route::get('admin/chg_passwd_form/{id}', [Admin::class, 'chg_passwd_form']);
    Route::post('admin/chg_passwd', [Admin::class, 'chg_passwd']);
    Route::get('admin/update_form/{id}', [Admin::class, 'update_form']);
    Route::post('admin/update', [Admin::class, 'update']);
    Route::get('admin/delete/{id}', [Admin::class, 'delete']);
});

 

16. 여기까지 작성하면, 로그인해야만 http://xyz.test.com/mgmt/admin 을 접근할 수 있게 된다.

정보통신망법, 개인정보보호법 등에 의하면 비밀번호는 단방향암호화(SHA256 등), 개인정보는 양방향암호화(AES256 등)를 하도록 되어 있습니다. 지금까지 작성한 예제는 이런 법에 맞지 않아서 서비스할 수 없겠네요. 여기에서는 비밀번호의 단방향 암호화를 구현해보도록 하겠습니다. SHA256을 적용하겠습니다. PHP(Laravel)에서는 아무런 작업을 하지 않고, DB(MySQL)에서만 작업을 하겠습니다.

 

1. 일단 DBMS에 접속해봅니다.

$ mysql -u xyz -pxyz123 xyz
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 282
Server version: 8.0.26-0ubuntu0.20.04.2 (Ubuntu)
 
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
 
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
mysql>

 

2. Admins 테이블에 있는 모든 항목을 삭제합니다.

mysql> CALL listAdmins();
+-----+---------+-----------+-------+
| sno | userid  | password  | nick  |
+-----+---------+-----------+-------+
|   1 | testid1 | passwd101 | nick1 |
|   2 | testid2 | passwd2   | nick2 |
|   3 | testid3 | passwd3   | nick3 |
+-----+---------+-----------+-------+
3 ROWS IN SET (0.00 sec)
 
Query OK, 0 ROWS affected (0.00 sec)
 
mysql> DELETE FROM admins;
Query OK, 3 ROWS affected (0.01 sec)
 
mysql> CALL listAdmins();
Empty SET (0.00 sec)
 
Query OK, 0 ROWS affected (0.00 sec)

 

3. 저장프로시저(insertAdminupdateAdminPassword)를 삭제합니다.

mysql> DROP PROCEDURE insertAdmin;
Query OK, 0 ROWS affected (0.00 sec)
 
mysql> DROP PROCEDURE updateAdminPassword;
Query OK, 0 ROWS affected (0.01 sec)

 

4. 저장프로시저(insertAdminupdateAdminPassword)에 SHA256을 적용하여 다시 생성합니다.

DELIMITER $$
CREATE PROCEDURE insertAdmin
  (i_userid VARCHAR(255),
   i_password VARCHAR(255),
   i_nick VARCHAR(255))
BEGIN
  INSERT INTO admins(userid, password, nick) VALUES(i_userid, SHA2(i_password, 256), i_nick);
END $$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE updateAdminPassword
    (i_sno INT,
     i_password VARCHAR(255))
BEGIN
    UPDATE admins SET password = SHA2(i_password, 256) WHERE sno = i_sno;
END $$
DELIMITER ;

 

5. 관리자 3명을 추가해봅니다.

mysql> CALL insertAdmin('userid1', 'passwd1', 'nick1');
Query OK, 1 row affected (0.00 sec)

mysql> CALL insertAdmin('userid2', 'passwd2', 'nick2');
Query OK, 1 row affected (0.01 sec)

mysql> CALL insertAdmin('userid3', 'passwd3', 'nick3');
Query OK, 1 row affected (0.00 sec)

 

6. 관리자 목록을 조회해보면… 비밀번호가 제대로 암호화되었다는 것을 확인할 수 있습니다.

mysql> CALL listAdmins();
+-----+---------+------------------------------------------------------------------+-------+
| sno | userid  | password                                                         | nick  |
+-----+---------+------------------------------------------------------------------+-------+
|  10 | userid1 | 3b1d7e9a7c37141350fb473fa099b8b18030cde1909f363e3758e52d4ea1a7b4 | nick1 |
|  11 | userid2 | 5a7d362627a891441ee34012b087915f03a6958c1062fe4cf01de24abecee053 | nick2 |
|  12 | userid3 | 44f1471b4598a6f5577221f7caf011743343b8b3b29c9675738cd225055563b7 | nick3 |
+-----+---------+------------------------------------------------------------------+-------+
3 rows in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> exit

 

1. 관리자 삭제를 위한 저장 프로시저(deleteAdmin)을 만들어봅시다.

$ mysql -u xyz -pxyz123 xyz
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 271
Server version: 8.0.26-0ubuntu0.20.04.2 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
DELIMITER $$
CREATE PROCEDURE deleteAdmin (i_sno INT)
BEGIN
    DELETE FROM admins WHERE sno = i_sno;
END $$
DELIMITER ;
mysql> CALL listAdmins();
+-----+---------+-----------+---------+
| sno | userid  | password  | nick    |
+-----+---------+-----------+---------+
|   1 | testid1 | passwd101 | nick101 |
|   2 | testid2 | passwd2   | nick2   |
|   3 | testid3 | passwd3   | nick3   |
|   4 | testid4 | passwd4   | nick4   |
|   5 | testid5 | passwd5   | nick502 |
|   9 | testid6 | passwd106 | nick601 |
+-----+---------+-----------+---------+
6 ROWS IN SET (0.00 sec)
 
Query OK, 0 ROWS affected (0.00 sec)
 
mysql> CALL deleteAdmin(9);
Query OK, 1 ROW affected (0.01 sec)
 
mysql> CALL listAdmins();
+-----+---------+-----------+---------+
| sno | userid  | password  | nick    |
+-----+---------+-----------+---------+
|   1 | testid1 | passwd101 | nick101 |
|   2 | testid2 | passwd2   | nick2   |
|   3 | testid3 | passwd3   | nick3   |
|   4 | testid4 | passwd4   | nick4   |
|   5 | testid5 | passwd5   | nick502 |
+-----+---------+-----------+---------+
5 ROWS IN SET (0.00 sec)
 
Query OK, 0 ROWS affected (0.00 sec)
 
mysql> exit

 

2. xyz/app/Http/Controllers/Mgmt/Admin.php 에 다음을 추가한다.

...
 
    // 관리자 삭제
    // /mgmt/admin/delete/{id}
    public function delete ($id) {
        DB::delete('CALL deleteAdmin(?)', [$id]);
        return redirect('/mgmt/admin');
    }
 
...

 

3. xyz/routes/web.php 에 다음을 추가하고, 관리자 삭제를 해봅니다.

    Route::get('admin/delete/{id}', [Admin::class, 'delete']);

 

4. 여기까지 하면, 기본적인 CRUD 기능을 모두 작성할 수 있게 됩니다. *^^*

+ Recent posts