이번 강좌에서는 현대 웹 애플리케이션에서 사용자가 애플리케이션에 접근할 수 있도록 하기 위한 인증(Authentication) 및 인가(Authorization) 기능을 다룰 것입니다. 특히 스프링 부트와 스프링 시큐리티를 활용하여 사용자 로그인, 로그아웃, 회원 가입 기능을 구현합니다. 이 과정은 실제 웹 서비스에서 자주 사용되는 기본적인 기능들을 포함하여, 보안이 얼마나 중요한지를 이해하는 데에도 큰 도움이 될 것입니다.
목차
1. 스프링 부트 개요
스프링 부트는 스프링 프레임워크의 확장으로써, 신속한 개발을 가능하게 하기 위해 설계되었습니다. 복잡한 설정 없이 애플리케이션을 손쉽게 시작할 수 있도록 도와주며, 스프링 부트 공식 사이트에서 제공하는 스타터 패키지를 통해 필요한 라이브러리를 간편하게 추가할 수 있습니다.
왜 스프링 부트를 사용할까요? 스프링 부트의 가장 큰 장점 중 하나는 의존성 관리입니다. 다양한 라이브러리를 포함하고 있는 pom.xml
파일을 구성하기만 하면 필요에 따라 필요한 의존성을 자동으로 다운로드 받을 수 있습니다. 간단하게 설정하고 여러분의 아이디어를 구현하는 데 집중하세요.
2. 스프링 시큐리티 소개
스프링 시큐리티는 애플리케이션의 인증 및 인가를 담당하는 강력한 프레임워크입니다. 스프링 시큐리티를 사용하면 다음과 같은 기능들을 손쉽게 구현할 수 있습니다:
- 사용자 인증: 아이디와 비밀번호를 통한 로그인 기능
- 인증된 사용자에 대한 권한 부여
- CSRF 방지
- 세션 관리
스프링 시큐리티는 그 자체로도 매우 강력하지만, 스프링 부트와 통합하여 더 많은 장점을 누릴 수 있습니다. 빠르고 간편하게 설정할 수 있으며, 보안 문제를 더 쉽게 관리할 수 있습니다.
3. 프로젝트 설정
스프링 부트를 사용하여 새로운 웹 애플리케이션을 생성합니다. 아래 단계에 따라 프로젝트를 설정하세요.
3.1. 스프링 이니셜라이저 이용하기
스프링 이니셜라이저(start.spring.io)를 사용하여 새로운 스프링 부트 프로젝트를 생성할 수 있습니다. 다음 의존성을 선택하세요:
- Spring Web
- Spring Security
- Spring Data JPA
- H2 Database
3.2. 프로젝트 코드 구조
프로젝트를 생성한 후, 다음과 같은 기본 코드 구조를 유지합니다:
src ├── main │ ├── java │ │ └── com │ │ └── example │ │ └── demo │ │ ├── DemoApplication.java │ │ ├── config │ │ │ └── SecurityConfig.java │ │ ├── controller │ │ │ └── UserController.java │ │ ├── model │ │ │ └── User.java │ │ └── repository │ │ └── UserRepository.java │ └── resources │ ├── application.properties │ └── templates └── test
4. 회원 가입 구현
회원 가입 기능을 구현하기 위해 User
모델과 UserRepository
를 정의한 후, 회원 가입을 처리할 UserController
를 만들어보겠습니다.
4.1. User 모델 정의
package com.example.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
private String password;
// Getter와 Setter 생략
}
4.2. UserRepository 인터페이스 구현
package com.example.demo.repository;
import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository {
User findByUsername(String username);
}
4.3. UserController 구현
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
@RequestMapping("/signup")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping
public String showSignupForm() {
return "signup"; // signup.html
}
@PostMapping
public String registerUser(@Valid User user) {
userRepository.save(user);
return "redirect:/login"; // 가입 후 로그인 페이지로 리다이렉트
}
}
4.4. 회원 가입 HTML 폼 생성
resources/templates/signup.html
파일을 생성하고 다음과 같이 작성합니다.
회원 가입
회원 가입
5. 로그인 및 로그아웃 구현
이제 사용자가 로그인할 수 있도록 스프링 시큐리티를 설정합니다. 인증 로직을 처리하고, 로그인 후 리다이렉션할 대상을 설정합니다.
5.1. SecurityConfig 클래스 설정
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup").permitAll() // 회원 가입 페이지는 모두 접근 가능
.anyRequest().authenticated() // 그 외 요청은 인증 필요
.and()
.formLogin()
.loginPage("/login") // 사용자 정의 로그인 페이지
.permitAll()
.and()
.logout()
.permitAll();
}
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
5.2. 로그인 페이지 생성
resources/templates/login.html
파일을 생성하여 사용자 정의 로그인 페이지를 추가합니다.
로그인
로그인
6. 로그아웃 메서드 추가하기
로그아웃 기능은 스프링 시큐리티에서 기본적으로 제공되지만, 추가적인 커스터마이징이 필요할 수 있습니다. 로그아웃 시킬 URL과 로그아웃 후 리다이렉션할 URL을 설정합니다.
6.1. 로그아웃 URL 설정
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/logout") // 로그아웃 URL
.logoutSuccessUrl("/login?logout") // 로그아웃 성공 시 리다이렉트할 URL
.invalidateHttpSession(true) // 세션 무효화
.clearAuthentication(true); // 인증 정보 지우기
}
}
6.2. 로그아웃 버튼 추가
로그인을 한 후에는 로그아웃 버튼을 추가하여 쉽게 로그아웃할 수 있도록 합시다. resources/templates/index.html
에서 다음과 같이 추가합니다.
환영합니다!