二、WebFlux 权限拦截
与 SpringMVC 不同,WebFlux 不再使用 Interceptor,取而代之的是 org.springframework.web.server.WebFilter。而同样的,为了排除一些不需要拦截的方法、或类,我们需要定义一个注解。
1、注解
@Retention
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE, AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
annotation class NoLogin
2、拦截器
@Order(-1)
@Configuration
@ConditionalOnMissingBean(name = ["authWebFilter"])
@ConditionalOnClass(org.springframework.web.reactive.DispatcherHandler::class, EnableSwagger2WebFlux::class)
class AuthWebFilter : WebFilter {
@Autowired lateinit var requestMappingHandlerMapping: RequestMappingHandlerMapping
@Suppress("SpringJavaInjectionPointsAutowiringInspection")
@Autowired lateinit var authBS: AbstractAuthBS
override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
return requestMappingHandlerMapping.getHandler(exchange).switchIfEmpty(chain.filter(exchange)).flatMap {
(it as HandlerMethod).let { handlerMethod ->
(handlerMethod.method.getAnnotation(NoLogin::class.java)
?: it.beanType.getAnnotation(NoLogin::class.java))?.let {
chain.filter(exchange)
} ?: let {
(exchange.request.headers.getFirst("token")?.let { token ->
authBS.checkPermission(token, exchange).flatMap { chain.filter(exchange) }
} ?: Mono.empty()).switchIfEmpty(Mono.defer {
// 放在最后, 因放在这里的路径响应的最慢, 所以 这样只会影响 开发/测试线
val path = exchange.request.path.toString()
if (path.startsWith("/swagger-ui.html")
|| path.startsWith("/swagger-resources") || path.startsWith("/v2/api-docs")
|| path.startsWith("/webjars") || path.startsWith("/csrf") || path == "/")
chain.filter(exchange)
else Mono.empty<Void>().apply {
exchange.response.statusCode = HttpStatus.UNAUTHORIZED
}
})
}
}
}
}
}
3、预置匿名实现
@Configuration
class FilterConfiguration {
@Bean
@ConditionalOnMissingBean(AbstractAuthBS::class)
@ConditionalOnClass(org.springframework.web.reactive.DispatcherHandler::class, EnableSwagger2WebFlux::class)
fun authBS(): AbstractAuthBS {
/** 匿名实现 */
return object : AbstractAuthBS {
override fun checkPermission(token: String, exchange: ServerWebExchange): Mono<Session> {
return Mono.justOrEmpty(Session(""))
}
}
}
}
同样,没啥说的,代码贴完了,也就完事了 ~