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.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.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 LogoutSuccessHandler logoutSuccessHandler(){
return (request, response, authentication) -> {
UserInoutLog inoutLog = new UserInoutLog();
inoutLog.setInoutType("IOT003");
inoutLog.setContactIp(Utils.getClientIP(request));
inoutLog.setSessionId(request.getSession().getId());
inoutLog.setUserBelong((String) request.getSession().getAttribute("belongValue"));
userLogService.saveInoutLog(inoutLog);
new DefaultRedirectStrategy().sendRedirect(request, response, "/");
};
}
@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 재정의
.logoutSuccessHandler(logoutSuccessHandler()) // 로그아웃 성공시 동작 수행.
.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();
}
}