package com.dbnt.faisp.config; import com.dbnt.faisp.main.userInfo.model.UserInfo; import com.dbnt.faisp.main.userInfo.model.UserInoutLog; import com.dbnt.faisp.main.userInfo.service.UserLogService; import com.dbnt.faisp.util.Utils; 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.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.SavedRequest; 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()); private final BaseController baseController; private final UserLogService userLogService; @Bean public PasswordEncoder passwordEncoder(){ return new Pbkdf2PasswordEncoder(); } @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 public AuthenticationSuccessHandler loginSuccessHandler() { return (request, response, authentication) -> { SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request,response); baseController.setSession((UserInfo)authentication.getPrincipal(), request.getSession()); UserInoutLog inoutLog = new UserInoutLog(); inoutLog.setInoutType("IOT001"); inoutLog.setContactIp(Utils.getClientIP(request)); inoutLog.setSessionId(request.getSession().getId()); inoutLog.setUserOrgan((String) request.getSession().getAttribute("userOrgan")); inoutLog.setUserBelong((String) request.getSession().getAttribute("belongValue")); userLogService.saveInoutLog(inoutLog); if(savedRequest != null){ String targetUrl = savedRequest.getRedirectUrl(); new DefaultRedirectStrategy().sendRedirect(request,response,targetUrl); }else{ new DefaultRedirectStrategy().sendRedirect(request,response,"/"); } }; } @Bean public AuthenticationFailureHandler loginFailureHandler(){ return (request, response, exception) -> { UserInoutLog inoutLog = new UserInoutLog(); inoutLog.setInoutType("IOT002"); inoutLog.setContactIp(Utils.getClientIP(request)); userLogService.saveInoutLog(inoutLog); new DefaultRedirectStrategy().sendRedirect(request, response, "/login-error"); }; } @Bean public LogoutHandler logoutHandler(){ return (request, response, authentication) -> { UserInoutLog inoutLog = new UserInoutLog(); inoutLog.setInoutType("IOT003"); inoutLog.setContactIp(Utils.getClientIP(request)); inoutLog.setSessionId(request.getSession().getId()); inoutLog.setUserOrgan((String) request.getSession().getAttribute("userOrgan")); inoutLog.setUserBelong((String) request.getSession().getAttribute("belongValue")); userLogService.saveInoutLog(inoutLog); }; } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeRequests() // 페이지 권한 설정 .antMatchers( "/dashboard", "/myInfo/**", "/modal/**", "/selectBoxOptions", "/publicBoard/**", "/faRpt/**", "/ivsgt/**", "/target/**", "/equip/**", "/affairPlan/**", "/affair/**", "/affairResult/**", "/faStatistics/**", "/translator/**", "/police/**", "/sri/**" ).hasRole(Role.USER.name()) // USER 접근 허용 .antMatchers( "/authMgt/**", "/userMgt/**" ).hasRole(Role.SUB_ADMIN.name()) // SUB_ADMIN 접근 허용 .antMatchers( "/codeMgt/**", "/organMgt/**", "/menuMgt/**" ).hasRole(Role.ADMIN.name()) // ADMIN 접근 허용 .antMatchers( "/login", "/css/**", "/img/**", "/js/**", "/vendor/**", "/Crosseditor/uploadImg" ).permitAll() // 로그인 페이지는 권한 없이 접근 허용 .and() // 로그인 설정 .formLogin().loginPage("/login") // Custom login form 사용 .failureHandler(loginFailureHandler()) // 로그인 실패시 동작 수행 .successHandler(loginSuccessHandler()) // 로그인 성공시 동작 수행. .and() // 로그아웃 설정 .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // 로그아웃 시 URL 재정의 .addLogoutHandler(logoutHandler()) // 로그아웃 전 실행. .logoutSuccessUrl("/login") .invalidateHttpSession(true) // HTTP Session 초기화 .deleteCookies("JSESSIONID") // 특정 쿠키 제거 .and() // 403 예외처리 핸들링 //.exceptionHandling().accessDeniedPage("/denied"); .exceptionHandling() .accessDeniedHandler(accessDeniedHandler()) .authenticationEntryPoint(authenticationEntryPoint()); // 나모 에디터 'X-Frame-Options' to 'DENY' 오류로 인하여 추가. // https://computer-science-student.tistory.com/497 http.headers().frameOptions().sameOrigin(); // 나모에디터 이미지 업로드시 csrf 토큰을 추가할 수 없어서 예외처리. http.csrf().ignoringAntMatchers("/Crosseditor/uploadImg"); return http.build(); } }