网关的签权参考
网关是响应式的,但是目前大量的签权接口及背后的技术大多是同步的。
- 尽量使用原生异步的(或响应式的)接口
- 当没有时
- 且涉及 io的,把同步转异步,并发生在订阅时
- 如果不涉及 io,按正常处理
1、简单鉴权参考(不涉及同步 io)
此示例,检查有没有 "TOKEN" 的头信息,如果没有就 401 输出并中止。
@Component(index = -9) //index 为可选
public class CloudGatewayAuthFilter implements CloudGatewayFilter {
@Override
public Completable doFilter(ExContext ctx, ExFilterChain chain) {
String token = ctx.rawHeader("TOKEN");
if (token == null) {
//如果没有 TOKEN 表示失败
//方式1:通过格式化内容输出
String resultStr = ONode.stringify(Result.failure(401, "签权失败"));
ctx.newResponse().header("Content-Type", "application/json;charset=UTF-8");
ctx.newResponse().body(Buffer.buffer(resultStr));
return Completable.complete();
//方式2:传递异常(交给异常过滤器统一处理)
//return Completable.error(new StatusException("No authority",401));
}
return chain.doFilter(ctx);
}
}
2、对接 sa-token 鉴权参考(会涉及同步 io)
sa-token 的鉴权行为:
- 会涉及同步io(redis dao),需要使用异步的方式,避免卡住底层的事件循环器
- 签权时还可能会直接输出响应(需要检查,如果已输出说明鉴权未通过)
- 内部是基于经典的 Context 接口适配的(需要用到
ExContext:toContext()
)
可以使用新接口 CloudGatewayFilterSync
或 ExFilterSync
(v3.2.1 后支持),简化开发。
具体对接参考:
@Component(index = -9) //index 为可选
public class CloudGatewayFilterImpl implements CloudGatewayFilterSync {
/**
* @return 是否继续
* */
@Override
public boolean doFilterSync(ExContext ctx) throws Throwable {
try {
//1.获取 web 经典同步接口;并设为当前上下文
Context ctx2 = ctx.toContext();
ContextHolder.currentSet(ctx2);
//2.对接同步处理(使用 sa-token 接口)
//new SaTokenFilter().doFilter(ctx2, ch->{});
StpUtil.checkLogin();
//3.检测是否要结束?
if (ctx2.isHeadersSent()) {
ctx2.flush();
return false; //表示已经有输出(鉴权没通过),不必再继续
} else {
return true;
}
} finally {
ContextHolder.currentRemove();
}
}
}
执行结果说明:
结果 | 说明 |
---|---|
返回 true | 表示“继续”传递过滤 |
返回 false | 表示“不继续”。即触发 onComplete 结束处理 |
抛出异常 | 表示异常。即触发 onError 结束处理 |