본문 바로가기
Java/Spring Boot

[Spring Boot] 리액트 네이티브 bcrypt를 이용해서 암호화 검증하기

by 산코디 2023. 7. 10.

 

안녕하세요!

오늘은 이전에 포스팅한 "리액트네이티브로 bcrypt 암호화하기"에 이어서, 서버 측(Spring Boot)에서 암호화된 입력값을 받아 검증하는 방법에 대해 알아보려고 합니다.

 

일반적으로 JSP, Thymeleaf와 같은 경우 Spring Security를 사용하여 로그인 검증을 처리하는 것이 간단하지만, 최근에는 frontend와 backend를 분리한 SPA(Single-Page Application)와 같은 개발 패턴이 많이 사용됩니다. 이런 경우에는 로그인 정보를 암호화하여 서버 측으로 전달해야 합니다. 물론, JSP나 Thymeleaf와 같은 방식에서도 상황에 따라 암호화 처리를 하여 전달할 수도 있습니다.

 

이제 Spring Boot에서 bcrypt를 사용하여 로그인 검증을 어떻게 처리하는지 예제를 통해 하나씩 살펴보도록 하겠습니다.


(앞서 설명한 내용을 참고하여 자연스럽게 문장을 표현하였습니다. 예제를 통해 진행할 것이라고 언급하였으므로, 다음 단락에서는 예제를 구체적으로 소개하면 됩니다.)

 


1. Controller 예시 코드

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.test.prj.auth.service.AuthService;
import com.test.prj.model.Member;

/**
 * 사용자 인증 정보 Controller
 *
 */
@RestController
@RequestMapping("/rest/auth")
public class AuthController {

	@Autowired
	private AuthService authService;
	
	/**
	 * 사용자 로그인 인증 조회 Controller
	 * 
	 * @param member
	 * @return
	 */
	@PostMapping("/login")
	public Map<String, Object> login(Member member) {
		return authService.login(member);
	}
}

위의 소스 코드는 사용자 인증 정보를 처리하는 AuthController 클래스입니다. 해당 코드는 Spring MVC의 컨트롤러 역할을 수행하고 있습니다. 

 

* 상세 설명
1. AuthController 클래스에는 /rest/auth 경로에 매핑되는 요청을 처리하는 메서드들이 정의되어 있습니다.
2. AuthService 인터페이스를 주입받아 authService를 사용할 수 있도록 @Autowired 어노테이션을 이용하여 의존성 주입을 수행합니다.
3. /rest/auth/login 경로로 POST 요청이 오면 login() 메서드가 실행됩니다.
4. login() 메서드는 Member 객체를 매개변수로 받아서 authService의 login() 메서드를 호출하고 그 결과를 반환합니다.
5. 반환된 결과는 Map<String, Object> 형태로 클라이언트에게 전달됩니다.

 

 

해당 예시 코드는 사용자 인증 정보를 처리하는 컨트롤러로, /rest/auth/login 경로로 POST 요청이 오면 해당 요청을 처리하여 사용자의 로그인 인증 정보를 조회하고, authService의 login() 메서드를 호출하여 처리 결과를 반환합니다. 이렇게 구현된 컨트롤러를 통해 클라이언트에서 로그인 요청을 보내고, 서버는 해당 요청을 처리하여 인증 정보를 반환합니다.

 

 


2. service interface 예시 코드

import java.util.Map;
import com.test.prj.model.Member;

/**
 * 사용자 인증 정보 Service
 *
 */
public interface AuthService {

	/**
	 * 로그인 인증 정보
	 * 
	 * @param member
	 * @return
	 */
	public Map<String, Object> login(Member member);
}

위의 소스 코드는 AuthService라는 인터페이스를 정의하는 코드입니다. 해당 코드는 사용자 인증 정보를 처리하는 서비스를 정의하고 있습니다.

 

* 상세 설명
1. AuthService 인터페이스는 login() 메서드를 정의하고 있습니다.
2. login() 메서드는 Member 객체를 매개변수로 받아서 사용자의 로그인 인증 정보를 처리합니다.
3. login() 메서드는 Map<String, Object> 타입의 결과를 반환합니다. 이 결과는 사용자 인증 정보에 대한 성공 여부 및 추가적인 정보를 담을 수 있는 맵 형태로 반환됩니다.

 

 


3. service implement 예시 코드

