코딩 노트
카카오지도 api 사용2 - 주소, 이메일인증 본문
5.map-address.html
이메일 보내기(SMTP Service) HTTP에서 SMTP를 어떻게 이용하는가?
spring13 project 생성 후 src/test/java 패키지에 Test01 클래스 생성
@Slf4j //로그 쓰고 싶을 때
@SpringBootTest
public class Test01 {
@Test
public void test() {
//이메일 발송 코드
//- 발송 가능한 계정이 필요(ex : gmail)
//- 프로젝트 생성 시 java mail sender라는 도구가 추가되어야 함
//전송 도구 - 업체와 계정관련 정보 설정
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("smtp.gmail.com"); //이메일 제공 업체 주소
sender.setPort(587); //업체포트
sender.setUsername("qufquf12120@gmail.com"); //나의이메일계정
sender.setPassword("ajeprfgyoraxwuks"); //나의앱비밀번호(비번x)
//통신과 관련된 추가 설정
Properties props = new Properties();
props.setProperty("mail.smtp.auth", "true"); //인증 후 이용 설정(필수)
props.setProperty("mail.stmp.debug", "true"); //디버깅 기능 이용 설정(선택)
props.setProperty("mail.smtp.starttls.enable", "true"); // TLS 사용 설정(필수)
props.setProperty("mail.stmp.ssl.protocols", "TLSv1.2"); //TLS 버전 설정(필수)
props.setProperty("mail.smtp.ssl.trust", "smtp.gmail.com"); //신뢰할 수 있는 대상 설정(필수)
sender.setJavaMailProperties(props);
//전송 메세지 - 상대방의 정보와 메일 내용을 설정
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("wkdtoquf3@naver.com"); //받는사람
message.setSubject("야"); //제목
message.setText("호"); //내용
//전송
sender.send(message);
}
}
이렇게 하면 입력한 wkdtoquf3@naver.com으로 이메일이 발송된다.
SSL
- 보안이 강화된 통신 방식(http --> https)
- 전송하는 모든 데이터를 암호화하여 전숭/수신
- 반드시 서비스 제공자가 인증서를 등록해야함
TLS
- SSL 버전 3.0부터를 TLS라고 부름
application.properties 수정
# project setting file
# key=value
# database setting
#sever setting
#server.port=9999
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=C##home
spring.datasource.password=home
#logging setting
logging.level.root=warn
logging.level.com.kh=debug
logging.pattern.console=[%-5level] %msg - %c [%d{yyyy-MM-dd HH:mm:ss.S}] %n
# logging file setting
#logging.file.name= logs/server.log
#logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss.S} [%-5level] %msg - %c %n
#logging.logback.rollingpolicy.max-file-size=10MB
#logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}-%d{yyyy-MM-dd-HH}-%i.log
#file upload setting
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB
#custom properties setting
#custom.fileupload.home=C:/upload/profile
custom.email.host=smtp.gmail.com
custom.email.port=587
custom.email.username=qufquf12120
custom.email.password=ajeprfgyoraxwuks
EmailProperties 클래스 생성
@Component
@Data
@ConfigurationProperties(prefix = "custom.email")
public class EmailProperties {
private String host;
private int port;
private String username, password;
}
Test01 수정
@Slf4j //로그 쓰고 싶을 때
@SpringBootTest
public class Test01 {
@Test
public void test() {
//이메일 발송 코드
//- 발송 가능한 계정이 필요(ex : gmail)
//- 프로젝트 생성 시 java mail sender라는 도구가 추가되어야 함
//전송 도구 - 업체와 계정관련 정보 설정
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("smtp.gmail.com"); //이메일 제공 업체 주소
sender.setPort(587); //업체포트
sender.setUsername("qufquf12120@gmail.com"); //나의이메일계정
sender.setPassword("ajeprfgyoraxwuks"); //나의앱비밀번호(비번x)
//통신과 관련된 추가 설정
Properties props = new Properties();
props.setProperty("mail.smtp.auth", "true"); //인증 후 이용 설정(필수)
props.setProperty("mail.stmp.debug", "true"); //디버깅 기능 이용 설정(선택)
props.setProperty("mail.smtp.starttls.enable", "true"); // TLS 사용 설정(필수)
props.setProperty("mail.stmp.ssl.protocols", "TLSv1.2"); //TLS 버전 설정(필수)
props.setProperty("mail.smtp.ssl.trust", "smtp.gmail.com"); //신뢰할 수 있는 대상 설정(필수)
sender.setJavaMailProperties(props);
//전송 메세지 - 상대방의 정보와 메일 내용을 설정
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("wkdtoquf3@naver.com"); //받는사람
message.setSubject("야"); //제목
message.setText("호"); //내용
//전송
sender.send(message);
}
}
Emailconfiguration 생성
//JavaMailSenderImpl을 스프링에 등록해두기 위한 설정
//- Bean 등록을 하는 설정파일은 상속이 필요하지 않다.
@Configuration
public class Emailconfiguration {
@Autowired
private EmailProperties emailProperties;
//객체를 생성하여 반환하는 메소드를 만들고 상단에 @Bean 추가
// @Bean
// public String Hello() { //Autowired가 된다. method 이름(Hello)이 id이다.
// return "Hello world";
// }
@Bean
public JavaMailSender sender() {
//전송 도구 - 업체와 계정관련 정보 설정
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost(emailProperties.getHost()); //이메일 제공 업체 주소
sender.setPort(emailProperties.getPort()); //업체포트
sender.setUsername(emailProperties.getUsername()); //나의이메일계정
sender.setPassword(emailProperties.getPassword()); //나의앱비밀번호(비번x)
//통신과 관련된 추가 설정
Properties props = new Properties();
props.setProperty("mail.smtp.auth", "true"); //인증 후 이용 설정(필수)
props.setProperty("mail.stmp.debug", "true"); //디버깅 기능 이용 설정(선택)
props.setProperty("mail.smtp.starttls.enable", "true"); // TLS 사용 설정(필수)
props.setProperty("mail.stmp.ssl.protocols", "TLSv1.2"); //TLS 버전 설정(필수)
props.setProperty("mail.smtp.ssl.trust", "smtp.gmail.com"); //신뢰할 수 있는 대상 설정(필수)
sender.setJavaMailProperties(props);
return sender;
}
}
Test03 생성
@Slf4j //로그 쓰고 싶을 때
@SpringBootTest
public class Test03 {
//application.properties에 작성된 정보를 불러와 사용
@Autowired
private JavaMailSender sender;
@Test
public void test() {
//전송 메세지 - 상대방의 정보와 메일 내용을 설정
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("wkdtoquf3@naver.com"); //받는사람
message.setSubject("야"); //제목
message.setText("호"); //내용
//전송
sender.send(message);
}
}
springhome 프로젝트로 돌아와서
MemberController에 구문 추가 후
//비밀번호 찾기
@GetMapping("/findPw")
public String findPw() {
return "/WEB-INF/views/member/findPw.jsp";
}
@PostMapping("/findPw")
public String findPw(@ModelAttribute MemberDto memberDto) {//아이디, 이메일
//[1] 아이디로 모든 정보를 불러오고
MemberDto findDto = memberDao.selectOne(memberDto.getMemberId());
//[2] 이메일이 일치하는지 확인한다.
boolean isValid = findDto != null &&
findDto.getMemberEmail().equals(memberDto.getMemberEmail());
if(isValid) { //find와 memberDto의 이메일이 같다면
//이메일 발송 코드
return "redirect:발송완료안내페이지";
}
else { //이메일이 다르다면
return "redirect:findPw?error";
}
}
@Autowired
private JavaMailSender sender;
mamber > findPw.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<jsp:include page="/WEB-INF/views/template/header.jsp"></jsp:include>
`
<h1>비밀번호 찾기</h1>
<br><br>
<form action ="findPw" method="post">
아이디 <input type="text" name="memberId" required><br><br>
이메일 <input type="email" name="memberEmail" required><br><br>
<button type="submit">비밀번호 찾기</button>
</form>
<jsp:include page="/WEB-INF/views/template/footer.jsp"></jsp:include>
InterceptorConfiguration에 구문 추가
registry.addInterceptor(memberInterceptor) //등록한 화면에
.addPathPatterns(
"/member/**",
"/board/**",
"/rest/reply/**"
)
.excludePathPatterns( //관련된 페이지들을 검사하지 않겠다
"/member/join*",
"/member/login",
"/member/find*", //추가
"/member/exitFinish",
"/board/list*",
"/board/detail",
"/rest/reply/list"
);
springhome 프로젝트에 spring13 프로젝트에서 만든
apllication.properties 설정 파일과, EmailProperties, EmailConfiguration을 가져온다.
MemberController에 구문 완성
//비밀번호 찾기
@GetMapping("/findPw")
public String findPw() {
return "/WEB-INF/views/member/findPw.jsp";
}
@PostMapping("/findPw")
public String findPw(@ModelAttribute MemberDto memberDto) {//아이디, 이메일
//[1] 아이디로 모든 정보를 불러오고
MemberDto findDto = memberDao.selectOne(memberDto.getMemberId());
//[2] 이메일이 일치하는지 확인한다.
boolean isValid = findDto != null &&
findDto.getMemberEmail().equals(memberDto.getMemberEmail());
if(isValid) { //find와 memberDto의 이메일이 같다면
//이메일 발송 코드
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(findDto.getMemberEmail());
message.setSubject("비밀번호 찾기 결과");
message.setText(findDto.getMemberPw());
sender.send(message);
return "redirect:findPwFinish";
}
else { //이메일이 다르다면
return "redirect:findPw?error";
}
}
@RequestMapping("/findPwFinish")
public String findPwFinish() {
return "/WEB-INF/views/member/findPwFinish.jsp";
}
}
findPwFinish.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:include page="/WEB-INF/views/template/header.jsp"></jsp:include>
<h1>이메일 전송이 완료되었습니다. 확인 바랍니다.</h1>
<jsp:include page="/WEB-INF/views/template/footer.jsp"></jsp:include>
인증 시스템
이메일과 인증번호를 이용하여 이메일의 유효성을 검사하는 시스템
이메일이 아니라 문자 서비스와 연결된다면 문자인증 시스템이 됨
인증 테이블
- 대상 정보 : 대상의 이메일 또는 연락처(기본키)
- 인증번호 : 6자리의 무작위 숫자로 구성된 문자열
- 생성시각 : 현재시각을 기본값으로 가지며 제한시간을 위해 구현할 때 사용
CREATE TABLE cert(
cert_email varchar2(256) PRIMARY KEY,
cert_number char(6) NOT NULL,
cert_time DATE DEFAULT sysdate NOT NULL
);
CertDto 생성
@Data
public class CertDto {
private String certEmail;
private String certNumber;
private Date certTime;
}
CertMapper 생성
@Component
public class CertMapper implements RowMapper<CertDto>{
@Override
public CertDto mapRow(ResultSet rs, int rowNum) throws SQLException {
CertDto certDto = new CertDto();
certDto.setCertEmail(rs.getString("cert_email"));
certDto.setCertNumber(rs.getString("cert_number"));
certDto.setCertTime(rs.getDate("cert_time"));
return certDto;
}
}
CertDao 생성
public interface CertDao {
void insert(CertDto certDto);
boolean delete(String certEmail);
CertDto selectOne(String certEmail);
}
CertDaoImpl 구현
@Repository
public class CertDaoImpl implements CertDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private CertMapper certMapper;
@Override
public void insert(CertDto certDto) {
String sql = "insert into cert(cert_email, cert_number) values(?, ?)";
Object[] data = {certDto.getCertEmail(), certDto.getCertNumber()};
jdbcTemplate.update(sql,data);
}
@Override
public boolean delete(String certEmail) {
String sql = "delete cert where cert_email = ?";
Object[] data = {certEmail};
return jdbcTemplate.update(sql, data) > 0;
}
@Override
public CertDto selectOne(String certEmail) {
String sql = "select * from cert where cert_email = ?";
Object[] data = {certEmail};
List<CertDto> list = jdbcTemplate.query(sql, certMapper, data);
return list.isEmpty() ? null : list.get(0);
}
CertRestController 생성
@CrossOrigin
@RestController
@RequestMapping("/rest/cert")
public class CertRestConroller {
@Autowired CertDao certDao;
@Autowired
private JavaMailSender sender;
@PostMapping("/send")
public void send(@RequestParam String certEmail) {
//[1] 인증번호 생성
Random r = new Random();
int number = r.nextInt(1000000);
DecimalFormat fm = new DecimalFormat("000000");
String certNumber = fm.format(number);
//[2] 이메일 발송
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(certEmail);
message.setSubject("[KH정보교육원] 인증번호 안내");
message.setText("인증번호는 [" + certNumber + "] 입니다.");
sender.send(message); //이메일이 날아감
//[3] DB에 저장(기존 데이터 삭제)
certDao.delete(certEmail);
CertDto certDto = new CertDto();
certDto.setCertEmail(certEmail);
certDto.setCertNumber(certNumber);
certDao.insert(certDto);
}
//
// @PostMapping("/check")
}
59.email-auth.html
비동기통신으로 이메일 인증번호 발송
CertDao 추가
public interface CertDao {
void insert(CertDto certDto);
boolean delete(String certEmail);
boolean deleteOver5min();
CertDto selectOne(String certEmail);
CertDto selectOneIn5min(String certEmail);
}
CertDaoImpl 추가
@Override
public CertDto selectOneIn5min(String certEmail) {
String sql = "select * from cert "
+ "where cert_email = ? "
+ "and "
+ "cert_time between sysdate-5/24/60 and sysdate";
Object[] data = {certEmail};
List<CertDto> list = jdbcTemplate.query(sql, certMapper, data);
return list.isEmpty() ? null : list.get(0);
}
@Override
public boolean deleteOver5min() {
String sql = "delete cert where cert_time < sysdate-5/24/60";
return jdbcTemplate.update(sql) > 0;
}
}
CertRestController 수정
@CrossOrigin
@RestController
@RequestMapping("/rest/cert")
public class CertRestConroller {
@Autowired CertDao certDao;
@Autowired
private JavaMailSender sender;
@PostMapping("/send")
public void send(@RequestParam String certEmail) {
//[1] 인증번호 생성
Random r = new Random();
int number = r.nextInt(1000000);
DecimalFormat fm = new DecimalFormat("000000");
String certNumber = fm.format(number);
//[2] 이메일 발송
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(certEmail);
message.setSubject("[KH정보교육원] 인증번호 안내");
message.setText("인증번호는 [" + certNumber + "] 입니다.");
sender.send(message); //이메일이 날아감
//[3] DB에 저장(기존 데이터 삭제)
certDao.delete(certEmail);
CertDto certDto = new CertDto();
certDto.setCertEmail(certEmail);
certDto.setCertNumber(certNumber);
certDao.insert(certDto);
}
@PostMapping("/check")
public Map<String, Object> check(@ModelAttribute CertDto certDto) {
//[1] 이메일로 인증정보를 조회
//CertDto findDto = certDao.selectOne(certDto.getCertEmail()); //기간무제한
CertDto findDto = certDao.selectOneIn5min(certDto.getCertEmail()); //5분제한
if(findDto != null) {
//[2] 인증번호 비교
boolean isValid =
findDto.getCertNumber().equals(certDto.getCertNumber());
if(isValid) {
//인증 성공하면 인증번호를 삭제
certDao.delete(certDto.getCertEmail());
return Map.of("result", true);
}
}
return Map.of("result", false);
}
}
기본으로 생성되는 SpringhomeApplication 클래스에 설정
//스케줄러를 사용하고 싶다면 사용하겠다는 설정을 해야 한다.
@SpringBootApplication
@EnableScheduling //추가
public class SpringhomeApplication {
public static void main(String[] args) {
SpringApplication.run(SpringhomeApplication.class, args);
}
}
service 패키지 생성 후 RegularService 생성
/*
* 서비스(service)
* - 복잡한 작업들을 하나로 묶어서 의미를 부여하기 위한 가장 큰 작업 단위
* - 스케줄러 등을 이용해서 독립적으로 작업을 실행하기 위한 도구
*/
public interface RegularService {
void clearCert();
}
RegularServiceImpl 생성
/*
* 서비스(service)
* - 복잡한 작업들을 하나로 묶어서 의미를 부여하기 위한 가장 큰 작업 단위
* - 스케줄러 등을 이용해서 독립적으로 작업을 실행하기 위한 도구
*/
@Slf4j
@Service
public class RegularServiceImpl implements RegularService {
@Autowired
private CertDao certDao;
//스케줄러 메소드는 언제 실행할 것인지에 대한 설정이 추가로 필요
//와일드카드(*)는 해당되는 것 모두 다라는 뜻이다.
// * = all / ? = any
//@Scheduled(fixedRate = 1000) //1000ms(1초)에 한 번씩
//@Scheduled(cron = "* * * * * *")//예약식이 들어감 / 매초 매분 매시 매일 매월 매요일
//@Scheduled(cron = "*/2 * * * * *")//매2초 매분 매시 매일 매월 매요일(2초마다)
//@Scheduled(cron = "0 * * * * *")//0초 매분 매시 매일 매월 매요일(1분마다)
@Scheduled(cron = "0 0 * * * *")//매 시 정각마다
//@Scheduled(cron = "0 30 * * * *")//30분마다
//@Scheduled(cron = "0 0 9 * * *")//매일아침 9시
//@Scheduled(cron = "0 30 9,18 * * *")//출근할 때(9:30), 퇴근할 때(18:30) 한 번씩
//@Scheduled(cron = "0 30 9-18 * * *")//출근할 때부터 퇴근할 때까지 1시간마다(9시반,10시반,...6시반)
//@Scheduled(cron = "0 30 9-18 * * 1-5")//월~금까지 근무시간 1시간마다(숫자 1은 월요일)
//@Scheduled(cron = "0 30 9-18 * * mon-fri")//바로 위코드 다른 버전
//@Scheduled(cron = "* * * * * mon")//월요일만 1초마다
//@Scheduled(cron = "* * * 18 * ?")//요일 무관 매 18일마다
//@Scheduled(cron = "0 0 12 ? * 4L")//매월 마지막(L) 목요일(4) 12시 정각
//@Scheduled(cron = "0 0 12 ? * thuL")//매월 마지막(L) 목요일(thu) 12시 정각(위 코드와 같음)
//@Scheduled(cron = "0 0 12 ? * 4#1")//매월 1주차 목요일(4) 12시 정각
//@Scheduled(cron = "0 0 12 ? * thu#1")//매월 1주차 목요일(thu) 12시 정각(위 코드와 같음)
@Override
public void clearCert() {
// log.debug("실행되니?");
certDao.deleteOver5min();
}
}
'JavaScript' 카테고리의 다른 글
카카오지도 api 사용1 - 지도, 마커 (0) | 2023.09.15 |
---|---|
Javascript04 - 자바스크립트 최종형태(반복문) (0) | 2023.09.05 |
Javascript03 - 회원가입 검사 코드, 체크박스 (0) | 2023.09.04 |
Javascript02 - 게시글 작성 (0) | 2023.09.01 |
Javascript02 - 정규표현식 (0) | 2023.09.01 |