--
- nurigo sdk ์์ ์ ๊ณตํ๋ SMS API ์๋น์ค๋ฅผ ์ด์ฉํด ๋ณธ์ธ์ธ์ฆ์ ๊ตฌํํ๊ธฐ๋ก ํ์๋ค.
-> SMS ๋ฌธ์ ์ธ์ฆ ํฌ์คํ- ์๋๋ PortOne์์ ์ ๊ณตํ๋ PASS ๋ฅผ ํตํด์ ๋ณธ์ธ์ธ์ฆ์ ํ๋ ค๊ณ ํ์ผ๋, ์ฌ์ ์ ๋ฑ๋ก์ฆ์ด ํ์ํด์ ์คํจ..
- ์์ด๋ ์ฐพ๊ธฐ๋ ์ด๋ฆ, ํด๋ํฐ ๋ฒํธ๋ฅผ ๊ฐ์ ํ ํ์์ ๋ณด์ ๋ง๊ฒ ๋ณด๋ด๊ณ ,
- ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์ ์์ด๋, ํด๋ํฐ ๋ฒํธ๋ฅผ ๊ฐ์ ํ ํ์์ ๋ณด์ ๋ง๊ฒ ๋ณด๋ด๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์๋ค.
- Redis๋ฅผ ํตํด ์ผ์ ๊ธฐ๊ฐ๋ง ์ ํจํ ๊ฐ์ ๋ง๋ค๊ณ ์ถ์์ง๋ง, ๊ฐ๋จํ๊ฒ SMS ํ ์ด๋ธ์ ๋ง๋ค์ด์ ๊ตฌํํ์๋ค.
- ์์ด๋ ์ฐพ๊ธฐ, ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์์ฒญ์ ๋ฐ๋ฅธ ์ธ์ฆ๋ฒํธ ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ ํ ์ด๋ธ์ด๋ค.
- Status ๊ฐ - "I : ์์ด๋ ์ฐพ๊ธฐ", "P : ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ", "S : ํ์๊ฐ์ ์ ์ธ์ฆ"
- ์ ํจํ ์ธ์ฆ๋ฒํธ๋ ํญ์ ํด๋น ์ ํ๋ฒํธ, ์ด๋ฆ/์์ด๋๋ก ๋ค์ด์จ ์์ฒญ์ ๋ํด์ 3๋ถ ์ด๋ด ์์ฑ๋ ์ธ์ฆ๋ฒํธ ์ค ๊ฐ์ฅ ์ต๊ทผ ๊ฐ์ ์ด์ฉํด ์ธ์ฆ์ ๊ตฌํํ์๋ค.
(1) ๋ก์ง ํ๋ก์ฐ
1. ์์ด๋ ์ฐพ๊ธฐ : ์ด๋ฆ, ํธ๋ํฐ ๋ฒํธ๋ฅผ Body์ ๋ด์ POST๋ก ๋ณด๋
2. ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ : ์์ด๋, ํธ๋ํฐ ๋ฒํธ๋ฅผ Body์ ๋ด์ POST๋ก ๋ณด๋
3. ์์ด๋ ์ฐพ๊ธฐ, ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ์ธ์ง ํ๋๊ฐ์ ํ์ธํ์ฌ ํ๋ณ.
4. ์ฌ๋ฐ๋ฅธ ํ์์ธ์ง ์๋ณ
5. ๋๋ค ์ธ์ฆ๋ฒํธ ์์ฑ ํ ๋ฌธ์ ์ ์ก
6. DB์ ์ ์ก๋ ์ธ์ฆ ํ์
๋ฐ ์ธ์ฆ ๋ฒํธ ์ ์ฅ.
- ์์ฒญ ๋ฐ๋ [SmsCertificateReq.java]
์์ด๋/ ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ ๋ชจ๋ ๋ค ์ ํ๋ฒํธ๋ฅผ ์ ๋ ฅํ๋ ๊ฒ์ ๋์ผ,
์์ด๋ ์ฐพ๊ธฐ๋ ์ด๋ฆ์ ๋ณด๋ด๊ณ , ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ๋ ์์ด๋๋ฅผ ๋ณด๋ด๋ ๊ฒ์ผ๋ก ๋ช ์ธ์์ ์์ฑํ์ฌ ํ๋ก ํธ์ ํ์๋ฅผ ๋ณด์๋ค.
- SellerController.java
- SellerService.java
@Transactional(rollbackFor = BaseException.class) public int lostIdAndPw(SmsCertificateReq smsCertificateReq) throws BaseException { // 1) ์ฌ๋ฐ๋ฅธ ๋ฐ๋ value๋ก ์์ฒญ๋์ง ์์์๋ if(smsCertificateReq.getPhoneNum() == null && (smsCertificateReq.getName() == null|| smsCertificateReq.getUid() == null)){ throw new BaseException(REQUEST_ERROR); // 2000 : ์ ๋ ฅ๊ฐ์ ํ์ธํด์ฃผ์ธ์ } // 2) ์ธ์ฆ ํ์ ์ค์ String findType; if (smsCertificateReq.getName() != null && smsCertificateReq.getUid() == null){ findType = "I"; // ID ์ฐพ๊ธฐ๋ ์ด๋ฆ != null && ์์ด๋ == null } else if (smsCertificateReq.getName() == null && smsCertificateReq.getUid() != null){ findType = "P"; // PW ์ฐพ๊ธฐ๋ ์์ด๋ != null && ์ด๋ฆ == null } else{ throw new BaseException(REQUEST_ERROR); // 2000 : ์ ๋ ฅ๊ฐ์ ํ์ธํด์ฃผ์ธ์ } // 3) ๊ฐ์ ํ์ง ์์ ํ์์ผ๋ int sellerValidCheck = sellerDao.validLoginInfo(smsCertificateReq, findType); if (sellerValidCheck == 0){ throw new BaseException(POST_USERS_NOT_FOUND); // 2021 : ๊ฐ์ ๋์ง ์์ ํ์์ ๋๋ค. } // 4) ๋๋ค ์ธ์ฆ๋ฒํธ ์์ฑ (๋ฒํธ) Random rand = new Random(); String certificationNum = ""; for(int i=0; i<6; i++) { String ran = Integer.toString(rand.nextInt(10)); certificationNum+=ran; } // 5) cool SMS์ธ์ฆ๋ฒํธ ๋ฐ์ก try{ // ์ธ์ฆ ๋ฉ์์ง ์์ฑ Message message = new Message(); message.setFrom("01043753181"); message.setTo(smsCertificateReq.getPhoneNum()); message.setText((findType == "I"? "Jatteoli ์์ด๋ ์ฐพ๊ธฐ\n์ธ์ฆ๋ฒํธ" : "Jatteoli ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ\n์ธ์ฆ๋ฒํธ") + " : ["+certificationNum+"]"); // coolSMS API ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ํธ๋ํฐ์ ์ ์ก SingleMessageSentResponse response = this.messageService.sendOne(new SingleMessageSendingRequest(message)); log.info("coolSMS API์์ฒญ :{}", response); // DB์ ์ ์ก ์ธ์ฆ์ ๋ณด ์ ์ฅ int smsSendRes = smsDao.smsSend(smsCertificateReq, certificationNum, findType); return smsSendRes; }catch(Exception exception){ throw new BaseException(COOLSMS_API_ERROR); // 5010 : SMS ์ธ์ฆ๋ฒํธ ๋ฐ์ก์ ์คํจํ์์ต๋๋ค. } }
- ์์ด๋ ์ฐพ๊ธฐ์ธ์ง ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์์ฒญ์ธ์ง ์ปจํธ๋กค๋ฌ์์ ๊ตฌ๋ณํ์ผ๋ฉด ์ฝ๋๊ฐ ๋ ๊น๋ํ์ ๊ฒ ๊ฐ์๋ฐ.. ํ์ ์ค์ ์ด๋ DB์ ์ ์ฅํ๋ ๊ธฐ์ค์ ๋๋ฌด ํ๋๋ง ๋ฐ๋ผ๋ณด๊ณ ์ฒ๋ฆฌํ์๋ค..
- ๋ฐํ ๊ฐ์ DB์ ์ ์ฅ๋ smsIdx ๊ฐ์ ์ฃผ์๋ค.
- SellerDao.java
public int validLoginInfo(SmsCertificateReq smsCertificateReq, String findType){ String query = "SELECT EXISTS(" + "SELECT * FROM Merchandisers M " + (findType.equals("I") ? "WHERE M.name = ? AND M.phone = ?)" : "WHERE M.uid = ? AND M.phone = ?)"); Object[] params = new Object[]{ (findType.equals("I") ?smsCertificateReq.getName() : smsCertificateReq.getUid()), smsCertificateReq.getPhoneNum() }; return this.jdbcTemplate.queryForObject(query, int.class, params); }
public int smsSend(SmsCertificateReq smsCertificateReq, String certificationNum, String checkType){ String query = "INSERT INTO Sms(phone, name, uid, certification_num, status)" + "VALUES(?, ?, ?, ?, ?);"; Object[] params = new Object[]{ smsCertificateReq.getPhoneNum(), smsCertificateReq.getName() == null ? null : smsCertificateReq.getName(), smsCertificateReq.getUid() == null ? null : smsCertificateReq.getUid(), certificationNum, checkType }; this.jdbcTemplate.update(query, params); String lastInsertIdQuery = "select last_insert_id()"; return this.jdbcTemplate.queryForObject(lastInsertIdQuery,int.class); }
- ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ ๋ฒํธ ์ธ์ฆ์ SMS ์ธ์ฆ์ผ๋ก ๊ตฌํํ์๋ค. -> SMS ๋ฌธ์ ์ธ์ฆ ํฌ์คํ
- ์์ ์๋ 5. /jat/sellers/lost ์ ๋๊ฐ์ ์์์ ํธ๋ํฐ์ผ๋ก ์์ ๋ฐ์ ์ธ์ฆ๋ฒํธ๋ฅผ ์ถ๊ฐ๋ก Body์ ๋ด์ POST๋ก ์์ฒญํ๋ค.
- ์์ฒญ ๋ฐ๋ [ReceivedNumConfReq.java]
- SellerController.java
- id-find: ์์ด๋ ์ฐพ๊ธฐ๋ ํ ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ ์ ๋ณด๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ ์์ด๋, ์์ฑ๋ ์ง๋ฅผ ๋ฆฌ์คํธ ํํ๋ก ๋ฐํํ์๊ณ ,
- pw-find: ๋น๋ฐ๋ฒํธ๋ ๋ณธ์ธ ์ธ์ ๋ฐ๊พธ๋ฉด ์๋๊ธฐ์, ๋ค์ ์ฌ์ค์ ์์ฒญ์์ ์ธ๊ฐ๋ ์ ๊ทผ์ ํ ์ ์๋๋ก jwt๋ฅผ ํฌํจํ์ฌ ๋ฐํํ๋ค.
- SellerService.java
// ์์ด๋ ์ฐพ๊ธฐ public List<ReceivedNumConfRes> idFind(ReceivedNumConfReq receivedNumConfReq) throws BaseException{ try{ int smsIdx = smsDao.smsCheckId(receivedNumConfReq); if (smsIdx == 1){ return sellerDao.idFind(receivedNumConfReq); } else{ throw new BaseException(SMS_CERTIFICATE_FAILED); // 4022 : SMS ์ธ์ฆ ์คํจ } }catch(Exception exception){ throw new BaseException(SMS_DATA_FIND_ERROR); // 4021 : ์ ํจํ์ง ์์ SMS ์ธ์ฆ๋ฒํธ ์์ฒญ์ ๋๋ค. } }
// ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ public ReceivedNumConfPwRes pwFind(ReceivedNumConfReq receivedNumConfReq) throws BaseException{ try{ int smsIdx = smsDao.smsCheckPw(receivedNumConfReq); if (smsIdx == 1){ int sellerIdx = sellerDao.JwtForRestorePw(receivedNumConfReq); String jwt = jwtTokenProvider.createJwt(sellerIdx, "Merchandiser"); return new ReceivedNumConfPwRes(jwt, receivedNumConfReq.getUid(), 1); } else{ throw new BaseException(SMS_CERTIFICATE_FAILED); // 4021 : ๋น๋ฐ๋ฒํธ ์ํธํ์ ์คํจํ์์ต๋๋ค } }catch(Exception exception){ throw new BaseException(SMS_DATA_FIND_ERROR); // 4022 : SMS ์ธ์ฆ ์คํจ } }
- SmsDao.java
// ์์ด๋ ์ฐพ๊ธฐ : ์์ด๋ ์ฐพ๊ธฐ ์ ์ธ์ฆ ์์ฒญ์ ๋ณด๋์ ๋ ๋ฐ์ํ ์ธ์ฆ๋ฒํธ๋ฅผ ํ์๊ฐ์ผ๋ก๋ถํฐ 3๋ถ์ด๋ด, // ์์ฒญํ ์ ํ๋ฒํธ์ ์ด๋ฆ์ผ๋ก ๊ฐ์ ๋ ํ์์ ๋ง์ง๋ง ๋ฐ์ ์ธ์ฆ๋ฒํธ๋ฅผ ์กฐํํ๋ค. public int smsCheckId(ReceivedNumConfReq receivedNumConfReq) { String query = "SELECT EXISTS(\n" + " SELECT\n" + " * \n" + " FROM Sms WHERE phone = ?\n" + " AND name = ?\n" + " AND certification_num = ?\n" + " AND status = 'I'\n" + " AND created >= DATE_ADD(NOW(), INTERVAL -3 MINUTE) \n" + " ORDER BY created DESC LIMIT 1" + " )"; Object[] params = new Object[]{ receivedNumConfReq.getPhoneNum(), receivedNumConfReq.getName(), receivedNumConfReq.getCertificationNum() }; return this.jdbcTemplate.queryForObject(query, int.class, params); }
// ๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ : ์์ด๋ ์ฐพ๊ธฐ์ ๊ฐ์ ์๊ฐ ๋ฒ์์์ ๋ง์ง๋ง ์ธ์ฆ๋ฒํธ๋ฅผ ์กฐํํ์ฌ ๋น๊ตํ๋ค. // ์กด์ฌํ๋ค๋ฉด, ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ๊ฐ๋ฅ. public int smsCheckPw(ReceivedNumConfReq receivedNumConfReq){ String query = "SELECT EXISTS(\n" + " SELECT\n" + " *\n" + " FROM Sms WHERE phone = ? \n" + " AND uid = ? \n" + " AND certification_num = ? \n" + " AND status = 'P'\n" + " AND created >= DATE_ADD(NOW(), INTERVAL -3 MINUTE) \n" + " ORDER BY created DESC LIMIT 1" + " )"; Object[] params = new Object[]{ receivedNumConfReq.getPhoneNum(), receivedNumConfReq.getUid(), receivedNumConfReq.getCertificationNum() }; return this.jdbcTemplate.queryForObject(query, int.class, params); }
- /jat/sellers/pw-find ์์ฒญ ์ดํ, ์๋ง์ ์ธ์ฆ๋ฒํธ๋ก ์ธ์ฆ์ด ์๋ฃ๋๋ฉด, ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ํ๋ฉด์ผ๋ก ๋์ด๊ฐ๊ฒ ๋๋ค.
- ๋ง์ผ ํด๋น URI๋ก ์๋์น ์์ ์ ๊ทผ์ ํตํด ์ ์ ์ PW๋ฅผ ๋ค๋ฅธ ์ฌ๋์ด ๋ณ๊ฒฝํ๋ คํ๋ค๋ฉด, ์๋๊ธฐ ๋๋ฌธ์ ๋น๋ฐ๋ฒํธ ์ฌ์ค์ ์ ์ธ์ฆ ๊ณผ์ ์์ ๋ฐํํ JWT ํ ํฐ์ ํค๋์ ๋ด์์ ๋ฐ๋์ ์์ฒญํ๋๋ก ๊ตฌํํ๊ธฐ๋ก ํ์๋ค.
(1) ๋ก์ง ํ๋ก์ฐ
1. ๋ฐ๊ฟ ๋น๋ฐ๋ฒํธ์, ์ฌ๋ฐ๋ฅด๊ฒ ์
๋ ฅํ๋์ง ํ์ธ์ฉ ๋น๋ฐ๋ฒํธ๋ฅผ Patch๋ก ์์ฒญ๋ฐ๋๋ค.
2. ๋ ๋น๋ฐ๋ฒํธ ๊ฐ์ด ๊ฐ์์ง ๋น๊ตํ๋ค.
3. ๊ฐ๋ค๋ฉด SHA256 ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ํตํด ๋ค์ ์ํธํํ๊ณ ,
4. DB์ ํด๋น ์ ์ ์ password ์นผ๋ผ์ ๊ฐ์ ์์ ํ๋ค.
- ์์ฒญ ๋ฐ๋ [RestorePwReq.java]
- SellerController.java
- SellerService.java
-> ์ํธํ ๊ด๋ จ ํฌ์คํ@Transactional(rollbackFor = BaseException.class) public RestorePwRes pwRestore(RestorePwReq restorePwReq, int sellerIdx) throws BaseException{ if (!restorePwReq.getPw().equals(restorePwReq.getPwCheck())){ throw new BaseException(MODIFY_FAIL_USERPASSWORD); // 4015 : ์ ์ ๋น๋ฐ๋ฒํธ ์์ ์คํจ } String pwd, salt; try{ salt = SHA256.createSalt(restorePwReq.getPw()); // ๋น๋ฐ๋ฒํธ๋ฅผ ์ด์ฉํ์ฌ salt ์์ฑ pwd = new SHA256().encrypt(restorePwReq.getPw(), salt); // ๋น๋ฐ๋ฒํธ ์ํธํ }catch(Exception exception){ throw new BaseException(PASSWORD_ENCRYPTION_ERROR); // 4011 : ๋น๋ฐ๋ฒํธ ์ํธํ์ ์คํจํ์์ต๋๋ค. } try{ sellerDao.pwRestore(sellerIdx, salt, pwd); return new RestorePwRes(0,1); }catch(Exception exception){ throw new BaseException(MODIFY_FAIL_USERPASSWORD); // 4015 : ์ ์ ๋น๋ฐ๋ฒํธ ์์ ์คํจ } }
- SellerDao.java
-> jwt๋ฅผ ํตํด ๋๊ฒจ ๋ฐ์ ํ๋งค์ ์๋ณ Id๋ก DBํ ์ด๋ธ์ ๊ฐ์ UPDATEํ์๋ค.public void pwRestore(int sellerIdx, String salt, String pwd) { String query = "UPDATE Merchandisers\n" + "SET salt = ? , password = ?\n" + "WHERE sellerIdx = ?"; Object[] params = new Object[]{ salt, pwd, sellerIdx }; this.jdbcTemplate.update(query, params); }
์ด์ ํ์์ , ๋ก๊ทธ์ธ์ ๊ด๋ จ๋ ๊ธฐ๋ฅ์ ๋ชจ๋ ํฌ์คํ
์๋ฃํ์๋ค.
๋ค์ ํฌ์คํ
์ ๋ง์ง๋ง์ผ๋ก ํด๋น ํ๋ก์ฐ๋ฐ๋ก ๋ชจ๋ API ํ
์คํธ๋ฅผ ์งํํ๊ณ DB์ ์ ์ฅ๋๋ ๊ฐ๋ ํ์ธํด ๋ณด๊ฒ ์.