CoolSMS
SpringBoot와 CoolSMS로 문자 인증 구현
문자 인증을 구현하려는데, CoolSMS가 제일 자료도 많고 편리해 보여 선택하였다.
CoolSMS 사용 준비
CoolSMS 회원가입하고 API Key를 생성한다.
CoolSMS 사이트
메뉴 -> 개발/연동 -> API Key 관리에서 발급한다.
한 건당 가격이 나가고, 첫 가입시 일정 포인트를 제공한다.
build.gradle 의존성 추가
// cool SMS
implementation 'net.nurigo:sdk:4.3.0'
application-cool-sms.yml
API_KEY: ㅁㄴㅇㄹ
API_SECRET: ㅁㄴㅇㄹ
FROM_PHONE_NUMBER: ㅁㄴㅇㄹ
SmsUtil
package com.backend.dorandoran.user.service;
import jakarta.annotation.PostConstruct;
import net.nurigo.sdk.NurigoApp;
import net.nurigo.sdk.message.model.Message;
import net.nurigo.sdk.message.request.SingleMessageSendingRequest;
import net.nurigo.sdk.message.service.DefaultMessageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@PropertySource("classpath:application-cool-sms.yml")
@Component
public class SmsUtil {
@Value("${API_KEY}")
private String API_KEY;
@Value("${API_SECRET}")
private String API_SECRET_KEY;
@Value("${FROM_PHONE_NUMBER}")
private String FROM_PHONE_NUMBER;
private DefaultMessageService messageService;
@PostConstruct
private void init() {
messageService = NurigoApp.INSTANCE.initialize(API_KEY, API_SECRET_KEY, "https://api.coolsms.co.kr");
}
// 단일 메시지 발송 예제
public void sendSms(String phoneNumber, String verificationCode) {
Message message = new Message();
// 발신번호 및 수신번호는 반드시 01012345678 형태로 입력되어야 한다.
message.setFrom(FROM_PHONE_NUMBER);
message.setTo(phoneNumber);
message.setText("인증번호[" + verificationCode + "] 타인에게 절대 알려주지 마세요.");
messageService.sendOne(new SingleMessageSendingRequest(message));
}
}
SmsVerificationRepository
redis와 연결해서 인증번호를 저장한다.
package com.backend.dorandoran.user.repository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import java.time.Duration;
@RequiredArgsConstructor
@Repository
public class SmsVerificationRepository {
private final String PREFIX = "sms:";
private final Duration SMS_LIMIT_TIME = Duration.ofSeconds(5 * 60);
private final StringRedisTemplate redisTemplate;
public void createSmsVerificationCode(String phoneNumber, String verificationCode) {
redisTemplate.opsForValue().set(PREFIX + phoneNumber, verificationCode, SMS_LIMIT_TIME);
}
public String getSmsVerificationCode(String phoneNumber) {
return redisTemplate.opsForValue().get(PREFIX + phoneNumber);
}
public void removeSmsVerificationCode(String phoneNumber) {
redisTemplate.delete(PREFIX + phoneNumber);
}
public boolean hasKey(String phoneNumber) {
return Boolean.TRUE.equals(redisTemplate.hasKey(PREFIX + phoneNumber));
}
}
application-redis.yml
REDIS_PORT: ㅁㄴㅇㄹ
REDIS_HOST: ㅁㄴㅇㄹ
REDIS_PASSWORD: ㅁㄴㅇㄹ
RedisConfig
package com.backend.dorandoran.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
@EnableCaching
@Configuration
@PropertySource("classpath:application-redis.yml")
public class RedisConfig {
@Value("${REDIS_HOST}")
private String HOST;
@Value("${REDIS_PORT}")
private String PORT;
@Value("${REDIS_PASSWORD}")
private String PASSWORD;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(HOST);
redisStandaloneConfiguration.setPort(Integer.parseInt(PORT));
redisStandaloneConfiguration.setPassword(PASSWORD);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public StringRedisTemplate stringRedisTemplate() {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory());
return stringRedisTemplate;
}
}
자세한 코드는 프로젝트 깃허브를 참고
sms 구현은 다음 블로그를 참고했습니다.
겪은 에러
세팅을 다 하고 문자를 보내기 위해 테스트를 했다. 하지만 계속해서 허용되지 않은 ip라는 에러가 발생했다.
처음에는 CORS에러인줄 알고 SecurityConfig를 계속 보았다. 모두 disable해도 해결되지 않았다.
그러다가.. 찾은 해결 방법!
CoolSMS의 API Key에는 허용 IP를 설정하는 부분이 있다.
처음 개발을 시작한 강남의 한 카페 IP만 등록해두고.. 내 집 IP는 등록해두지 않아서 forbidden에러가 났던 것이다.
부디 이 글을 읽는 사람은 나와 같은 어이없는 실수를 하지 말길 빈다.