티스토리 뷰

카테고리 없음

Spring Security

진열사랑 2025. 3. 27. 17:44

Spring Security 코드 상세 분석

이 코드는 Spring Security의 UsernamePasswordAuthenticationFilter를 직접 설정하고 실행하는 코드입니다.

  • 전자정부프레임워크(eGovFrame) 환경에서 Spring Security를 커스터마이징하여 로그인 요청을 처리하는 것으로 보입니다.
  • UsernamePasswordAuthenticationFilter는 사용자 인증을 처리하는 필터로, doFilter() 메서드를 통해 직접 실행하고 있습니다.

🔹 1️⃣ UsernamePasswordAuthenticationFilter 객체 생성

UsernamePasswordAuthenticationFilter springSecurity = new UsernamePasswordAuthenticationFilter();
  • UsernamePasswordAuthenticationFilter 객체를 새로 생성하지만, 곧 Spring 컨테이너에서 가져온 Bean으로 덮어쓰기됨
  • 따라서 이 줄은 사실상 의미가 없을 가능성이 큼

🔹 2️⃣ Spring 컨테이너에서 UsernamePasswordAuthenticationFilter 가져오기

Map<String, UsernamePasswordAuthenticationFilter> beans = act.getBeansOfType(UsernamePasswordAuthenticationFilter.class);
  • act.getBeansOfType(UsernamePasswordAuthenticationFilter.class)
    • Spring 컨테이너(ApplicationContext)에서 UsernamePasswordAuthenticationFilter 타입의 모든 Bean을 가져옴
    • 결과는 이름(String) → UsernamePasswordAuthenticationFilter 객체(Map 형식)

🔹 3️⃣ 첫 번째 UsernamePasswordAuthenticationFilter를 가져와 설정

if (beans.size() > 0) {
    springSecurity = (UsernamePasswordAuthenticationFilter) beans.values().toArray()[0];

Spring 컨테이너에서 등록된 UsernamePasswordAuthenticationFilter가 하나라도 있다면, 첫 번째 Bean을 가져와 사용
✔ 하지만 toArray()[0]을 사용하면 필터 순서가 바뀔 가능성이 있어 불안정


🔹 4️⃣ 로그인 폼에서 사용하는 파라미터 설정

springSecurity.setUsernameParameter("egov_security_username");
springSecurity.setPasswordParameter("egov_security_password");

✔ 기본적으로 Spring Security는

  • username
  • password
    라는 파라미터 이름을 사용하지만,
    egov_security_username과 egov_security_password로 변경

📌 전자정부프레임워크(eGovFrame)에서는 기본적으로 커스텀 로그인 파라미터를 사용함


🔹 5️⃣ 로그인 요청을 받을 URL 설정

springSecurity.setRequiresAuthenticationRequestMatcher(
    new AntPathRequestMatcher(request.getServletContext().getContextPath() + "/egov_security_login", "POST")
);

✔ 로그인 요청 URL을 /egov_security_login으로 설정
✔ POST 방식으로만 로그인 요청을 받도록 제한


🔹 6️⃣ UsernamePasswordAuthenticationFilter가 없을 경우 예외 처리

} else {
    LOGGER.error("No AuthenticationProcessingFilter");
    throw new IllegalStateException("No AuthenticationProcessingFilter");
}

✔ Spring 컨테이너에서 UsernamePasswordAuthenticationFilter를 찾지 못하면 오류를 로그에 남기고 예외 발생


🔹 7️⃣ Security 필터 실행 전/후 로그 출력

LOGGER.debug("before security filter call....");

✔ 필터 실행 전 로그 출력


🔹 8️⃣ doFilter()를 사용하여 인증 필터 직접 실행

springSecurity.doFilter(
    new RequestWrapperForSecurity(httpRequest, loginVO.getUserSe() + loginVO.getId(), loginVO.getId()), 
    httpResponse, 
    chain
);

✔ doFilter()를 직접 호출하여 Spring Security 인증 필터를 강제 실행
RequestWrapperForSecurity는 사용자 정보(loginVO)를 추가하여 요청을 가공하는 역할
chain을 넘겨 다음 필터로 전달할 수 있도록 처리


🔹 9️⃣ Security 필터 실행 후 로그 출력

LOGGER.debug("after security filter call....");

✔ 필터 실행 후 로그 출력


결론 및 코드 요약

1️⃣ Spring 컨테이너에서 UsernamePasswordAuthenticationFilter를 찾아 가져옴
2️⃣ 로그인 폼의 username/password 필드명을 "egov_security_username"/"egov_security_password"로 변경
3️⃣ 로그인 요청 URL을 /egov_security_login(POST)로 설정
4️⃣ 필터가 없으면 예외 발생 (IllegalStateException)
5️⃣ doFilter()를 직접 호출하여 Security 필터를 실행 (요청을 강제로 필터링)


개선할 점

  1. Bean을 가져올 때 안정적인 방식 사용📌 toArray()[0] 대신 iterator().next()를 사용하면 더 안전함
  2. if (!beans.isEmpty()) { springSecurity = beans.values().iterator().next(); // 더 안전한 방식 }
  3. Spring Security 설정을 사용하면 더 깔끔한 코드 가능📌 Spring Security의 설정을 활용하면 필터를 직접 조작할 필요 없이 깔끔하게 구현 가능
  4. @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .formLogin() .loginPage("/egov_security_login") .usernameParameter("egov_security_username") .passwordParameter("egov_security_password") .permitAll(); return http.build(); }

결론

현재 코드는 전자정부프레임워크(eGovFrame)에서 Spring Security를 직접 제어하는 방식으로 구현되어 있음.

  • Spring Security의 기본 동작을 변경하려고 필터를 강제로 가져와 설정
  • 하지만 설정 기반으로 Security를 변경하는 것이 더 유지보수에 용이함
  • Spring Security 설정을 활용하는 방식으로 개선하면 더 좋음 🚀
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함