webflux切面拦截权限,webflux整合aop,webflux获取request
背景在springboot+tomcat应用中获取request可以使用RequestContextHolder.getRequestAttributes()的方式来获取,此种方式的核心在于request所在容器被放在threadlocal中,但是webflux结合netty项目却不能这么使用,因为webflux是异步响应式的。...
·
背景
在springboot+tomcat应用中获取request对象可以使用RequestContextHolder.getRequestAttributes()的方式来获取,此种方式的核心在于request所在容器被放在threadlocal中,但是webflux结合netty项目却不能这么使用,因为webflux是异步响应式的,下面介绍下异步服务webflux+netty如何便捷获取request。
编写基于webflux的RequestContextHolder实现
- 编写ReactiveHttpContextHolder类用来模拟RequestContextHolder
public class ReactiveHttpContextHolder {
//获取当前请求对象
public static Mono<ServerHttpRequest> getRequest() {
return Mono.subscriberContext()
.map(context -> context.get(Info.CONTEXT_KEY).getRequest());
}
//获取当前response
public static Mono<ServerHttpResponse> getResponse(){
return Mono.subscriberContext()
.map(context -> context.get(Info.CONTEXT_KEY).getResponse());
}
public static final class Info{
public static final Class<ServerWebExchange> CONTEXT_KEY = ServerWebExchange.class;
}
}
- 编写过滤器类用于设置request到容器中
@Component
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class AppFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//设置当前请求
return chain.filter(exchange)
.subscriberContext(context -> context.put(ReactiveHttpContextHolder.Info.CONTEXT_KEY, exchange));
}
}
编写切面实现token拦截,校验权限
- 切面逻辑代码
@Component
@Aspect
public class AuthAspect extends BaseController {
@Pointcut("execution(public * xx.xx.xxController.*(..))")
private void classRule(){}
//带有AuthIgnore注解的不校验
@Pointcut("@annotation(xx.AuthIgnore)")
private void ignoreRule(){}
@Around("classRule() && !ignoreRule()")
public Mono<Object> aroundInvoke(ProceedingJoinPoint joinPoint){
//获取token
Mono<ServerHttpRequest> requestMono = ReactiveHttpContextHolder.getRequest();
return requestMono.flatMap(request -> {
//检查token
String token = getHeader("token", request);
if (token == null || TokenCacheContainer.getTokenCache().get(token) == null){
BusException ex = new BusException("01300001");
return buildErrMsg(ex);
} else {
try {
return (Mono<Object>) joinPoint.proceed();
} catch (Throwable throwable) {
LogFactory.getLog(AuthAspect.class).error("", throwable);
BusException ex = new BusException("01300000");
return buildErrMsg(ex);
}
}
});
}
private Mono<String> buildErrMsg(BusException ex){
ApiJsonResult errResult = ApiJsonResult.createErrResult(ex.getErrorCode(), ex.getReason(), ex.getResolve());
return Mono.just( errResult.toString() );
}
}
- 说明
过滤器会在切面之前执行,因此aop中能获取到在filter中设置的request - 测试结果
更多推荐
已为社区贡献2条内容
所有评论(0)