package com.dbnt.faisp.config; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import javax.servlet.http.HttpServletResponse; @Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig{ private final Logger log = LoggerFactory.getLogger(getClass()); @Bean public PasswordEncoder passwordEncoder(){ return new Pbkdf2PasswordEncoder(); } @Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) -> web.ignoring().antMatchers("/css/**", "/img/**", "/js/**", "/vendor/**"); } @Bean public AccessDeniedHandler accessDeniedHandler() { log.warn("accessDeniedHandler"); return (request, response, e) -> { response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.setContentType("text/html;charset=UTF-8"); response.getWriter().println(""); response.getWriter().flush(); response.getWriter().close(); }; } @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return (request, response, e) -> { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("text/html;charset=UTF-8"); response.getWriter().println(""); response.getWriter().flush(); response.getWriter().close(); }; } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeRequests() // 페이지 권한 설정 .antMatchers( "/dashboard", "/refreshSession" ).hasRole(Role.USER.name()) // USER, ADMIN 접근 허용 .antMatchers( "/codeMgt/**", "/menuMgt/**" ).hasRole(Role.ADMIN.name()) // ADMIN만 접근 허용 .antMatchers( "/authMgt/**", "/userMgt/**", "/organMgt/**" ).hasRole(Role.SUB_ADMIN.name()) // SUB_ADMIN만 접근 허용 .antMatchers("/login").permitAll() // 로그인 페이지는 권한 없이 접근 허용 .and() // 로그인 설정 .formLogin().loginPage("/login") // Custom login form 사용 .failureUrl("/login-error") // 로그인 실패 시 이동 .defaultSuccessUrl("/") // 로그인 성공 시 이동 /*.failureHandler((request, response, exception) -> { }) // 로그인 실패시 동작 수행 .successHandler((request, response, authentication) -> { SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request,response); if(savedRequest != null){ String targetUrl = savedRequest.getRedirectUrl(); new DefaultRedirectStrategy().sendRedirect(request,response,targetUrl); }else{ new DefaultRedirectStrategy().sendRedirect(request,response,"/"); } }) // 로그인 성공시 동작 수행.*/ .and() // 로그아웃 설정 .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // 로그아웃 시 URL 재정의 .logoutSuccessUrl("/") // 로그아웃 성공 시 redirect 이동 .invalidateHttpSession(true) // HTTP Session 초기화 .deleteCookies("JSESSIONID") // 특정 쿠키 제거 .and() // 403 예외처리 핸들링 //.exceptionHandling().accessDeniedPage("/denied"); .exceptionHandling() .accessDeniedHandler(accessDeniedHandler()) .authenticationEntryPoint(authenticationEntryPoint()); return http.build(); } }