[프로젝트 개선] - 웹사이트 제작 15. (Spring/Java) 이메일 인증하기 (+인증번호)

JINI·2023년 5월 6일
3
post-thumbnail

그 전에 했던 프로젝트 내용은 회원가입 페이지에서 단순히 이메일을 입력해서 회원가입을 진행했으나 본인 인증 수단으로 사용할 수 있는 이메일 인증을 구현해보고 싶었다.
그래서 이번에는 이메일 인증을 통해 보안을 강화하는 기능 업데이트를 해보려고 한다.


📧이메일 인증 방법
1️⃣ 인증번호 입력
2️⃣ 링크 클릭


업데이트 내용
🚩Before ➡️ 단순 이메일 입력
🚩After   ➡️ 인증번호를 받아 이메일 인증


📧 이메일 인증번호 전송


⚙️ 라이브러리 추가 / 앱키 발급 /보안 설정


1. 인증 관련 라이브러리 추가

메일 인증을 위한 라이브러리를 pom.xml에 추가한다.

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>${org.springframework-version}</version>
</dependency>

<dependency>
	<groupId>javax.mail</groupId>
	<artifactId>javax.mail-api</artifactId>
	<version>1.5.4</version>
</dependency>

버전을 직접 적어도 되지만
<version>${org.springframework-version}</version>
자동으로 버전을 맞춰주기 때문에 더 편리하다.


2. 구글 앱 비밀번호 생성

원래 보안 수준이 낮은 앱의 액세스 허용 설정으로 이메일 인증을 할 수 있었는데 현재는 해당 서비스가 종료됐다.

2단계 인증을 활성화하고 앱 비밀번호를 생성해야 하고,
이 비밀번호는 지메일 비밀번호 대신 사용해야 하기에 꼭 필요한 과정이다.


🚧발생하는 오류🚧

여기서 잠시! 앱 비밀번호 설정을 하지 않고 일반 비밀번호 입력시 발생하는 오류이다.

이렇게 유저의 이름과 패스워드가 오류나서 메일을 보낼 수 없다고 뜬다.



(1) 구글 계정 로그인

(2) Google 계정 관리 - 보안 탭 클릭 - 2단계 인증 활성화

(3) 앱 비밀번호 생성

16자리 앱 비밀번호가 생성된다.


3. 발신 메일 관련 설정(SSL 보안)

2가지 경우가 있는데 1번 방식을 이용하려고 한다.

✔️1. xml 파일 (root-context.xml)

  1. java 파일 (mailConfig.java)

root-context.xml에 이메일 인증 관련 설정을 위해 bean을 등록한다.

<bean id="mailSender"
		class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host" value="smtp.gmail.com" />
		<property name="port" value="587" />
		<property name="username" value="구글 계정@gmail.com" />
		<property name="password" value="비밀번호 대신 앱키 입력" />
		<property name="javaMailProperties">
			<props>
				<prop key="mail.transport.protocol">smtp</prop>
				<prop key="mail.smtp.auth">true</prop>
				<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
				<prop key="mail.smtp.starttls.enable">true</prop>
				<prop key="mail.debug">true</prop>
				<prop key="mail.smtp.ssl.trust">smtp.gmail.com</prop>
				<prop key="mail.smtp.ssl.protocols">TLSv1.2</prop>
			</props>
		</property>
	</bean>

이메일 관련 기본 설정이 끝났다.
본격적으로 코드를 작성해보자.





📕 코드 작성


📕JS

메일로 인증번호 전송

