gateway做token校验

本文使用springcloud的gateway做token校验

登录的本质:拿用户名和密码 换 token。

token会返回给浏览器(存储),当访问的时候,携带token 发起请求。

  1. token校验图
  1. 引入redis依赖

    java 复制代码
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-redis</artifactId>
    		</dependency>
  2. token校验过滤器

java 复制代码
package com.example.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * token 校验
 */
@Component
public class TokenCheckFilter implements GlobalFilter, Ordered {//GlobalFilter全局过滤器,Ordered 顺序优先级

    @Autowired
    private StringRedisTemplate redisTemplate; //引入redis依赖,才能使用
    /**
     * 指定好放行的路径  (可以写在这,也可以写到配置文件中)
     * 白名单 (请求路径)
     */
    public static final List<String> ALLOW_URL = Arrays.asList("login-service/doLogin","/myUrl");

    /**
     *前提是? 和前端约定好,一般放在请求头中  key=Authorization, value=bearer token    (前缀:bearer+空格+token)
     * 1.拿到url  (GlobalFilter是全局过滤器,  但是,登录 没有token,要放行)
     * 2.判断放行   (登录+白名单 放行,不需要token)
     * 然后再校验token
     * 3.拿到 请求头
     * 4.拿到token
     * 5.校验 (看redis 中 有没有,如果没有就拦截,有就放行)
     * 6.放行/拦截
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //拿到url    请求路径
        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)){ //key不为空,取第一个
            String token = authorization.get(0);
            if (StringUtils.hasText(token)){ //token不空
                //约定好有前缀 bearer token
                String realToken = token.replaceFirst("bearer ", "");// replaceFirst替换字符串前面
                if (StringUtils.hasText(realToken) && redisTemplate.hasKey(realToken)){
                    //如果 请求头中 有token, 并且 redis中 有这个token(不带前缀)
                    //放行
                    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]; //以字节形式 写到objectmapper
        try {
            bytes = objectMapper.writeValueAsBytes(map);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        DataBuffer wrap = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(wrap));

    }

    @Override
    public int getOrder() {
        return 2; //先校验ip,再校验token
    }
}
  1. 流程:

    前提: 和前端约定好

    token一般放在请求头中 key=Authorization, value=bearer token

    (前缀:bearer+空格+token)

    • 1.拿到url (GlobalFilter是全局过滤器, 但是,登录 没有token,要放行)
    • 2.判断放行 (登录+白名单 放行,不需要token)
    • 然后再校验token
    • 3.拿到 请求头
    • 4.拿到token
    • 5.校验 (看redis 中 有没有,如果没有就拦截,有就放行)
    • 6.放行/拦截
相关推荐
研究司马懿16 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
Java后端的Ai之路1 天前
【Spring全家桶】-一文弄懂Spring Cloud Gateway
java·后端·spring cloud·gateway
CodeCaptain2 天前
nacos-2.3.2-OEM与nacos3.1.x的差异分析
java·经验分享·nacos·springcloud
Dragon Wu3 天前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
七夜zippoe5 天前
分布式配置中心终极对决 Spring Cloud Config与Apollo架构深度解析
分布式·架构·springcloud·apollo·配置中心
研究司马懿6 天前
【云原生】Gateway API介绍
云原生·gateway
研究司马懿6 天前
【云原生】Gateway API路由、重定向、修饰符等关键操作
云原生·gateway
研究司马懿6 天前
【云原生】初识Gateway API
云原生·gateway
没有bug.的程序员7 天前
Spring Cloud Alibaba:Nacos 配置中心与服务发现的工业级深度实战
java·spring boot·nacos·服务发现·springcloud·配置中心·alibaba
七夜zippoe7 天前
API网关设计模式实战 Spring Cloud Gateway路由过滤限流深度解析
java·设计模式·gateway·路由·api网关