개발/백엔드

멀티캠퍼스 [현대 이지웰] Spring에서는 로그인과 회원가입을 어떻게 사용할 수 있을까?

taecostudy76 2025. 10. 13. 20:00

 

코드 분석

spring에서 제공하는 Spring Security

 

 

@Configuration 어노테이션은 이 클래스가 단순한 클래스가 아니라 Spring의 설정을 담고 있는

특별한 클래스라는 것을 Spring에게 알려주는 어노테이션입니다.

 

@EnableWebSecurity 어노테이션을 통해서 모든 웹 요청은 Sptring Security를 거치게 됩니다.

PasswordEncoder는 비밀번호를 안전하게 보관하기 위한 암호화 도구입니다.

BCryptPasswordEncoder는 암호화 객체입니다.

이 함수를 만들어 사용을 하게 되면 비밀번호를 암호화되게 됩니다. 원래 비밀번호는 무엇이었는지 절대로 다시 알아낼 수 없습니다.

오직 사용자가 로그인 시 입력한 비밀번호가 암호화된 값과 일치하는지만 비교할 수 있게 됩니다.

 

 

HttpSecurity http는 설정하는 객체라고 생각하면 됩니다. 이 객체의 메서드를 연달아 호출하면서 규칙을 하나씩 설정할 수 있습니다.

.csrf(csrf -> csrf.disable())에서 CSRF란

사이트 간 요청 위조 공격 즉, 해커가 다른 사이트에 악성 링크를 심어 두고, 사용자가 그 링크를 클릭하면

사용자의 권한으로 우리 사이트에  원치 않는 요청을 보내는 공격입니다.

저희는 공부하는 목적으로 사용하기 때문에 disable() 함수를 사용하여 사용하지 않는다고 설정했습니다.

하지만 실제 서비스에서는 반드시 활성화해야 합니다.

 

.formLogin(formLogin -> formLogin.disable())에서 formLogin이란

다른 웹사이트가 우리 웹페이지를 <frame>이나 <iframe> 안에 포함시키지 못하게 막는 보안 기능입니다.

이 설정은 다른 사이트에서 우리 페이지를 <iframe>으로 가져다 쓰는 것을 허용하겠다는 설정입니다.

 

 

위 클래스를 사용하기 위해서는 사용할 Service에 @Autowired를 통해서 PasswordEncoder 객체를 주입을 받아 사용하면 됩니다.

 

 

insertMember 함수에서는 pwdEncoder.encode()함수를 사용해서 vo.getMemPwd()를 통해서 사용자가 회원가입 할 때 

작성한 비밀번호를 가져와 암호화를 진행합니다. 그리고 암호화된 데이터 값을 데이터베이스에 저장합니다.

 

pwdEncoder.encode()함수는 실행할 때마다 매번 다른 결과의 암호문을 만들어냅니다. 따라서 같은 "1234"이라도

서로 다른 문자열로 암호화가 진행됩니다. 

 

 

로그인에서는 db에서 입력한 아이디가 있는지 확인을 하고 해당 아이디의 비밀번호를 encodePwd에 저장을 합니다.

if문에서 pwdEncoder.matches() 함수를 통해 사용자가 입력한 비밀번호와 encodePwd가 일치한 지 확인을 하고 id와 비밀번호 모두 

데이터 베이스와 일치하다면 success를 보냅니다.

matches() 함수는  BCrypt의 원리를 이용해, 평문과 암호문이 서로 짝이 맞는지를 내부적으로 비교하여 true 또는 false를 반환합니다.

 

 

궁금증!!

BCrypt의 원리는 무엇일까?

1. 단방향 해시 함수

 

- 원리: BCrypt는 해시를 사용합니다.

해시를 사용하게 되면 비밀번호를 해시값으로 만들 수 있습니다. 하지만 해시값을 가지고 사용자의 비밀번호로 바꿀 수는 없습니다.

2. 솔트(Salt)

 

- 원리: 동일한 비밀번호를 해시하더라도 매번 다른 결과가 나오도록, 해시하기 전에 '솔트'라고 불리는 임의의 데이터를 추가합니다.

만약에 솔트가 없다면 1234라는 비밀번호를 입력했을 때 동일한 해시값으로 변환됩니다. 그래서 같은 1234라도 솔트 값을 다르게 넣어

같은 DB에 저장되는 해시값은 다른 값으로 저장할 수 있습니다.

3. 키 스트레칭(Key Stretching)

 

- 원리: 해시 함수를 수천, 수만 번 반복하여 계산 과정을 의도적으로 느리게 만듭니다.

이 과정이 없다면 요즘 컴퓨터는 성능이 너무 좋아 1초에 수십억 번의 해시 계산을 할 수 있습니다. 해커는 이를 이용해서

무차별 대입 공격으로 비밀번호 조합을 빠르게 해시하여 유출된 해시값과 비교하여 비밀번호를 알아낼 수 있습니다.

 

여기서 또 궁금증!!

그러면 내가 로그인할 때 입력한 비밀번호는 또 다른 해시값으로 만들어져 기존에 가지고 있던 해시값과 달라지지 않을까?

matches() 함수에서 두 개의 파라미터를 받습니다. 비밀번호 평문과 DB에서의 해시값. 

그리고 함수는 사용자의 비밀번호 평문과 솔트 값으로 다시 해시값을 재현합니다. 그리고 재현된 해시값과 DB의 해시값이 같다면 로그인이 성공하게 됩니다.

 

 

위 사진은 해시값입니다.

$를 기준으로 나누게 되면 앞에 2y는 알고리즘, 10은 작업 비용 2^10을 의미합니다.

뒤에 초록색 문자열은 솔트값입니다. 그리고 빨간색 문자열은 해시값입니다.

 

로그인을 할 때 match 함수가 입력한 평문 비밀번호와 솔트 값을 결합하고 작업비용 2^10만큼 똑같이 반복 실행을 하게 됩니다.

그러면 새로운 해시값이 생성이 되는데 이때 비밀번호를 정확하게 입력했다면 같은 해시값이 나오게 됩니다.