코드 그라데이션

JWT 예제 구현 (12) 3.0.1 버전 업그레이드 본문

Spring/Security

JWT 예제 구현 (12) 3.0.1 버전 업그레이드

완벽한 장면 2023. 12. 23. 20:26

3.01로 업데이트 하기 위한 작업

*** 자바 버전을 반드시 17 이상으로 해야 한다!

 

build.gradle

plugins {
    id 'java'
    // 두 개 수정
    id 'org.springframework.boot' version '3.0.1'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'inflearn'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17' // 수정

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    runtimeOnly 'com.h2database:h2'

    implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
    runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
    runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'
}

tasks.named('test') {
    useJUnitPlatform()
}

 

gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
# 버전 업그레이드
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

 

SecurityConfig

package inflearn.freejwt.config;


import inflearn.freejwt.jwt.JwtAccessDeniedHandler;
import inflearn.freejwt.jwt.JwtAuthenticationEntryPoint;
import inflearn.freejwt.jwt.JwtSecurityConfig;
import inflearn.freejwt.jwt.TokenProvider;
import lombok.RequiredArgsConstructor;

import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
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.filter.CorsFilter;

@EnableWebSecurity // 기본적인 웹 시큐리티 설정을 활성화하겠다.
@EnableMethodSecurity // 추가
@Configuration
@RequiredArgsConstructor
public class SecurityConfig { // extend 삭제

    private final TokenProvider tokenProvider;
    private final CorsFilter corsFilter;
    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;


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

// WebSecurityCustomizer 삭제

    /**
     *
     * @param http the {@link HttpSecurity} to modify
     * @throws Exception
     *
     * 많은 부분들을 추가
     * : 토큰을 사용하기 때문에 csrf 설정은 disable
     *  Exception을 핸들링할 때 만들었던 클래스들을 추가한다.
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        // token을 사용하는 방식이기 때문에 csrf를 disable한다.
        httpSecurity.csrf().disable()
                .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)

                // h2-console을 위한 설정
                .and()
                .headers()
                .frameOptions()
                .sameOrigin()


                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session을 사용하지 않음.

                .and()
                // 이부분 전부 수정
                .authorizeHttpRequests()
                .requestMatchers("/api/hello", "/api/authenticate", "/api/signup").permitAll()
                .requestMatchers(PathRequest.toH2Console()).permitAll()
                .anyRequest().authenticated()

                .and()
                .apply(new JwtSecurityConfig(tokenProvider));

        return httpSecurity.build();
    }
}

 

 

 

addAllowedOriginPattern 적용

CorsConfig

package inflearn.freejwt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;


@Configuration
public class CorsConfig {

    // CORS 필터 빈을 정의하는 메서드
    @Bean
    public CorsFilter corsFilter() {
        // URL 기반의 CORS 구성을 관리하는 객체 생성
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        // CORS 구성 설정 객체 생성
        CorsConfiguration config = new CorsConfiguration();

        // 요청에서 자격 증명(자격 증명 쿠키, 인증 등)을 허용
        config.setAllowCredentials(true);

//        // 모든 출처(Origin)를 허용
//        config.addAllowedOrigin("*");
        config.addAllowedOriginPattern("*");

        // 모든 HTTP 헤더를 허용
        config.addAllowedHeader("*");

        // 모든 HTTP 메서드(GET, POST, PUT, DELETE 등)를 허용
        config.addAllowedMethod("*");

        // "/api/**" 패턴에 해당하는 엔드포인트에 대해 CORS 구성을 등록
        source.registerCorsConfiguration("/api/**", config);

        // CORS 필터를 생성하고 반환
        return new CorsFilter(source);
    }
}

 

addAllowedOrigin("*")와 config.addAllowedOriginPattern("*")

config.addAllowedOrigin("*")와 config.addAllowedOriginPattern("*")는 

CORS (Cross-Origin Resource Sharing) 설정에서 다르게 작동하는 두 가지 방법을 나타낸다.


1. config.addAllowedOrigin("*"):

이 설정은 모든 출처(Origin)를 허용하는 것을 의미한다. 

즉, 어떤 도메인이든 자원에 접근할 수 있도록 CORS 정책을 완전히 비활성화한다. 

이 설정은 보안에 취약할 수 있으므로 주의해서 사용해야 합니다. 개발 또는 테스트 목적으로만 사용해야 된다.

 

2. config.addAllowedOriginPattern("*"):

이 설정은 출처 패턴을 허용하는 것을 의미한다. 

출처 패턴은 정규 표현식과 유사한 방식으로 동작하며, 특정 출처 패턴과 일치하는 도메인만 허용된다. 

예를 들어, "https://example.com"과 같은 특정 출처를 허용하거나, 

"https://*.example.com"과 같은 와일드카드 패턴을 사용하여 특정 도메인과 하위 도메인을 허용할 수 있다. 

이 방법은 더 세밀한 제어를 제공하며, 보안을 더 강화할 수 있다.

일반적으로 보안을 고려하고 정확한 출처를 허용하려면 

config.addAllowedOriginPattern("*") 대신 실제 도메인 또는 도메인 패턴을 지정하여 사용하는 것이 좋다.

config.addAllowedOrigin("*")은 개발 중에 테스트를 위해 사용되거나 보안이 필요하지 않은 상황에서만 사용해야 한다.

728x90
Comments