import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.test.prj.auth.service.AuthService;
import com.test.prj.model.Member;
import com.test.prj.model.mapper.MemberMapper;
import com.test.prj.util.ResponseUtil;

/**
 * 사용자 인증 정보 Service implements
 * 
 */
@Service
public class AuthServiceImpl implements AuthService {

	@Autowired
	private MemberMapper memberMapper;
	
	/**
	 * 사용자 비밀번호 조회
	 * 
	 */
	@Override
	public Map<String, Object> getPassword(Member member) {
		Map<String, Object> resultMap = ResponseUtil.successMap();
		
		try {
        		// 로그인 정보 조회
			Member serverMember = memberMapper.select(member);
            
            	// 서버측의 비밀번호와 클라이언트측의 암호화된 비밀번호 비교
			boolean isMatch = BCrypt.checkpw(serverMember.getMemberPassword(), member.getMemberPassword());
			
            	// 비밀번호 일치
			if (isMatch) {
				System.out.println("비밀번호 일치");
				resultMap.put("isAuth", true);
                
            	// 비밀번호 불일치
			} else {
				System.out.println("비밀번호 불일치");
				resultMap.put("isAuth", false);
			}
			
		} catch (Exception e) {
			resultMap = ResponseUtil.failureMap();
		}
		
		return resultMap;
	}

위의 소스 코드는 Spring Boot에서 사용자 인증 정보를 처리하는 AuthService의 구현체인 AuthServiceImpl입니다. 해당 코드는 사용자의 비밀번호를 검증하는 기능을 포함하고 있습니다.

 

* 상세 설명

1. MemberMapper를 주입받아 데이터베이스에서 사용자 정보를 조회합니다.
2. 조회한 서버의 비밀번호(serverMember.getMemberPassword())와 클라이언트에서 전달받은 암호화된 비밀번호(member.getMemberPassword())를 비교합니다.
3. BCrypt.checkpw() 메서드를 사용하여 비밀번호를 비교하고, 비밀번호가 일치하는지 여부를 확인합니다.
비밀번호가 일치하면 "비밀번호 일치" 메시지를 출력하고, 비밀번호가 일치하지 않으면 "비밀번호 불일치" 메시지를 출력합니다.
4. 결과를 resultMap에 저장하여 클라이언트에게 반환합니다.
5. 이 코드는 BCrypt 암호화 라이브러리를 사용하여 비밀번호를 검증하는 예시입니다. BCrypt.checkpw() 메서드를 통해 서버 측의 비밀번호와 클라이언트 측의 암호화된 비밀번호를 비교하여 일치 여부를 확인합니다. 결과는 isAuth라는 키로 resultMap에 저장되어 클라이언트에게 반환됩니다.


4. mapper interface 예시 코드

package com.test.prj.model.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.test.prj.model.Member;

/**
 * 사용자 정보 Mapper
 *
 */
@Mapper
public interface MemberMapper {

	/**
	 * 사용자 정보 조회
	 * 
	 * @param member
	 * @return
	 */
	public Member select(Member member);
}

위의 소스 코드는 사용자 정보를 조회하는 MemberMapper 인터페이스입니다. 해당 코드는 MyBatis의 Mapper 어노테이션을 이용하여 사용자 정보에 접근하는 매퍼 클래스임을 나타내고 있습니다.

 

* 상세 설명
1. MemberMapper 인터페이스에는 @Mapper 어노테이션이 붙어 있어 MyBatis에서 사용되는 매퍼 인터페이스임을 나타냅니다.
2. select() 메서드는 Member 객체를 매개변수로 받아서 해당 사용자의 정보를 조회합니다.
3. 조회한 사용자 정보를 Member 객체로 반환합니다.
4. MemberMapper 인터페이스는 MyBatis에서 해당 인터페이스의 구현체를 자동으로 생성하여 사용합니다.


위의 예시 코드는 MyBatis를 사용하여 데이터베이스에 접근하고 사용자 정보를 조회하는 Mapper interface 입니다. 

 


5. mapper XML 예시 코드

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.prj.model.mapper.MemberMapper">

