[SpringBoot3] 로그인 페이지 실습 1

[개발환경]
M2 OSX Ventura 13.2.1
VS Code
SpringBoot 3.0.2
OpenJDK 17
Gradle 7.6
[Docker]
 - mysql:latest

들어가며

SpringBoot3에서 Spring Session과 JWT를 이용한 인증, 인가 로직을 구현하고 발생할 수 있는 취약점을 분석한다.

Spring Session과 JWT는 둘 다 스프링 부트 애플리케이션에서 인증과 세션 관리를 위해 사용될 수 있지만, 서로 다른 방식으로 작동한다.

Spring Session은 세션 데이터를 저장하기 위한 다양한 저장소(예: Redis, MongoDB, JDBC 등)를 지원하며, 서버 측에서 세션을 관리한다. Spring Security와 함께 사용할 때, Spring Session은 인증 및 권한 부여에 필요한 데이터를 저장하고 관리할 수 있다. Spring Session은 세션 관리를 위해 쿠키를 사용할 수도 있지만, 이 방법은 쿠키를 지원하지 않는 API(예: 모바일 앱)에서는 작동하지 않는다.

반면에 JWT는 서버와 클라이언트 간의 인증에 사용되며, 클라이언트에서 토큰을 생성하고 서버에서 검증한다. JWT는 사용자 정보와 권한 정보를 포함할 수 있으며, 서버 측에서 세션을 저장하거나 관리하지 않는다. JWT는 토큰을 사용하기 때문에, 서버와 클라이언트 간의 통신에서 매번 인증 정보를 전송해야 할 필요 없이 토큰만을 전송하여 인증할 수 있다.

따라서, Spring Session은 서버 측에서 세션을 관리하고 다양한 저장소를 지원하며, Spring Security와 함께 사용하여 권한 부여에 필요한 데이터를 관리한다. 반면에 JWT는 클라이언트 측에서 인증 정보를 생성하고 서버 측에서 인증 정보를 검증하며, 세션을 저장하거나 관리하지 않는다.

Spring Session

Spring Session은 서버 측에서 세션을 관리하고 인증, 인가를 수행하는 기능을 제공한다.

서버 측에서의 인증과 인가는 Spring Security를 사용하여 구현할 수 있다. Spring Security는 인증(Authentication)과 인가(Authorization)를 지원하는 프레임워크로, 사용자 인증, 권한 부여, 접근 제어 등의 기능을 제공한다.

인증(Authentication)은 사용자가 신원을 증명하여 자신이 누구인지 확인하는 과정이다. Spring Security에서는 사용자 인증을 위해 다양한 인증 방법을 지원한다. 예를 들어, 기본적으로 제공되는 폼 기반 인증(Form-based Authentication)을 사용하여 사용자의 아이디와 비밀번호를 검증하거나, 소셜 로그인(Social Login)을 통해 사용자를 인증할 수 있다.

인가(Authorization)는 인증된 사용자가 특정 자원에 접근할 권한이 있는지 확인하는 과정이다. Spring Security에서는 권한 부여를 위해 Access Control List(ACL)이나 Role-based Access Control(RBAC)과 같은 다양한 방식을 지원한다.

구현

폼 기반 로그인 페이지에서 간단한 인증을 구현한다. 사용자 아이디와 패스워드를 검증하고, 로그인 성공 시 세션에 사용자 정보를 저장한다.

의존성 [build.gradle]

dependencies{
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.session:spring-session-data-redis'
    implementation 'org.springframework.boot:spring-boot-starter-security'
}

Redis를 사용하여 세션 저장 [RedisConfiguration.java]

@Configuration
@EnableRedisHttpSession
public class RedisConfiguration {
    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }
}

로그인 처리 [LoginController.java]

@Controller
public class LoginController {
    @GetMapping("/login")
    public String login() {
        return "login";
    }
    
    @PostMapping("/login")
    public String doLogin(@RequestParam String username, @RequestParam String password, HttpSession session) {
        // 사용자 아이디와 비밀번호를 검증하는 로직
        if ("user".equals(username) && "password".equals(password)) {
            // 인증 성공 시 세션에 사용자 정보를 저장
            session.setAttribute("username", username);
            return "redirect:/home";
        } else {
            // 인증 실패 시 로그인 화면으로 이동
            return "redirect:/login";
        }
    }
}

인증 이후 페이지 [HomeController.java]

@Controller
public class HomeController {
    @GetMapping("/home")
    public String home(HttpSession session) {
        // 세션에서 사용자 정보를 가져옴
        String username = (String) session.getAttribute("username");
        // 사용자 정보가 없으면 로그인 화면으로 이동
        if (username == null) {
            return "redirect:/login";
        }
        // 사용자 정보가 있으면 홈 페이지로 이동
        return "home";
    }
}

사용자 아이디가 'user'이고 패스워드가 'password'인 경우 로그인에 성공하고 /home 페이지로 이동한다.

 

참고

점프 투 스프링부트(https://wikidocs.net/book/7601)

JWT&Spring Security(https://brunch.co.kr/@springboot/491)

ChatGPT

반응형