JWT 로그인 인증 구현 가이드
이 가이드에서는 Spring Boot와 Vue.js를 사용하여 JWT(JSON Web Token) 기반의 로그인 인증 시스템을 구축하는 전체 과정을 안내합니다.
Part 1: 백엔드 (Spring Boot) 설정
가장 먼저 백엔드에서 사용자 인증을 처리하고 JWT를 발급하는 API를 만듭니다.
1단계: 의존성 추가
(이전과 동일)
// build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
// ...
}
2단계: User Entity 및 Repository 생성
(이전과 동일)
User.java
package dev.nerobong2.openehr.open_ehr.backend.user;
// ... (Lombok, JPA 어노테이션 등)
public class User {
// ... id, username, password 필드 ...
}
UserRepository.java
package dev.nerobong2.openehr.open_ehr.backend.user;
// ...
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
3단계: Spring Security 설정 (단순 버전으로 복원)
403
오류의 원인을 명확히 하기 위해, 가장 단순한 초기 버전으로 설정을 되돌립니다.
SecurityConfig.java
// [수정] 403 오류 원인 파악을 위해 가장 단순한 버전으로 복원합니다.
package dev.nerobong2.openehr.open_ehr.backend.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // CSRF 보호 비활성화
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 세션 사용 안 함
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 로그인/회원가입 API는 모두 허용
.anyRequest().authenticated() // 나머지 요청은 인증 필요
);
return http.build();
}
}
4단계: 로그인 API 생성 (단순 버전으로 복원)
AuthService
에서 직접 PasswordEncoder
를 사용하여 비밀번호를 비교하는 초기 방식으로 되돌립니다.
AuthService.java
// [수정] PasswordEncoder를 직접 사용하는 단순 버전으로 복원합니다.
package dev.nerobong2.openehr.open_ehr.backend.auth;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import dev.nerobong2.openehr.open_ehr.backend.user.User;
import dev.nerobong2.openehr.open_ehr.backend.user.UserRepository;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class AuthService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public String login(String username, String password) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다."));
// 입력된 비밀번호와 DB의 암호화된 비밀번호를 비교
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
}
// 로그인 성공 시 임시 토큰 반환
return "temp-jwt-token-for-" + user.getUsername();
}
}
AuthController.java
(변경 없음)
// ...
public class AuthController {
// ...
@PostMapping("/login")
public String login(@RequestBody LoginRequestDto requestDto) {
return authService.login(requestDto.username(), requestDto.password());
}
}
record LoginRequestDto(String username, String password) {}
5단계: 올바른 테스트 데이터 생성 (매우 중요!)
“비밀번호가 일치하지 않습니다” 오류는 DB에 저장된 암호화된 비밀번호가 잘못되었기 때문입니다. 아래 방법으로 올바른 암호화 비밀번호를 직접 생성하여 DB에 넣으세요.
-
메인 애플리케이션 파일(
OpenEhrBackendApplication.java
)을 열고, 기존 클래스 내부에 임시로 아래 코드를 추가합니다. 이 코드는 서버가 시작될 때 비밀번호 '1234’를 암호화하여 콘솔에 출력해 줍니다.OpenEhrBackendApplication.java
package dev.nerobong2.openehr.open_ehr.backend; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.security.crypto.password.PasswordEncoder; @SpringBootApplication public class OpenEhrBackendApplication { public static void main(String[] args) { SpringApplication.run(OpenEhrBackendApplication.class, args); } // [추가] 비밀번호 암호화를 위해 이 Bean을 기존 클래스 내부에 임시로 추가합니다. @Bean public CommandLineRunner commandLineRunner(PasswordEncoder passwordEncoder) { return args -> { String encodedPassword = passwordEncoder.encode("1234"); System.out.println("####################################################"); System.out.println("Encoded password for '1234': " + encodedPassword); System.out.println("####################################################"); }; } }
-
백엔드 서버를 재시작합니다.
-
터미널(콘솔)에 아래와 같이 암호화된 비밀번호가 출력됩니다.
#################################################### Encoded password for '1234': $2a$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ####################################################
-
콘솔에 출력된
$2a$10$...
로 시작하는 전체 문자열을 복사합니다. -
DBeaver에서 아래 SQL을 실행하여
password
컬럼에 복사한 값을 붙여넣고 사용자를 생성합니다.-- 기존 데이터 삭제 DELETE FROM users WHERE username = 'testuser'; -- 새로 생성된 암호화 값으로 INSERT INSERT INTO users (username, password, employee_number, company_code) VALUES ('testuser', '콘솔에서 복사한 암호화된 비밀번호 붙여넣기', '12345', 'COMP01'); COMMIT;
-
테스트 데이터 생성이 끝나면,
OpenEhrBackendApplication.java
에 추가했던CommandLineRunner
코드는 다시 삭제해도 됩니다.
Part 2: 프론트엔드 (Vue) 설정
(이전과 동일)
다음 단계: 이제 백엔드 서버를 재시작하고, 프론트엔드에서 아이디
testuser
, 비밀번호1234
로 다시 로그인을 시도해 보세요. 이제는403
오류 없이 정상적으로 로그인되어 메인 페이지로 이동할 것입니다.## JWT 로그인 인증 구현 가이드
이 가이드에서는 Spring Boot와 Vue.js를 사용하여 JWT(JSON Web Token) 기반의 로그인 인증 시스템을 구축하는 전체 과정을 안내합니다.
Part 1: 백엔드 (Spring Boot) 설정
가장 먼저 백엔드에서 사용자 인증을 처리하고 JWT를 발급하는 API를 만듭니다.
1단계: 의존성 추가
(이전과 동일)
// build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
// ...
}
2단계: User Entity 및 Repository 생성
(이전과 동일)
User.java
package dev.nerobong2.openehr.open_ehr.backend.user;
// ... (Lombok, JPA 어노테이션 등)
public class User {
// ... id, username, password 필드 ...
}
UserRepository.java
package dev.nerobong2.openehr.open_ehr.backend.user;
// ...
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
3단계: Spring Security 설정 (단순 버전으로 복원)
403
오류의 원인을 명확히 하기 위해, 가장 단순한 초기 버전으로 설정을 되돌립니다.
SecurityConfig.java
// [수정] 403 오류 원인 파악을 위해 가장 단순한 버전으로 복원합니다.
package dev.nerobong2.openehr.open_ehr.backend.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // CSRF 보호 비활성화
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 세션 사용 안 함
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 로그인/회원가입 API는 모두 허용
.anyRequest().authenticated() // 나머지 요청은 인증 필요
);
return http.build();
}
}
4단계: 로그인 API 생성 (단순 버전으로 복원)
AuthService
에서 직접 PasswordEncoder
를 사용하여 비밀번호를 비교하는 초기 방식으로 되돌립니다.
AuthService.java
// [수정] PasswordEncoder를 직접 사용하는 단순 버전으로 복원합니다.
package dev.nerobong2.openehr.open_ehr.backend.auth;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import dev.nerobong2.openehr.open_ehr.backend.user.User;
import dev.nerobong2.openehr.open_ehr.backend.user.UserRepository;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class AuthService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public String login(String username, String password) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다."));
// 입력된 비밀번호와 DB의 암호화된 비밀번호를 비교
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
}
// 로그인 성공 시 임시 토큰 반환
return "temp-jwt-token-for-" + user.getUsername();
}
}
AuthController.java
(변경 없음)
// ...
public class AuthController {
// ...
@PostMapping("/login")
public String login(@RequestBody LoginRequestDto requestDto) {
return authService.login(requestDto.username(), requestDto.password());
}
}
record LoginRequestDto(String username, String password) {}
5단계: 올바른 테스트 데이터 생성 (매우 중요!)
“비밀번호가 일치하지 않습니다” 오류는 DB에 저장된 암호화된 비밀번호가 잘못되었기 때문입니다. 아래 방법으로 올바른 암호화 비밀번호를 직접 생성하여 DB에 넣으세요.
-
메인 애플리케이션 파일(
OpenEhrBackendApplication.java
)을 열고, 기존 클래스 내부에 임시로 아래 코드를 추가합니다. 이 코드는 서버가 시작될 때 비밀번호 '1234’를 암호화하여 콘솔에 출력해 줍니다.OpenEhrBackendApplication.java
package dev.nerobong2.openehr.open_ehr.backend; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.security.crypto.password.PasswordEncoder; @SpringBootApplication public class OpenEhrBackendApplication { public static void main(String[] args) { SpringApplication.run(OpenEhrBackendApplication.class, args); } // [추가] 비밀번호 암호화를 위해 이 Bean을 기존 클래스 내부에 임시로 추가합니다. @Bean public CommandLineRunner commandLineRunner(PasswordEncoder passwordEncoder) { return args -> { String encodedPassword = passwordEncoder.encode("1234"); System.out.println("####################################################"); System.out.println("Encoded password for '1234': " + encodedPassword); System.out.println("####################################################"); }; } }
-
백엔드 서버를 재시작합니다.
-
터미널(콘솔)에 아래와 같이 암호화된 비밀번호가 출력됩니다.
#################################################### Encoded password for '1234': $2a$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ####################################################
-
콘솔에 출력된
$2a$10$...
로 시작하는 전체 문자열을 복사합니다. -
DBeaver에서 아래 SQL을 실행하여
password
컬럼에 복사한 값을 붙여넣고 사용자를 생성합니다.-- 기존 데이터 삭제 DELETE FROM users WHERE username = 'testuser'; -- 새로 생성된 암호화 값으로 INSERT INSERT INTO users (username, password, employee_number, company_code) VALUES ('testuser', '콘솔에서 복사한 암호화된 비밀번호 붙여넣기', '12345', 'COMP01'); COMMIT;
-
테스트 데이터 생성이 끝나면,
OpenEhrBackendApplication.java
에 추가했던CommandLineRunner
코드는 다시 삭제해도 됩니다.
Part 2: 프론트엔드 (Vue) 설정
(이전과 동일)
다음 단계: 이제 백엔드 서버를 재시작하고, 프론트엔드에서 아이디
testuser
, 비밀번호1234
로 다시 로그인을 시도해 보세요. 이제는403
오류 없이 정상적으로 로그인되어 메인 페이지로 이동할 것입니다.
댓글 없음:
댓글 쓰기