Обработка ошибки при загрузке Spring в настраиваемом фильтре аутентификации

Я работаю в приложении с весенней загрузкой на моем бэкэнде, и я хочу использовать firebase для выполнения процесса аутентификации. Я правильно настроил firebase в своем проекте с весенней загрузкой и добавил уровень безопасности после этого репозитория с открытым исходным кодом: https://github.com/savicprvoslav/Spring-Boot-starter

Поскольку срок жизни токена Firebase составляет 1 час, мне нужно обработать ошибку, когда Firebase SDK выдает исключение FirebaseAuthException. Проблема в том, что я не могу обрабатывать исключение внутри своего FirebaseFilter. Бэкэнд всегда возвращает страницу ошибки по умолчанию с отметкой времени, ошибкой, сообщением и статусом 500. Я хочу изменить ее так, чтобы она возвращала только код статуса HTTP 401.

Я также хотел бы изменить страницу ошибок по умолчанию, когда URL-путь не существует, чтобы возвращать только 404, поскольку должен возвращаться хороший REST API.

Я пробовал использовать @ExceptionHandler и @ControllerAdvice (следуя этой статье https://www.baeldung.com/exception-handling-for-rest-with-spring), но это не сработало. Я очень новый разработчик Spring Framework, так что я думаю, что мне что-то не хватает ...

Мой файл .gradle:

implementation('org.springframework.boot:spring-boot-starter-data-jpa')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.springframework.boot:spring-boot-starter-security')
implementation('org.flywaydb:flyway-core:5.2.1')
implementation('com.fasterxml.jackson.module:jackson-module-kotlin')
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation('com.google.firebase:firebase-admin:6.5.0')
implementation('io.springfox:springfox-swagger2:2.9.2')
implementation('io.springfox:springfox-swagger-ui:2.9.2')
runtimeOnly('org.postgresql:postgresql')
testImplementation('org.springframework.boot:spring-boot-starter-test')

Мой WebSecurityConfigurerAdapter:

@Configuration
inner class ApplicationSecurity : WebSecurityConfigurerAdapter(false) {
    @Autowired(required = false)
    lateinit var firebaseService: FirebaseServiceContract

    override fun configure(web: WebSecurity) {
        web.ignoring().antMatchers(
            "/api/users",
            "/v2/api-docs",
            "/configuration/ui",
            "/swagger-resources",
            "/configuration/security", "/swagger-ui.html",
            "/webjars/**", "/swagger-resources/configuration/ui",
            "/swagge‌r-ui.html", "/docs/**",
            "/swagger-resources/configuration/security"
        )
    }

    override fun configure(http: HttpSecurity) {
        http.addFilterBefore(tokenAuthorizationFilter(), BasicAuthenticationFilter::class.java)
            .authorizeRequests()
            .antMatchers("/api/**").hasAnyRole(Roles.USER)
            .and().csrf().disable().anonymous().authorities(Roles.ROLE_ANONYMOUS)
    }

    private fun tokenAuthorizationFilter(): FirebaseFilter? {
        return FirebaseFilter(firebaseService)
    }
}

Мой FirebaseFilter:

class FirebaseFilter(private val firebaseService: FirebaseServiceContract) : OncePerRequestFilter() {
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
    val xAuth = request.getHeader(HEADER_NAME)?.removePrefix("Bearer ")
    if (xAuth.isNullOrBlank()) {
        chain.doFilter(request, response)
        return
    } else {
        try {
            // Fire FirebaseAuth.getInstance().verifyIdToken
            val holder = firebaseService.parseToken(xAuth)

            val userName = holder.getUid()

            val auth = FirebaseAuthenticationToken(userName, holder)
            SecurityContextHolder.getContext().authentication = auth

            chain.doFilter(request, response)
        } catch (e: FirebaseTokenInvalidException) {
            throw SecurityException(e)
        }
    }
}

Мой парсер Firebase:

class FirebaseParser {

fun parseToken(idToken: String): FirebaseTokenHolder {
    if (idToken.isBlank()) {
        throw IllegalArgumentException("Blank Token")
    }

    try {
        val authTask = FirebaseAuth.getInstance().verifyIdToken(idToken)
        FirebaseAuth.getInstance().getUser(authTask.uid)

        return FirebaseTokenHolder(authTask)
    } catch (e: FirebaseAuthException) {
        throw FirebaseTokenInvalidException(e.message)
    }
  }
}

person Esdras    schedule 25.11.2018    source источник
comment
Ваша установка в Котлине? Я борюсь с настройкой в ​​Kotlin, используя Spring Boot 2 и автоматическое подключение.   -  person Ollikas    schedule 27.04.2020


Ответы (1)


По сути, ответ здесь: https://stackoverflow.com/a/34633687/496038

Реализуйте класс ExceptionHandlerFilter, как в ответе выше (аналогично), и в своем расширении WebSecurityConfigurerAdapter добавьте что-то вроде этого:

      @Override
      protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().cors().and().authorizeRequests().anyRequest().authenticated().and()
            .addFilterBefore(
                new ExceptionHandlerFilter(), CorsFilter.class);
      }

Это должно сработать.

person pringi    schedule 21.11.2019