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

1. 일단 DBMS에 접속해서, TB_ADMIN 테이블에 있는 모든 항목을 삭제합니다.

mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+-------+
|  id | userid  | password  | nick  |
+-----+---------+-----------+-------+
|   1 | testid1 | passwd101 | nick1 |
|   2 | testid2 | passwd2   | nick2 |
|   3 | testid3 | passwd3   | nick3 |
+-----+---------+-----------+-------+

 
mysql> DELETE FROM TB_ADMIN;

 
mysql> CALL SP_LIST_ADMIN();
Empty SET (0.00 sec)


2. 저장프로시저(SP_INSERT_ADMIN, SP_UPDATE_ADMIN_PASSWORD)를 삭제합니다.

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


3. 저장프로시저(SP_INSERT_ADMIN, SP_UPDATE_ADMIN_PASSWORD)에 SHA256을 적용하여 다시 생성합니다.

CREATE PROCEDURE SP_INSERT_ADMIN
  (i_userid VARCHAR(255),
   i_password VARCHAR(255),
   i_nick VARCHAR(255))
BEGIN
  INSERT INTO TB_ADMIN(userid, password, nick) VALUES(i_userid, SHA2(i_password, 256), i_nick);
END


CREATE PROCEDURE SP_UPDATE_ADMIN_PASSWORD
    (i_id INT,
     i_password VARCHAR(255))
BEGIN
    UPDATE TB_ADMIN SET password = SHA2(i_password, 256) WHERE id = i_id;
END


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

mysql> CALL SP_INSERT_ADMIN('userid1', 'passwd1', 'nick1');
mysql> CALL SP_INSERT_ADMIN('userid2', 'passwd2', 'nick2');
mysql> CALL SP_INSERT_ADMIN('userid3', 'passwd3', 'nick3');


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

mysql> CALL SP_LIST_ADMIN();
+-----+---------+------------------------------------------------------------------+-------+
|  id | userid  | password                                                         | nick  |
+-----+---------+------------------------------------------------------------------+-------+
|  10 | userid1 | 3b1d7e9a7c37141350fb473fa099b8b18030cde1909f363e3758e52d4ea1a7b4 | nick1 |
|  11 | userid2 | 5a7d362627a891441ee34012b087915f03a6958c1062fe4cf01de24abecee053 | nick2 |
|  12 | userid3 | 44f1471b4598a6f5577221f7caf011743343b8b3b29c9675738cd225055563b7 | nick3 |
+-----+---------+------------------------------------------------------------------+-------+





 




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

CREATE PROCEDURE SP_DELETE_ADMIN (i_id INT)
BEGIN
    DELETE FROM TB_ADMIN WHERE id = i_id;
END


mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+---------+
| 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 |
+-----+---------+-----------+---------+

 
mysql> CALL SP_DELETE_ADMIN(9);

 
mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+---------+
| sno | userid  | password  | nick    |
+-----+---------+-----------+---------+
|   1 | testid1 | passwd101 | nick101 |
|   2 | testid2 | passwd2   | nick2   |
|   3 | testid3 | passwd3   | nick3   |
|   4 | testid4 | passwd4   | nick4   |
|   5 | testid5 | passwd5   | nick502 |
+-----+---------+-----------+---------+

 

2. src/main/resources/mybatis-mapper/AdminMapper.xml에 다음을 추가합니다.

