
File name
Commit message
Commit date
File name
Commit message
Commit date
04-22
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
package com.takensoft.common.config;
import com.takensoft.cms.accesCtrl.service.AccesCtrlService;
import com.takensoft.cms.cntxtPth.service.CntxtPthService;
import com.takensoft.cms.loginPolicy.service.LoginModeService;
import com.takensoft.cms.loginPolicy.service.LoginPolicyService;
import com.takensoft.cms.mber.service.LgnHstryService;
import com.takensoft.cms.token.service.RefreshTokenService;
import com.takensoft.common.filter.*;
import com.takensoft.common.util.HttpRequestUtil;
import com.takensoft.common.exception.CustomAccessDenieHandler;
import com.takensoft.common.exception.CustomAuthenticationEntryPoint;
import com.takensoft.common.util.JWTUtil;
import com.takensoft.common.util.SessionUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Collections;
/**
* @author takensoft
* @since 2025.01.22
* @modification
* since | author | description
* 2025.01.22 | takensoft | 최초 등록
*
* Spring Security 설정을 위한 Config
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
// AuthenticationManager가 인자로 받을 AuthenticationConfiguration 객체 생성자 주입
private final AuthenticationConfiguration authenticationConfiguration;
private final JWTUtil jwtUtil;
private final RefreshTokenService refreshTokenService;
private final LgnHstryService lgnHstryService;
private final CntxtPthService cntxtPthService;
private final AccesCtrlService accesCtrlService;
private final CustomAuthenticationEntryPoint authenticationEntryPoint;
private final CustomAccessDenieHandler accessDenieHandler;
private final HttpRequestUtil httpRequestUtil;
private final AppConfig appConfig;
private final LoginModeService loginModeService;
private final LoginPolicyService loginPolicyService;
private final SessionUtil sessionUtil;
private static String FRONT_URL; // 프론트 접근 허용 URL
private static long JWT_ACCESSTIME; // access 토큰 유지 시간
private static long JWT_REFRESHTIME; // refresh 토큰 유지 시간
private static int COOKIE_TIME; // 쿠키 유지 시간
private final RedisTemplate<String, String> redisTemplate;
/**
* @param authenticationConfiguration - 인증 구성 객체
* @param jwtUtil - JWT 유틸리티 객체
* @param authenticationEntryPoint - 인증 실패 시 처리 엔트리 포인트
* @param accessDenieHandler - 접근 거부 처리 핸들러
* @param fUrl - 프론트엔드 URL (application.yml에서 값을 읽어 옴)
* @param aTime - JWT 접근 토큰 유효 시간 (application.yml에서 값을 읽어 옴)
* @param rTime - JWT 리프레시 토큰 유효 시간 (application.yml에서 값을 읽어 옴)
* @param ctime - 쿠키 유효 시간 (application.yml에서 값을 읽어 옴)
* @param redisTemplate
*
*/
public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, RefreshTokenService refreshTokenService, CntxtPthService cntxtPthService, AccesCtrlService accesCtrlService, AppConfig appConfig,
LgnHstryService lgnHstryService, CustomAuthenticationEntryPoint authenticationEntryPoint, CustomAccessDenieHandler accessDenieHandler, HttpRequestUtil httpRequestUtil,
LoginModeService loginModeService, LoginPolicyService loginPolicyService, SessionUtil sessionUtil, @Value("${front.url}") String fUrl, @Value("${jwt.accessTime}") long aTime, @Value("${jwt.refreshTime}") long rTime, @Value("${cookie.time}") int ctime, RedisTemplate<String, String> redisTemplate) {
this.authenticationConfiguration = authenticationConfiguration;
this.refreshTokenService = refreshTokenService;
this.lgnHstryService = lgnHstryService;
this.cntxtPthService = cntxtPthService;
this.accesCtrlService = accesCtrlService;
this.authenticationEntryPoint = authenticationEntryPoint;
this.accessDenieHandler = accessDenieHandler;
this.jwtUtil = jwtUtil;
this.httpRequestUtil = httpRequestUtil;
this.appConfig = appConfig;
this.loginModeService = loginModeService;
this.loginPolicyService = loginPolicyService;
this.sessionUtil = sessionUtil;
this.FRONT_URL = fUrl;
this.JWT_ACCESSTIME = aTime;
this.JWT_REFRESHTIME = rTime;
this.COOKIE_TIME = ctime;
this.redisTemplate = redisTemplate;
}
/**
* @param configuration - 인증 구성 객체
* @return AuthenticationManager 객체
* @throws Exception - 인증 관리자 초기화 실패 시
*
* AuthenticationManager Bean 등록
*/
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
/**
* @return BCryptPasswordEncoder 객체
*
* 비밀번호 해시 암호화를 위한 Bean 등록
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* @param http - HTTP 보안 설정 객체
* @return SecurityFilterChain 객체
* @throws Exception - 보안 필터 체인 초기화 실패 시
*
* Spring Security 필터 체인 설정
*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.cors((cors) -> cors
.configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList(FRONT_URL)); // 허용할 프론트 포트 포함 경로 입력
configuration.setAllowedMethods(Collections.singletonList("*")); // 허용할 메소드(GET, POST, PUT 등)
configuration.setAllowedHeaders(Collections.singletonList("*")); // 허용할 헤드
configuration.setAllowCredentials(true); // 프론트에서 credentials 설정하면 true
configuration.setMaxAge(3600L); // 허용을 물고 있을 시간
configuration.setExposedHeaders(Collections.singletonList("Authorization")); // 서버에서 JWT를 Authorization에 담아 보내기 위해 허용을 함
return configuration;
}
})
);
// csrf disable
http.csrf((auth) -> auth.disable());
// formLogin disable
http.formLogin((auth) -> auth.disable());
// http basic 인증 방식 disable
http.httpBasic((auth) -> auth.disable());
// 세션 설정
http.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
// Context Path 검증 필터
http.addFilterBefore(new ContextPathFilter(cntxtPthService), SecurityContextPersistenceFilter.class);
http.exceptionHandling((exception) -> exception
.authenticationEntryPoint(authenticationEntryPoint) // 접근 권한이 없는 경우에 호출
.accessDeniedHandler(accessDenieHandler) // 인증되지 않은 상태로 접근 했을 때 호출
);
http.authorizeHttpRequests((auth) -> auth
.requestMatchers("/", "/mbr/**", "/company/**", "/refresh/**", "/sys/**").permitAll() // 회원관련, 시스템 제공 관련, 기업용페이지는 누구나 접근 가능
.requestMatchers("/admin/**").hasRole("ADMIN") // 관리자 페이지는 ADMIN 권한을 가진 사용자만 접근 가능
.requestMatchers("/editFileUpload/**", "/fileUpload/**").permitAll() // 에디터 파일 업로드
.anyRequest().authenticated() // 그 외에는 로그인한 사용자만 접근 가능
// .anyRequest().permitAll() // 모든 사용자 접근 가능
);
// 로그인 방식에 따라 필터 적용 (JWT or 세션)
if (loginModeService.getLoginMode().equals("S")) {
http.addFilterBefore(new SessionAuthFilter(jwtUtil, redisTemplate, loginPolicyService, refreshTokenService), LoginFilter.class);
} else {
http.addFilterBefore(new JWTFilter(jwtUtil, appConfig, loginPolicyService, redisTemplate), LoginFilter.class);
}
http.addFilterBefore(new AccesFilter(accesCtrlService, httpRequestUtil, appConfig), JWTFilter.class); // 아이피 검증
http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil, refreshTokenService, lgnHstryService, httpRequestUtil,
loginModeService, loginPolicyService, sessionUtil, JWT_ACCESSTIME, JWT_REFRESHTIME, COOKIE_TIME, redisTemplate), UsernamePasswordAuthenticationFilter.class); // 로그인 필터
return http.build();
}
}