java - 在自定义身份验证过滤器中处理 Spring Boot 上的错误
问题描述
我正在后端的 spring-boot 应用程序中工作,我想使用 firebase 进行身份验证过程。我在我的 spring-boot 项目中正确设置了 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)
}
}
}
解决方案
基本上,答案就在这里: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);
}
这应该做的工作。
推荐阅读
- c# - 将 IQueryable 转换为 IAsyncQueryable
- kubernetes - Kubernetes入口:如何限制虚拟主机名包含用户自己的命名空间?
- c# - 如何正确编码 url 中的查询参数?
- git - 使用 Git 标签作为阶段的条件
- python - Pygame Escape 键事件响应空格键
- android - 声音在 MacOS 上的 Android 模拟器中不起作用
- point-of-sale - odoo14 POS 收据条码不打印
- c - 如何将 char 缓冲区中的整数读入 int 变量
- java - 获取泛型类的属性值
- django - 如何处理 AJAX 中的补丁方法?