본문 바로가기
관리자

Project/Poppin

OAuth2 구현 - websecurityconfigureradapter deprecated, NoClassDefFoundError

728x90
반응형

 

1. OAuth2 - websecurityconfigureradapter deprecated

참조한 블로그

https://m.blog.naver.com/PostView.naver?blogId=anytimedebug&logNo=221396422266&categoryNo=28&proxyReferer=

 

dependencies에 oauth 관련 라이브러리르 추가해주었다.

dependencies {
    testImplementation(kotlin("test"))
    implementation("org.springframework.boot:spring-boot-starter:3.1.5")
    implementation("org.springframework.boot:spring-boot-starter-web:3.1.5")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.1.5")
    implementation("org.springframework.boot:spring-boot-starter-logging:3.1.5")
    runtimeOnly("org.jetbrains.kotlin:kotlin-reflect:1.9.10")
    compileOnly("org.projectlombok:lombok:1.18.26")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.2")
    implementation("org.springframework.boot:spring-boot-starter-security:3.1.5") //
    implementation("org.springframework.security:spring-security-oauth2-client:6.1.2") //
    implementation("org.springframework.security:spring-security-oauth2-jose:6.1.2") //
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf:3.1.2")
    implementation("com.mysql:mysql-connector-j:8.1.0")
    testImplementation("org.springframework.boot:spring-boot-starter-test:3.1.5")
    testImplementation("org.springframework.security:spring-security-test:6.1.2") //
    testImplementation("com.h2database:h2:2.2.224")

}

 

 

 

 

 

다만 블로그의 코드는 deprecated된 websecurityconfigureradapter를 참조하고 있어서, Spring에서 권장하는 filterChain 방식으로 바꿨다.

 

@Configuration
@EnableWebSecurity
open class SecurityConfig {

    @Bean
    open fun filterChain(http: HttpSecurity): SecurityFilterChain {

        http.invoke {
            authorizeRequests {
                authorize("/login/**", permitAll)
                authorize("/oauth2/**", permitAll)
                authorize("/images/**", permitAll)
            }
            oauth2Login {
                defaultSuccessUrl("/login/complete", alwaysUse = true)
            }
            // iframe 설정
            headers {
                frameOptions {
                    disable()
                }
            }
            // 비인증 사용자 이동
            exceptionHandling {
                authenticationEntryPoint = LoginUrlAuthenticationEntryPoint("/login")
            }
            // 로그인 후 이동
            formLogin {
                defaultSuccessUrl("/", alwaysUse = true)
            }
            // 로그아웃
            logout {
                logoutUrl = "/logout"
                logoutSuccessUrl = "/login"
                deleteCookies("JSESSIONID")
                invalidateHttpSession = true
            }

            csrf { disable() }
            addFilterAt<CsrfFilter>(CharacterEncodingFilter())

        }


        return http.build()
    }
   // ... 아래에 계속

 

 

@Bean
    open fun clientRegistrationRepository(
        oAuth2ClientProperties: OAuth2ClientProperties,
    ): InMemoryClientRegistrationRepository {

        val registrations = oAuth2ClientProperties.registration.keys
            .map { getRegistration(oAuth2ClientProperties, it) }
            .filterNotNull()
            .toMutableList()

        return InMemoryClientRegistrationRepository(registrations)
    }

 

private fun getRegistration(clientProperties: OAuth2ClientProperties, client: String): ClientRegistration? {
        val registration = clientProperties.registration[client]
        return when (client) {
            "google" -> CommonOAuth2Provider.GOOGLE.getBuilder(client)
                .clientId(registration?.clientId)
                .clientSecret(registration?.clientSecret)
                .scope("email", "profile")
                .build()
            // 페이스북을 추가하고 싶으면 SSL을 적용하셔야 합니다.
//            "facebook" -> CommonOAuth2Provider.FACEBOOK.getBuilder(client)
//                    .clientId(registration?.clientId)
//                    .clientSecret(registration?.clientSecret)
//                    .userInfoUri("https://graph.facebook.com/me?fields=id,name,email,link")
//                    .scope("email")
//                    .build()
            else -> null
        }
    }
  }

 

 

2. NoClassDefFoundError, ClassNotFoundException

 

에러의 원리 및 두 에러의 차이점은 아래 링크에서 확인할 수 있다.

https://yangbox.tistory.com/117

 

정상적으로 코드를 작성했는데 자꾸 에러가 났다. 위 참조 링크에서 에러의 원리를 생각해보니 compile 때는 class가 존재하는데, runtime에 class가 존재하지 않는 것이였다.

 

- 원인: build.gradle.kts에 oauth 관련 라이브러리들을 implementation 하지 않고 compileOnly로 추가했었다. implementation으로 수정하니 해결되었다.

 

 

3. thymeleaf relative path

아래 그림처럼 하면 된다. 다만, resources/static 디렉토리 내부에 있어야 정적 컨텐츠 참조가 가능하다.

 

 

728x90
반응형