	<!-- 
		사용자 로그인 정보 조회
	 -->
	<select id="select" parameterType="member" resultType="member">
		SELECT
			MemberIdx		,
			MemberId 		,
			MemberPassword	,
			MemberName
		  FROM Member
		 WHERE MemberId = #{memberId}
	</select>
	
</mapper>

위의 소스 코드는 MyBatis의 XML Mapper 파일로, 사용자 정보를 조회하는 쿼리가 정의되어 있습니다. 

 

* 상세 설명
1. <select> 태그는 사용자 로그인 정보를 조회하는 쿼리를 정의합니다.
2. SELECT 문을 통해 Member 테이블에서 MemberId를 기준으로 사용자 정보를 조회합니다.

 


6. React-Native login 페이지 예시 코드

import React, { useState } from 'react';
import { View, Text, TextInput, Button } from 'react-native';
import axios from 'axios';
import bcrypt from 'react-native-bcrypt';

const LoginScreen = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = async () => {
    try {
      // 비밀번호를 bcrypt로 암호화
      const hashedPassword = await bcrypt.hash(password, 10);

      // 서버로 전송할 데이터 객체 생성
      const data = {
        username: username,
        password: hashedPassword,
      };

      // 서버에 로그인 요청
      const response = await axios.post('http://localhost/rest/auth/login', data);

      // 응답 데이터 처리
      if (response.data.isAuth) {
        console.log('로그인 성공');
      } else {
        console.log('로그인 실패');
      }
    } catch (error) {
      // 요청 실패 시 처리할 로직
      console.log('로그인 요청 실패', error);
    }
  };

  return (
    <View>
      <Text>로그인 화면</Text>
      <TextInput
        placeholder="사용자명"
        value={username}
        onChangeText={(text) => setUsername(text)}
      />
      <TextInput
        placeholder="비밀번호"
        secureTextEntry
        value={password}
        onChangeText={(text) => setPassword(text)}
      />
      <Button title="로그인" onPress={handleLogin} />
    </View>
  );
};

export default LoginScreen;

위의 코드는 React-Native측에서 비밀번호를 bcrypt로 암호화하여 서버로 전송하는 로그인 페이지를 구현한 예시 코드입니다.

 

* 상세 설명
1. react-native-bcrypt 라이브러리를 사용하여 비밀번호를 bcrypt로 암호화합니다.
2. 사용자명과 암호화된 비밀번호를 서버로 전송하기 위해 데이터 객체를 생성합니다.
3. axios를 사용하여 서버에 로그인 요청을 보냅니다.
4. 서버로부터 받은 응답 데이터를 처리하여 로그인 성공 또는 실패에 따라 적절한 로직을 수행합니다.

 


최종 정리

지금까지 Spring Boot와 React Native를 사용하여 bcrypt를 이용한 로그인 검증 방법에 대해 알아보았습니다.

Spring Boot에서는 bcrypt 라이브러리를 사용하여 간단하게 암호화된 비밀번호를 비교하고, React Native에서는 bcrypt를 통해 비밀번호를 안전하게 서버로 전송하는 방법을 살펴보았습니다.

Spring이나 Spring Boot와 같은 Java 프레임워크를 사용하면 서버 측의 디자인 패턴을 비교적 쉽게 개발할 수 있을 것입니다. 그러나 최근의 웹 애플리케이션 개발은 SPA를 활용하는 방식으로 많이 변화하고 있습니다. 이런 변화에 따라 React Native를 통해 점진적으로 스킬을 키워가는 것은 많은 도움이 될 것입니다.

개발자분들이 웹 애플리케이션 개발에 익숙하신 분이라면, 이러한 전환 과정에서 React Native를 활용하여 모바일 애플리케이션을 개발하는 것이 큰 도움이 될 것입니다. 이를 통해 보다 많은 사용자들에게 접근할 수 있고, React Native의 강력한 기능과 생산성을 경험할 수 있을 것입니다.

앞으로도 계속해서 React Native와 Spring Boot를 활용한 다양한 개발 방법들을 정리하여 포스팅하도록 하겠습니다.

 

 

감사합니다.

 

 

* [리액트 네이티브] 로그인 페이지 Bcrypt 암호화하기 

https://sancode.tistory.com/113

 

[리액트 네이티브] 로그인 페이지 Bcrypt 암호화 하기

안녕하세요! 오늘은 리액트 네이티브에서 로그인 페이지를 개발할 때 Bcrypt 암호화 기술을 활용한 암호화 처리 방법에 대해 포스팅하려고 합니다. 보안은 소프트웨어에서 로그인 기능을 구현할

sancode.tistory.com

 

 

 

반응형

 

반응형