var code = "";  /*인증번호 저장할 곳*/
$('#auth_btn').click(function() {
	var email = $('#email').val();  /*입력한 이메일*/
	console.log('완성된 이메일 : ' + email); /* 이메일 오는지 확인*/
	var checkInput = $('.mail-check-input') /* 인증번호 입력 */

	$.ajax({
		type: 'GET',
		url: 'mailCheck?email=' + email, /*url을 통해 데이터를 보낼 수 있도록 GET방식, url명을 "mailCheck"로 지정 */
		success: function(data) {
			console.log("data : " + data);
			checkInput.attr('disabled', false); /*데이터가 성공적으로 들어오면 인증번호 입력란이 활성화되도록*/
			code = data;
			alert('인증번호가 전송되었습니다.')
		},

	}
	);

jsp파일의 id/class를 지정한 이름을 이용해 각각 이메일, 인증번호 변수를 만들고 인증하기 버튼을 클릭하면 ajax를 통해 get방식으로 메일이 전송되도록 했다.

이때 인증 전에는 인증번호 입력란이 비활성화 되어 입력할 수 없는 상태이지만
데이터가 성공적으로 들어온다면(메일로 인증번호가 제대로 전송된다면)
번호 입력란은 활성화되어 입력 가능한 상태가 된다.


📕Controller

  1. 인증번호 생성
  2. 이메일 전송 내용(양식)
  3. 수신 이메일로 인증번호 전송
@Autowired  
	private JavaMailSender mailSender;

의존성 주입을 사용을 위해 @Autowired 을 적고
JavaMailSender 객체 타입인 mailSender 변수를 선언한다.


@RequestMapping(value = "member/mailCheck", method =  RequestMethod.GET )	
	@ResponseBody
	public String mailCheck(String email) throws Exception{ //반환값이 있기에 메서드 타입도 String
		System.out.println("이메일 데이터 전송 확인");  //확인용
		System.out.println("인증 이메일 : " + email);  
		
		
		//인증번호 생성
		Random random = new Random();
		int checkNum = random.nextInt(888888) + 111111;
		System.out.println("인증번호 :"+ checkNum);
		
		
		//이메일 전송 내용
		String setFrom = "@gmail.com"; //발신 이메일
		String toMail = email;         //받는 이메일
		String title = "KeepingBox 회원가입 인증 이메일 입니다.";
		String content = 
						"인증 번호는 " + checkNum + "입니다." + 
						"해당 인증번호를 인증번호 확인란에 기입하여 주세요.";
		//이메일 전송 코드
		try {
			MimeMessage message = mailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
			helper.setFrom(setFrom);
			helper.setTo(toMail);
			helper.setSubject(title);
			helper.setText(content,true);
			mailSender.send(message);
		}catch(Exception e) {
			e.printStackTrace();
		}
		String num = Integer.toString(checkNum); // ajax를 뷰로 반환시 데이터 타입은 String 타입만 가능
		return num; // String 타입으로 변환 후 반환
	}
}

ajax코드가 실행되면 지정한 controller코드가 실행되는데 json통신을 하기위해
무조건 ❗❗❗ @ResponseBody을 써준다.

Random 객체로 난수를 생성해 6자리 숫자의 인증번호를 만들고 이메일 내용을 String 변수에 담아 작성한다.
그 다음 MimeMessage를 이용해 이메일을 전송할 코드를 작성한다.

return으로 받아 생성된 인증번호가 잘 넘어오는지 확인했다.

이메일 전송이 성공하면 console창에 메세지가 뜨고 jsp페이지에도 성공메세지가 alert로 뜬다.
이제 네이버 메일이 잘 왔는지 확인해보자!

오오!! 메세지가 정상적으로 보내졌다. 🎉🎉



📧 인증번호 일치 검사

이메일에 전송돼 발급받은 인증번호를 인증번호란에 입력하면
인증여부를 거쳐 일치할 경우 성공 문구와 함께 입력란이 파란색으로 바뀌고, 불일치할 경우 실패 문구와 함께 입력란이 빨간색으로 변경된다.


📕 코드 작성


📕JS

제이쿼리 문법을 사용했다.

$('.mail-check-input').on('input',function() {
		var inputCode = $(".mail-check-input").val();   /*사용자가 입력한 전송 번호*/
		var checkResult = $("#mail-check-input-info");  /* 비교 결과 */
		
		if (inputCode == code) {                 // 일치할 경우
			checkResult.html("인증번호가 일치합니다.");
			checkResult.attr("class", "correct");
			$(".mail-check-input").css("border","1.5px solid #3781E3");/*일치할 경우 테두리 색 변경*/
			$(".mail-check-input").css("color","#3781E3");/*일치할 경우 글자 색 변경*/
		} else {                                            
			checkResult.html("인증번호를 다시 확인해주세요.");
			checkResult.attr("class", "incorrect");
			$(".mail-check-input").css("border","1.5px solid red");
			$(".mail-check-input").css("color","red");
		}
	});

사용자 입력란과 비교될 div영역을 각 변수로 지정하고
사용자가 입력한 전송 코드가 발급된 인증번호와 일치할 경우 결과 영역에는 성공 문구와 함께 input 테두리 색이 변경된다.

불일치할 경우에는 실패 문구와 함께 역시 input 테두리 색이 변경된다.


프론트도 구현해야돼서 하고 싶은 디자인이나 효과는 일일이 검색하면서 하다보니 예상 구현일보다 시간이 꽤 걸린다.. 🥲 게다가 오류도 계속 터져서 고치느라 애를 먹었지만 잘 보내지니 이제야 속이 시원하네

profile
꾸준히 성장하는 개발자

0개의 댓글