본문 바로가기

카테고리 없음

[Spring Boot] Security6 세션 정보 및 CORS 설정 (6)

 

 

https://docs.spring.io/spring-security/reference/servlet/integrations/cors.html

 

CORS :: Spring Security

Spring Framework provides first class support for CORS. CORS must be processed before Spring Security, because the pre-flight request does not contain any cookies (that is, the JSESSIONID). If the request does not contain any cookies and Spring Security is

docs.spring.io

 

 

세션 정보 확인

@GetMapping("/test")
public String test() {
    // 현재 SecurityContext에서 인증된 사용자의 이름을 가져옵니다.
    String name = SecurityContextHolder.getContext().getAuthentication().getName();

    // 현재 SecurityContext에서 Authentication 객체를 가져옵니다.
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    // 인증된 사용자의 권한(역할) 목록을 가져옵니다.
    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
    
    // 권한 목록에서 첫 번째 권한을 가져옵니다.
    Iterator<? extends GrantedAuthority> iter = authorities.iterator();
    GrantedAuthority auth = iter.next();
    
    // 첫 번째 권한의 이름(역할)을 가져옵니다.
    String role = auth.getAuthority();

    // 인증된 사용자의 이름과 역할을 포함한 문자열을 반환합니다.
    return "test security ContextName :  " + name + " " + role;
}

 

세션 정보 확인 @AuthenticationPricipal

@AuthenticationPrincipal 어노테이션을 사용하면 SecurityContext에서 현재 인증된 사용자의 정보를 주입받을 수 있습니다.

   @GetMapping("/test")
    public String test(@AuthenticationPrincipal UserDetails userDetails) {
        // 인증된 사용자의 이름을 가져옵니다.
        String name = userDetails.getUsername();

        // 인증된 사용자의 권한(역할) 목록을 가져옵니다.
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();

        // 권한 목록에서 첫 번째 권한을 가져옵니다.
        Iterator<? extends GrantedAuthority> iter = authorities.iterator();
        GrantedAuthority auth = iter.next();

        // 첫 번째 권한의 이름(역할)을 가져옵니다.
        String role = auth.getAuthority();

        // 인증된 사용자의 이름과 역할을 포함한 문자열을 반환합니다.
        return "test security ContextName :  " + name + " " + role;
    }

 

SecurityConfig

http
    .cors((corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource() {
        // CORS 설정을 위한 configurationSource를 커스터마이징합니다.

        @Override
        public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
            // getCorsConfiguration 메서드를 오버라이드하여 CORS 설정을 구성합니다.
            CorsConfiguration configuration = new CorsConfiguration();

            configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
            // "http://localhost:3000" 도메인에서 오는 요청을 허용합니다.

            configuration.setAllowedMethods(Collections.singletonList("*"));
            // 모든 HTTP 메서드를 허용합니다.

            configuration.setAllowCredentials(true);
            // 자격 증명(쿠키, Authorization 헤더 등)을 포함한 요청을 허용합니다.

            configuration.setAllowedHeaders(Collections.singletonList("*"));
            // 모든 요청 헤더를 허용합니다.

            configuration.setMaxAge(3600L);
            // CORS 요청의 사전 검사(pre-flight) 응답을 캐시할 시간(초)을 설정합니다. 여기서는 1시간(3600초)입니다.

            configuration.setExposedHeaders(Collections.singletonList("Authorization"));
            // "Authorization" 헤더를 클라이언트에 노출합니다.

            return configuration;
        }
    })));
    // 이 설정을 통해 모든 경로에 대해 CORS 설정을 적용합니다.

 

 

이 설정은 HTTP 요청에 대한 CORS 설정을 커스터마이징하는 방법을 보여줍니다. CorsConfigurationSource 인터페이스를 구현하여 getCorsConfiguration 메서드를 오버라이드하고, 여러 CORS 규칙을 설정합니다. 이 예제에서는 http://localhost:3000에서 오는 요청을 허용하며, 모든 HTTP 메서드와 헤더를 허용하고, 자격 증명을 포함한 요청을 허용합니다. 또한, "Authorization" 헤더를 클라이언트에 노출하고, 사전 검사 요청의 응답을 1시간 동안 캐시합니다.

 

config > CorsMvcConfig

@Configuration // 이 클래스가 스프링의 설정 클래스임을 나타냅니다.
public class CorsMvcConfig implements WebMvcConfigurer { // WebMvcConfigurer를 구현하여 CORS 설정을 추가합니다.
    
    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {
        // addCorsMappings 메서드를 오버라이드하여 CORS 설정을 추가합니다.
        
        corsRegistry.addMapping("/**")
                // 모든 경로에 대해 CORS 설정을 적용합니다.
                
                .allowedOrigins("http://localhost:3000");
                // http://localhost:3000 도메인에서 오는 요청을 허용합니다.
    }
}

스프링에서 CORS (Cross-Origin Resource Sharing) 설정을 구성하는 데 사용됩니다. WebMvcConfigurer 인터페이스를 구현하고, addCorsMappings 메서드를 오버라이드하여 특정 도메인에서 오는 요청을 허용합니다.

 

 

SecurityConfig 전체 코드

package com.example.loans_domain.auth.config;

import com.example.loans_domain.auth.jwt.JWTFilter;
import com.example.loans_domain.auth.jwt.JWTUtil;
import com.example.loans_domain.auth.jwt.LoginFilter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;

import java.util.Collections;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final AuthenticationConfiguration authenticationConfiguration;

    private final JWTUtil jwtUtil;

    public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil) {
        this.authenticationConfiguration = authenticationConfiguration;
        this.jwtUtil = jwtUtil;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {


        http
                .cors((corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource() {

                    @Override
                    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                        CorsConfiguration configuration = new CorsConfiguration();

                        configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
                        configuration.setAllowedMethods(Collections.singletonList("*"));
                        configuration.setAllowCredentials(true);
                        configuration.setAllowedHeaders(Collections.singletonList("*"));
                        configuration.setMaxAge(3600L);

                        configuration.setExposedHeaders(Collections.singletonList("Authorization"));

                        return configuration;
                    }
                })));

        //csrf disable
        http
                .csrf((auth) -> auth.disable());

        //From 로그인 방식 disable
        http
                .formLogin((auth) -> auth.disable());

        //http basic 인증 방식 disable
        http
                .httpBasic((auth) -> auth.disable());

        //경로별 인가 작업
        http
                .authorizeHttpRequests((auth) -> auth
                        .requestMatchers("/login", "/", "/join").permitAll()
                        .requestMatchers("/test").hasRole("USER")
                        .requestMatchers("/admin").hasRole("ADMIN")
                        .anyRequest().authenticated());

        http
                .addFilterBefore(new JWTFilter(jwtUtil), LoginFilter.class)
                .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil), UsernamePasswordAuthenticationFilter.class);

        //세션 설정
        http
                .sessionManagement((session) -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        return http.build();
    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}