使用gateway网关实现分布式系统的token校验

最近在写自己的毕业设计,我本着能与众不同点就不同一点的想法,脑子一热决定,“要不用分布式来写个毕业设计吧”然后悲惨的生活开始了

问题出处

大家都知道http连接是无状态的,所以服务器压根不会知道你到底是谁,你来过吗?
所以咋办?用session咯!但是呢由于现在都流行前后端分离,这两玩意都不在同一个服务器上呀,那session就不能共享了呀。
所以就出现了一个好东西——token,它就像你每天上班都要带的工牌,你不带门口保安叔叔可不让你进去呀。
但是呢还有个问题,我这分布式好多个功能模块噢,那我不得每个模块都来个token检验,那多麻烦呀。好了废话那么多,本次主角该登场了。

什么是网关

网关是微服务最边缘的服务,直接暴露给用户,用来做用户和微服务的桥梁

网关能做啥呢

网关可以实现负载均衡,可 以实现 token 拦截,权限验证,限流等操作。
等等token拦截,权限验证,那不就可以对所有的请求进行token校验然后再路由转发给其他的功能模块了吗?所以请添加图片描述
那必须动手做呀

Gateway

在这里插入图片描述

从这张图我们可以看出来gateway的核心就是一个一个的过滤器,所以token拦截自然也是在过滤器中完成的啦。这里再上一个图请添加图片描述

token校验的实现


/**
 * 使用网关进行token校验拦截
 * 注意这里需要创建这个对象所以需要依赖注入创建
 * */
@Component
public class TokenCheckFilter implements GlobalFilter, Ordered {
    /**
     * 制定好放行的路径
     * */
    public static final List<String> ALLOW_URL = Arrays.asList("/login-service/doLogin","/doLogin");

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        /**
         * 一般和前端约定好 一般把token放在请求头里面 一般key为Authorization (授权的意思) value 为bearer token
         * 拿到请求url判断是否为登录url是就放行,不是继续操作
         * 拿到请求头
         * 拿到token
         * 校验
         * 放行/拦截
         * */
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        if(ALLOW_URL.contains(path)){
            return chain.filter(exchange);
        }
        //检查
        HttpHeaders headers = request.getHeaders();
        List<String> authorization = headers.get("Authorization");
        if(!CollectionUtils.isEmpty(authorization)){
            //如果authorization集合不为空
            //获取第一个为token
            String token = authorization.get(0);
            //判断给token里面的值是不是空字符串
            if(StringUtils.hasText(token)){
                //不为空
                //约定好的有前缀的bearer token
                String realToken = token.replaceFirst("bearer ","");
                //判断realToken是否为空以及redis数据库是否包含
                if(StringUtils.hasText(realToken)&&redisTemplate.hasKey(realToken)){
                    return chain.filter(exchange);
                }
            }
        }
        //如果不符合就不给访问
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().set("content-type","application/json;charset=utf-8");
        HashMap<String,Object> map = new HashMap<>(4);
        //返回401
        map.put("code", HttpStatus.UNAUTHORIZED.value());
        map.put("msg","未授权");
        ObjectMapper objectMapper = new ObjectMapper();
        byte [] bytes = new byte[0];
        try {
            bytes=objectMapper.writeValueAsBytes(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        DataBuffer wrap = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(wrap));
    }

    @Override
    public int getOrder() {
    //配置优先级 越小越先执行
        return -1;
    }
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leach爱喝星冰乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值