반응형

전자정부프레임워크Spring Security를 사용하여 인증 관련 로그를 관리하는 방법을 배웁니다.
인증 로그 관리는 보안 모니터링 및 감사 추적(Audit Trail)에 필수적이며, 사용자 활동을 기록해 보안을 강화할 수 있습니다.


1. 인증 로그 관리의 필요성

1-1. 인증 로그란?

  • 사용자 로그인 및 로그아웃 기록.
  • 실패한 로그인 시도.
  • 권한 부족으로 인한 요청 거부 기록.

1-2. 인증 로그 관리의 중요성

  • 보안 사고 발생 시 로그 분석 가능.
  • 사용자 활동 추적을 통한 이상 행위 감지.
  • 보안 정책 준수 확인.

2. 인증 로그 관리 구현 계획

2-1. 요구사항 정의

  1. 모든 인증 이벤트를 기록.
  2. 성공 및 실패 이벤트를 분리하여 저장.
  3. 로그를 DB 또는 파일로 저장.
  4. 관리자 화면에서 로그를 조회 가능하도록 API를 제공.

2-2. 구현 흐름

  1. AuthenticationSuccessHandlerAuthenticationFailureHandler 구현.
  2. Spring Security 설정에서 핸들러 등록.
  3. 로그 데이터를 DB에 저장하는 서비스 구현.

3. 구현 코드

3-1. 성공 및 실패 핸들러 작성

성공 핸들러

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private final AuthenticationLogService logService;

    public CustomAuthenticationSuccessHandler(AuthenticationLogService logService) {
        this.logService = logService;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        String username = authentication.getName();
        logService.logSuccess(username, request.getRemoteAddr());
        response.sendRedirect("/dashboard");
    }
}

실패 핸들러

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private final AuthenticationLogService logService;

    public CustomAuthenticationFailureHandler(AuthenticationLogService logService) {
        this.logService = logService;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        String username = request.getParameter("username");
        logService.logFailure(username, request.getRemoteAddr(), exception.getMessage());
        response.sendRedirect("/login?error");
    }
}

3-2. 로그 서비스 구현

import org.springframework.stereotype.Service;

@Service
public class AuthenticationLogService {

    private final AuthenticationLogRepository logRepository;

    public AuthenticationLogService(AuthenticationLogRepository logRepository) {
        this.logRepository = logRepository;
    }

    public void logSuccess(String username, String ipAddress) {
        AuthenticationLog log = new AuthenticationLog(username, ipAddress, "SUCCESS", null);
        logRepository.save(log);
    }

    public void logFailure(String username, String ipAddress, String reason) {
        AuthenticationLog log = new AuthenticationLog(username, ipAddress, "FAILURE", reason);
        logRepository.save(log);
    }
}

3-3. 로그 엔티티 및 저장소 설정

로그 엔티티

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class AuthenticationLog {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String ipAddress;
    private String status;
    private String reason;

    // Constructor, Getters, and Setters
    public AuthenticationLog(String username, String ipAddress, String status, String reason) {
        this.username = username;
        this.ipAddress = ipAddress;
        this.status = status;
        this.reason = reason;
    }
}

저장소 인터페이스

import org.springframework.data.jpa.repository.JpaRepository;

public interface AuthenticationLogRepository extends JpaRepository<AuthenticationLog, Long> {
}

3-4. Spring Security 설정

핸들러를 Spring Security 설정에 추가합니다.

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.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    private final CustomAuthenticationSuccessHandler successHandler;
    private final CustomAuthenticationFailureHandler failureHandler;

    public SecurityConfig(CustomAuthenticationSuccessHandler successHandler, CustomAuthenticationFailureHandler failureHandler) {
        this.successHandler = successHandler;
        this.failureHandler = failureHandler;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .successHandler(successHandler)
            .failureHandler(failureHandler);

        return http.build();
    }
}

4. 테스트

  1. 로그인 성공 테스트
    • 올바른 자격 증명으로 로그인하여 성공 로그 기록 확인.
  2. 로그인 실패 테스트
    • 잘못된 자격 증명으로 로그인 시도 후 실패 로그 확인.
  3. 관리자 화면에서 로그 확인
    • DB에 저장된 인증 로그를 관리자 페이지에서 조회 가능하도록 API 구현.

5. 마무리

이번 학습에서는 전자정부프레임워크와 Spring Security를 활용하여 인증 로그를 관리하는 방법을 배웠습니다. 이를 통해 보안 강화와 감사 기능을 구현할 수 있었습니다.
다음에서는 전자정부프레임워크에서 역할 기반 권한 관리를 구현합니다.

반응형

+ Recent posts