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

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

问题出处

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

什么是网关

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

网关能做啥呢

网关可以实现负载均衡,可 以实现 token 拦截,权限验证,限流等操作。
等等token拦截,权限验证,那不就可以对所有的请求进行token校验然后再路由转发给其他的功能模块了吗?所以使用gateway网关实现分布式系统的token校验_第1张图片
那必须动手做呀

Gateway

使用gateway网关实现分布式系统的token校验_第2张图片

从这张图我们可以看出来gateway的核心就是一个一个的过滤器,所以token拦截自然也是在过滤器中完成的啦。这里再上一个图使用gateway网关实现分布式系统的token校验_第3张图片

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;
    }
}

你可能感兴趣的:(开发小技巧,gateway,java,服务器)