• 编写自定义的权限校验代码,并且使该过滤器在指定的路由上生效即可
  • 如果权限校验需要使用到redis,则在gateway中需要引入redis的依赖
自定义token权限校验代码
/**
 * @calssName AppTokenFilter
 * @Description 验证路由到APP用户端的接口是否有token
 * @Author jiangshaoneng
 * @DATE 2020/9/25 14:39
 */
public class AppTokenFilter implements GatewayFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(AppTokenFilter.class);

    private int order;

    private TokenRedis tokenRedis;

    private static final List<String> NO_FILTER_PATHS = new ArrayList<>();
    static{
        NO_FILTER_PATHS.add("/game-app-server-api/api/v1/account/register/rapid");         // 快速注册
        NO_FILTER_PATHS.add("/game-app-server-api/api/v1/account/register/mobile");        // 手机注册
        NO_FILTER_PATHS.add("/game-app-server-api/api/v1/account/login/account");          // 账号登录
        NO_FILTER_PATHS.add("/game-app-server-api/api/v1/account/login/mobile");           // 手机登录
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("AppTokenFilter ...");

        // 获取请求地址
        PathContainer pathContainer = exchange.getRequest().getPath().pathWithinApplication();
        String path = pathContainer.toString();

        if(NO_FILTER_PATHS.contains(path)){
            // 无需限制的地址,继续执行
            return chain.filter(exchange);
        }

        // 加载bean对象
        if(tokenRedis == null){
            tokenRedis = SpringUtils.getBean(TokenRedis.class);
        }

        // 获取token
        List<String> headers = exchange.getRequest().getHeaders().get("token");
        String token = headers != null ? headers.get(0) : "";
        logger.info(">>>>>>> token:{} >>>>>>>>", token);

        // 通过token获取redis中对应adminId
        UserInfoBo u = tokenRedis.getUserInfoByToken(token);
        logger.info(">>>>>>> userId:{} >>>>>>>>", u != null ? u.getUserId() : null);

        if(u == null){
            // 返回未登录得提示信息
            return exchange.getResponse().writeWith(Flux.just(exchange.getResponse()
                    .bufferFactory().wrap(JsonUtils.Object2Json(R.error(ErrorCode.SYS_USER_NOT_LOGIN)).getBytes())) );
        }else{
            // 继续执行 todo 这里暂时无法向请求中设置参数;如: req.setAttribute("userId",  u.getUserId());
            return chain.filter(exchange);
        }
    }

    @Override
    public int getOrder() {
        return this.order;
    }

    public AppTokenFilter(int order){
        this.order = order;
    }
}
配置自定义的ApptokenFilter到指定的路由上
@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator appRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route(r -> r.path("/game-app-server-api/api/**")
                .filters(f -> f.filter(new AppTokenFilter(-10))) // 此处的顺序需要根据具体项目而定。通常会在跨域,日志,解密等过滤器后面
                    .uri("lb://game-app-server-api")
                    .id("game-app-server-api")
                ).build();
    }
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