개발 가이드 백엔드 인증 / 인가 처리
최종 수정:

인증 / 인가 처리

현재 프로젝트 인증 방식 및 Spring Security 설정

인증 / 인가 처리

현재 프로젝트 인증 방식

현재 이 프로젝트는 공개 접근(Public Access) 방식으로 운영된다.

  • 일반 사용자 페이지: 누구나 접근 가능
  • 어드민 페이지 (/admin/**): 별도 인증 없이 직접 URL 접근 가능 (내부망 운영 또는 차후 도입 예정)
  • 관리자 기능에 인증 도입 시 이 문서를 갱신한다.

Spring Security 설정 (향후 도입 시 참고)

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/news/**", "/guide/**", "/health").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/guide/search").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll()
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/")
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .invalidSessionUrl("/login")
                .maximumSessions(1)
                .maxSessionsPreventsLogin(false)
            )
            .csrf(csrf -> csrf
                .ignoringRequestMatchers("/api/**")   // REST API는 CSRF 제외
            );

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);   // strength 12 (최소)
    }
}

세션 타임아웃 설정

# application.yml
server:
  servlet:
    session:
      timeout: 30m    # 세션 타임아웃 30분

인증 실패 로깅

@Component
public class AuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    private static final Logger log = LoggerFactory.getLogger(AuthFailureHandler.class);

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response,
                                        AuthenticationException exception) throws IOException {
        String username = request.getParameter("username");
        // 개인정보(비밀번호, 이메일 전체 등) 로그 출력 금지
        log.warn("로그인 실패: userId={}", username);
        super.onAuthenticationFailure(request, response, exception);
    }
}

권한 체크 (메서드 레벨)

@Service
public class PostService {

    // 메서드 레벨 권한 체크
    @PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
    public void delPost(Long postId, Long userId) {
        // ...
    }
}

CSRF 토큰 (Thymeleaf)

<!-- POST 폼에 CSRF 토큰 필수 -->
<form th:action="@{/submit}" method="post">
    <input type="hidden"
           th:name="${_csrf.parameterName}"
           th:value="${_csrf.token}"/>
</form>

REST API 클라이언트 (JavaScript):

// CSRF 토큰을 헤더로 전달
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;

fetch('/api/posts', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        [csrfHeader]: csrfToken
    },
    body: JSON.stringify(data)
});

JWT 도입 시 고려사항

향후 JWT 기반 인증을 도입할 때 참고:

  1. spring-boot-starter-security + jjwt 의존성 추가
  2. JwtAuthenticationFilterSecurityFilterChain 앞에 추가
  3. CSRF 비활성화 (Stateless 방식에서는 불필요)
  4. JWT 시크릿 키는 JWT_SECRET 환경변수로 관리
  5. 액세스 토큰 만료: 15분, 리프레시 토큰 만료: 7일
  6. 리프레시 토큰은 DB에 저장 (탈취 시 무효화 가능)
  7. 로그에 토큰 값 출력 절대 금지

보안 체크리스트

  • [ ] 인증 없이 접근 가능한 엔드포인트 최소화
  • [ ] 다른 사용자 리소스 접근 불가 (수평적 권한 상승 방지)
  • [ ] 관리자 기능(/admin/**) 권한 검증
  • [ ] 비밀번호 BCrypt 암호화 (최소 12자)
  • [ ] 세션 타임아웃 30분 설정
  • [ ] CSRF 토큰 적용 (POST 폼, REST API 헤더)
  • [ ] 인증/인가 실패 로그 기록
  • [ ] 로그에 개인정보/비밀번호 미포함
AI 문서 검색

현재 페이지 내용을 기반으로 질문하세요.