...
    <delete id="deleteAdmin">
        CALL SP_DELETE_ADMIN(#{id})
    </delete>
...

 

3. src/main/java/com/tutorial/xyz/mapper/AdminMapper.java 파일에 다음을 추가한다. 위의 XML파일을 사용하지 않으려면, @Delete 어노테이션의 주석을 풀어주면 됩니다.

...
  // @Delete("CALL SP_DELETE_ADMIN(#{id})")
  int deleteAdmin(@Param("id") Long id);
...

 

4. src/main/java/com/tutorial/xyz/controller/mgmt/AdminController.java 파일에 다음을 추가한다. 

...
  // 관리자 삭제
  @GetMapping("/admin/delete/{id}")
  public String delete(@PathVariable("id") Long id) {
    mapper.deleteAdmin(id);
    return "redirect:/mgmt/admin";
  }
...

 

5. 이제, 관리자를 삭제해보자. 잘 되었기를 바란다.~!


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

 





1. src/main/resources/templates/mgmt/admin/update_form.html 을 작성한다.

<div class="modal-header">
  <h5 class="modal-title">관리자 수정</h5>
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
  <form name="update_form" action="/mgmt/admin/update" method="post">
    <div class="form-group">
      <label>아이디</label>
      <input type="text" name="userid" class="form-control" readonly required pattern="[a-zA-Z0-9]+" th:value="${admin.userid}"/>
      <input type="hidden" name="id" class="form-control" th:value="${admin.id}" />
    </div>
    <div class="form-group">
      <label>별명 <small>(필수)</small></label>
      <input type="text" name="nick" class="form-control" required th:value="${admin.nick}"/>
    </div>
    <div class="form-group" style="text-align: right">
      <input class="btn btn-primary" type="submit" value="관리자 수정" />
    </div>
  </form>
</div>


2. src/main/java/com/tutorial/xyz/controller/mgmt/AdminController.java 에 다음을 추가한다.

...
  // 관리자 수정 폼
  @GetMapping("/admin/update_form/{id}")
  public String updateForm(@PathVariable("id") Long id, Model model) {
    Admin admin = mapper.getAdmin(id);
    model.addAttribute("admin", admin);
    return "mgmt/admin/update_form";
  }
...


3. 이제, 수정 버튼을 클릭하면 수정할 수 있는 폼이 나타나게 될 것이다.

 

4. 이제, 실제로 수정을 처리하는 루틴을 작성하고 라우터에 등록하자. 그전에 SP_UPDATE_ADMIN 이라는 저장 프로시저부터 만들어야겠지?

CREATE PROCEDURE SP_UPDATE_ADMIN (
    i_id   INT,
    i_nick VARCHAR(255))
BEGIN
    UPDATE TB_ADMIN SET nick = i_nick WHERE id = i_id;
END


mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+-------+
|  id | userid  | password  | nick  |
+-----+---------+-----------+-------+
|   1 | testid1 | passwd101 | nick1 |
|   2 | testid2 | passwd2   | nick2 |
|   3 | testid3 | passwd3   | nick3 |
|   4 | testid4 | passwd4   | nick4 |
|   5 | testid5 | passwd5   | nick5 |
|   9 | testid6 | passwd106 | nick6 |
+-----+---------+-----------+-------+


mysql> CALL SP_UPDATE_ADMIN(1, 'nick101');

 
mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+---------+
|  id | userid  | password  | nick    |
+-----+---------+-----------+---------+
|   1 | testid1 | passwd101 | nick101 |
|   2 | testid2 | passwd2   | nick2   |
|   3 | testid3 | passwd3   | nick3   |
|   4 | testid4 | passwd4   | nick4   |
|   5 | testid5 | passwd5   | nick5   |
|   9 | testid6 | passwd106 | nick6   |
+-----+---------+-----------+---------+

 

5. src/main/resources/mybatis-mapper/AdminMapper.xml에 다음을 추가합니다.

...
    <update id="updateAdmin">
        CALL SP_UPDATE_ADMIN(#{id}, #{nick})
    </update>
...

 

6. src/main/java/com/tutorial/xyz/mapper/AdminMapper.java 파일에 다음을 추가한다. 위의 XML파일을 사용하지 않으려면, @Update 어노테이션의 주석을 풀어주면 됩니다.

...
  // @Update("CALL SP_UPDATE_ADMIN(#{id}, #{nick})")
  int updateAdmin(@Param("id") Long id, @Param("nick") String nick);
...

 

7. src/main/java/com/tutorial/xyz/controller/mgmt/AdminController.java 파일에 다음을 추가한다. 

...
  // 관리자 수정
  @PostMapping("/admin/update")
  public String update(@RequestParam("id") Long id, @RequestParam("nick") String nick) {
    mapper.updateAdmin(id, nick);
    return "redirect:/mgmt/admin";
  }
...


8. 수정 작업을 진행해보자. 에러 없이 잘 수행되었길~! *^^*


 

이번에는 관리자의 비밀번호를 변경해볼 것입니다. 이를 위해서 저장프로시저를 2개 생성할 것이고, 관련 코드들을 작성해보겠습니다. 코드들이 이전과 비슷하지만, 조금씩 다들 부분들이 있으니 주의해서 봐주세요.

그리고, 이 튜토리얼의 소스는  https://github.com/gauryan/springboot2-tutorial 에서도 확인할 수 있습니다.

1. 저장 프로시저 (SP_GET_ADMIN) 생성 (1명의 관리자 정보를 가져옴)

CREATE PROCEDURE SP_GET_ADMIN(i_id INT)
BEGIN
  SELECT id, userid, password, nick FROM TB_ADMIN WHERE id = i_id LIMIT 1;
END


mysql> CALL SP_GET_ADMIN(2);
+------+---------+----------+-------+
| id   | userid  | password | nick  |
+------+---------+----------+-------+
|    2 | testid2 | passwd2  | nick2 |
+------+---------+----------+-------+


2. src/main/resources/templates/mgmt/admin/chg_passwd_form.html 파일을 생성한다. 비밀번호 변경하기 위한 폼을 출력한다.

<div class="modal-header">
  <h5 class="modal-title">관리자 비밀번호 변경</h5>
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
  <form name="chg_passwd_form" action="/mgmt/admin/chg_passwd" method="post">
    <div class="form-group">
      <label>아이디</label>
      <input type="text" name="userid" class="form-control" readonly required value="${admin.userid}"/>
      <input type="hidden" name="id" value="${admin.id}" />
    </div>
    <div class="form-group">
      <label>비밀번호 <small>(필수)</small></label>
      <input type="password" name="passwd1" class="form-control" required />
    </div>
    <div class="form-group">
      <label>비밀번호 확인 <small>(필수)</small></label>
      <input type="password" name="passwd2" class="form-control" required />
    </div>
    <div class="form-group" style="text-align: right">
      <input class="btn btn-primary" type="submit" value="관리자 비밀번호 변경" />
    </div>
  </form>
</div>

 

3. src/main/resources/mybatis-mapper/AdminMapper.xml에 다음을 추가합니다.

...    
    <select id="getAdmin" resultType="Admin">
        CALL SP_GET_ADMIN(#{id})
    </select>
...

 

4. src/main/java/com/tutorial/xyz/mapper/AdminMapper.java 파일에 다음을 추가한다. 위츼 XML파일을 사용하지 않으려면, @Select 어노테이션의 주석을 풀어주면 됩니다.

  // @Select("SELECT id, userid, password, nick FROM TB_ADMIN WHERE id = #{id}")
  // @Select("CALL SP_GET_ADMIN(#{id})")
  Admin getAdmin(@Param("id") Long id);

 

5. src/main/java/com/tutorial/xyz/controller/mgmt/AdminController.java 파일에 다음을 추가한다. URL에 포함된 변수값(id)을 받기 위해서 @PathVariable 어노테이션을 이용하였다.

  // 관리자 비밀번호 변경 폼
  @GetMapping("/admin/chg_passwd_form/{id}")
  public String chgPasswdForm(@PathVariable("id") Long id, Model model) {
    Admin admin = mapper.getAdmin(id);
    model.addAttribute("admin", admin);
    return "mgmt/admin/chg_passwd_form";
  }

 
6. 이제, 비밀번호변경 버튼을 클릭하면 비밀번호변경을 위한 모달 다이얼로그박스가 나타날 것이다.


7. 실제로 비밀번호를 변경하는 작업을 해보자. 우선 저장 프로시저 (SP_UPDATE_ADMIN_PASSWORD) 생성하자.

CREATE PROCEDURE SP_UPDATE_ADMIN_PASSWORD (
    i_id INT,
    i_password VARCHAR(255))
BEGIN
    UPDATE TB_ADMIN SET password = i_password WHERE id = i_id;
END




mysql> CALL SP_LIST_ADMIN();
+-----+---------+----------+-------+
| sno | userid  | password | nick  |
+-----+---------+----------+-------+
|   1 | testid1 | passwd1  | nick1 |
|   2 | testid2 | passwd2  | nick2 |
|   3 | testid3 | passwd3  | nick3 |
|   4 | testid4 | passwd4  | nick4 |
|   5 | testid5 | passwd5  | nick5 |
|   9 | testid6 | passwd6  | nick6 |
+-----+---------+----------+-------+
 
mysql> CALL SP_UPDATE_ADMIN_PASSWORD (1, 'passwd101');
 
mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+-------+
| sno | userid  | password  | nick  |
+-----+---------+-----------+-------+
|   1 | testid1 | passwd101 | nick1 |
|   2 | testid2 | passwd2   | nick2 |
|   3 | testid3 | passwd3   | nick3 |
|   4 | testid4 | passwd4   | nick4 |
|   5 | testid5 | passwd5   | nick5 |
|   9 | testid6 | passwd6   | nick6 |
+-----+---------+-----------+-------+

 

8. src/main/resources/mybatis-mapper/AdminMapper.xml 파일에 다음을 추가한다. AdminMapper.java 에서 @Update 어노테이션을 사용하는 경우에는 설정하지 않아도 된다.

...
    <update id="updateAdminPassword">
        CALL SP_UPDATE_ADMIN_PASSWORD(#{id}, #{password})
    </update>
...

 

9. src/main/java/com/tutorial/xyz/mapper/AdminMapper.java 파일에 다음을 추가한다.

...
  // @Update("CALL SP_UPDATE_ADMIN_PASSWORD(#{id}, #{password})")
  int updateAdminPassword(@Param("id") Long id, @Param("password") String password);
...


10. src/main/java/com/tutorial/xyz/controller/mgmt/AdminController.java 파일에 다음을 추가한다. Form 값을 받아서 처리하는 방법이 여러가지가 있는데, 여기에서는 가장 간편한 @RequestParam 어노테이션을 이용하였다.

...
  // 관리자 비밀번호 수정
  @PostMapping("/admin/chg_passwd")
  public String chg_passwd(@RequestParam("id") Long id, @RequestParam("passwd1") String passwd1, @RequestParam("passwd2") String passwd2) {
    if(!passwd1.equals(passwd2)) {
      return "redirect:/mgmt/admin";
    }
    mapper.updateAdminPassword(id, passwd1);
    return "redirect:/mgmt/admin";
  }
...


11. 비밀번호를 변경해보고, DB의 내용이 잘 반영되었는지 확인해보자.

mysql> CALL SP_LIST_ADMIN();
+-----+---------+-----------+-------+
| sno | userid  | password  | nick  |
+-----+---------+-----------+-------+
|   1 | testid1 | passwd101 | nick1 |
|   2 | testid2 | passwd2   | nick2 |
|   3 | testid3 | passwd3   | nick3 |
|   4 | testid4 | passwd4   | nick4 |
|   5 | testid5 | passwd5   | nick5 |
|   9 | testid6 | passwd106 | nick6 |
+-----+---------+-----------+-------+



+ Recent posts