Я работаю в подпружиненном приложении на своем бэкэнде и хочу использовать 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",
"/swagger-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)
}
}
}