
File name
Commit message
Commit date
File name
Commit message
Commit date
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 com.takensoft.common.oauth.service.Impl.CustomOAuth2UserServiceImpl;
import com.takensoft.common.oauth.handler.OAuth2AuthenticationSuccessHandler;
import com.takensoft.common.oauth.handler.OAuth2AuthenticationFailureHandler;
import org.springframework.beans.factory.annotation.Autowired;
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.oauth2.client.registration.ClientRegistrationRepository;
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 | 최초 등록
* 2025.05.22 | takensoft | OAuth2 로그인 추가
*
* 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;
@Autowired
private CustomOAuth2UserServiceImpl customOAuth2UserServiceImpl;
@Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
@Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
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;
/**
* SecurityConfig 생성자
*/
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));
http.exceptionHandling((exception) -> exception
.authenticationEntryPoint(authenticationEntryPoint) // 접근 권한이 없는 경우에 호출
.accessDeniedHandler(accessDenieHandler) // 인증되지 않은 상태로 접근 했을 때 호출
);
http.authorizeHttpRequests((auth) -> auth
.requestMatchers("/", "/mbr/**", "/refresh/**", "/sys/**", "/editFileUpload/**", "/fileUpload/**", "/oauth2/**", "/login/oauth2/**").permitAll() // 회원, 토큰, 시스템 제공, 파일, OAuth2 접근 모두 허용
.requestMatchers("/admin/**").hasRole("ADMIN") // 관리자 페이지는 ADMIN 권한을 가진 사용자만 접근 가능
.anyRequest().authenticated() // 그 외에는 로그인한 사용자만 접근 가능
);
// Context Path 검증 필터
http.addFilterBefore(new ContextPathFilter(cntxtPthService), SecurityContextPersistenceFilter.class);
// JWT 토큰 검증 필터
http.addFilterBefore(new JWTFilter(jwtUtil, appConfig, loginModeService, 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);
// OAuth2 로그인 설정
http.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(customOAuth2UserServiceImpl)
)
.successHandler(oAuth2AuthenticationSuccessHandler)
.failureHandler(oAuth2AuthenticationFailureHandler)
);
return http.build();
}
}