DEV Community

dss99911
dss99911

Posted on • Originally published at dss99911.github.io

Spring Security 시작하기 - 기본 설정과 인증

Spring Security는 Spring 기반 애플리케이션의 인증(Authentication)과 인가(Authorization)를 담당하는 강력한 보안 프레임워크입니다. 이 글에서는 기본 설정부터 시작하는 방법을 알아봅니다.

기본 설정

의존성 추가

Spring Security를 사용하려면 의존성만 추가하면 됩니다. 추가하는 것만으로 기본 보안이 활성화됩니다.

Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Gradle:

implementation 'org.springframework.boot:spring-boot-starter-security'
Enter fullscreen mode Exit fullscreen mode

기본 동작

의존성을 추가하면 다음과 같은 기본 동작이 활성화됩니다:

  1. 모든 HTTP 엔드포인트에 인증 필요
  2. 기본 로그인 폼 제공 (/login)
  3. 기본 사용자 생성
    • 사용자 ID: user
    • 비밀번호: 애플리케이션 시작 시 콘솔에 출력
Using generated security password: a1b2c3d4-e5f6-7890-abcd-ef1234567890
Enter fullscreen mode Exit fullscreen mode

이 기본 비밀번호는 개발 환경에서만 사용하세요.

사용자 정의 설정

application.properties에서 기본 사용자 설정

spring.security.user.name=admin
spring.security.user.password=secret
spring.security.user.roles=ADMIN
Enter fullscreen mode Exit fullscreen mode

SecurityFilterChain 설정 (Spring Security 6.x)

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/home", "/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/dashboard")
                .permitAll()
            )
            .logout(logout -> logout
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            );

        return http.build();
    }
}
Enter fullscreen mode Exit fullscreen mode

인메모리 사용자 정의

@Bean
public UserDetailsService userDetailsService() {
    UserDetails user = User.withDefaultPasswordEncoder()
        .username("user")
        .password("password")
        .roles("USER")
        .build();

    UserDetails admin = User.withDefaultPasswordEncoder()
        .username("admin")
        .password("admin")
        .roles("USER", "ADMIN")
        .build();

    return new InMemoryUserDetailsManager(user, admin);
}
Enter fullscreen mode Exit fullscreen mode

withDefaultPasswordEncoder()는 개발 환경용입니다. 운영에서는 BCrypt 등을 사용하세요.

비밀번호 인코딩

BCryptPasswordEncoder 사용

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
Enter fullscreen mode Exit fullscreen mode

비밀번호 인코딩 예시

@Autowired
private PasswordEncoder passwordEncoder;

public void createUser(String username, String rawPassword) {
    String encodedPassword = passwordEncoder.encode(rawPassword);
    // 인코딩된 비밀번호 저장
}
Enter fullscreen mode Exit fullscreen mode

로그아웃 기능

기본 로그아웃 설정

.logout(logout -> logout
    .logoutUrl("/logout")
    .logoutSuccessUrl("/login?logout")
    .invalidateHttpSession(true)
    .deleteCookies("JSESSIONID")
    .permitAll()
)
Enter fullscreen mode Exit fullscreen mode

로그아웃 버튼 (JSP/Thymeleaf)

<form action="/logout" method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    <button type="submit">Logout</button>
</form>
Enter fullscreen mode Exit fullscreen mode

CSRF 보호

Spring Security는 기본적으로 CSRF 보호가 활성화되어 있습니다.

CSRF 토큰 사용

<!-- Thymeleaf -->
<form th:action="@{/login}" method="post">
    <!-- CSRF 토큰 자동 포함 -->
</form>

<!-- JSP -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
Enter fullscreen mode Exit fullscreen mode

REST API에서 CSRF 비활성화

http.csrf(csrf -> csrf.disable());
Enter fullscreen mode Exit fullscreen mode

REST API에서는 주로 JWT 토큰 인증을 사용하므로 CSRF를 비활성화해도 됩니다.

메서드 수준 보안

활성화

@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig {
}
Enter fullscreen mode Exit fullscreen mode

사용 예시

@Service
public class UserService {

    @PreAuthorize("hasRole('ADMIN')")
    public void deleteUser(Long userId) {
        // ADMIN 권한만 실행 가능
    }

    @PreAuthorize("#username == authentication.name")
    public User getProfile(String username) {
        // 본인만 조회 가능
    }
}
Enter fullscreen mode Exit fullscreen mode

참고 자료

결론

Spring Security는 의존성 추가만으로 기본 보안을 제공하며, SecurityFilterChain을 통해 세밀한 설정이 가능합니다. 인증과 인가를 분리하여 관리하고, 비밀번호 인코딩을 반드시 적용하세요. 메서드 수준 보안까지 활용하면 더욱 견고한 보안을 구현할 수 있습니다.


Originally published at https://dss99911.github.io

Top comments (0)