[Java Spring] Spring Security formLogin

khj·2025년 3월 19일

Java

목록 보기
2/10
post-thumbnail

1. formLogin이란?

formLogin은 Spring Security에서 제공하는 폼 기반 로그인 인증 방식이다.
사용자는 아이디와 비밀번호를 입력하여 로그인하며, 인증이 성공하면 보안 컨텍스트(Security Context)에 인증 정보가 저장된다.

기본적으로 Spring Security를 적용하면 /login 경로에서 로그인 폼을 제공하며, 별도 설정 없이도 로그인 기능을 사용할 수 있다.

  1. formLogin 설정 방법
    Spring Boot 2.x까지는 WebSecurityConfigurerAdapter를 사용했지만,
    3.x부터는 SecurityFilterChain을 Bean으로 등록하는 방식으로 변경되었다.

(1) 기본 설정

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .formLogin(Customizer.withDefaults()) // 기본 formLogin 활성화
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        );

    return http.build();
}

이렇게 설정하면 /login 페이지를 기본 제공하며, 인증이 필요한 요청이 있을 경우 로그인 페이지로 자동 리다이렉트된다.


(2) 커스텀 설정

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .formLogin(form -> form
            .loginPage("/custom-login")  // 사용자 정의 로그인 페이지
            .loginProcessingUrl("/login-process") // 로그인 처리 URL
            .usernameParameter("userId") // 사용자 아이디 파라미터 지정
            .passwordParameter("passwd") // 비밀번호 파라미터 지정
            .defaultSuccessUrl("/home", true) // 로그인 성공 시 이동할 페이지
            .failureUrl("/custom-login?error=true") // 로그인 실패 시 이동할 페이지
        )
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        );

    return http.build();
}

3. formLogin 내부 동작 과정

(1) 로그인 요청 처리

사용자가 로그인 버튼을 클릭하면 다음과 같은 과정이 수행된다.

  1. 클라이언트가 POST /login-process 요청을 보냄
  2. UsernamePasswordAuthenticationFilter가 요청을 가로채서 아이디/비밀번호를 추출
  3. AuthenticationManager에게 인증 요청을 전달

(2) 인증 처리 과정

  1. AuthenticationManager는 AuthenticationProvider를 사용하여 인증 진행
  2. AuthenticationProvider는 UserDetailsService를 통해 사용자 정보를 조회
  3. 입력한 비밀번호를 PasswordEncoder로 비교
  4. 인증이 성공하면 SecurityContext에 저장
  5. 인증 실패 시 AuthenticationFailureHandler가 동작하며, 기본적으로 /login?error로 리다이렉트된다.

(3) 인증 성공 후 동작

  1. 인증이 성공하면 AuthenticationSuccessHandler가 실행됨
  2. 기본적으로 요청한 페이지 또는 defaultSuccessUrl()에서 지정한 페이지로 이동

4. 커스텀 로그인 구현 예제

(1) 로그인 폼 페이지 (login.html)

<form action="/login-process" method="post">
    <input type="text" name="userId" placeholder="아이디">
    <input type="password" name="passwd" placeholder="비밀번호">
    <button type="submit">로그인</button>
</form>

(2) 사용자 정보 조회 (UserDetailsService 구현)

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // DB에서 사용자 정보 조회
        return User.withUsername(username)
            .password(new BCryptPasswordEncoder().encode("password")) // 테스트용 비밀번호
            .roles("USER")
            .build();
    }
}

(3) 로그인 성공/실패 핸들러 커스텀

@Component
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException {
        response.sendRedirect("/home");
    }
}

@Component
public class CustomLoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException {
        response.sendRedirect("/login?error=true");
    }
}

(4) 커스텀 핸들러 적용

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .formLogin(form -> form
            .loginPage("/custom-login")
            .loginProcessingUrl("/login-process")
            .successHandler(customLoginSuccessHandler)
            .failureHandler(customLoginFailureHandler)
        )
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        );

    return http.build();
}
profile
Spring, Django 개발 블로그

0개의 댓글