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.放行/拦截
相关推荐
sunnyday042618 小时前
Spring Cloud Alibaba Sentinel 流量控制与熔断降级实战指南
spring boot·sentinel·springcloud
一条咸鱼_SaltyFish1 天前
WebFlux vs MVC:Gateway集成若依框架的技术选型之争
java·开发语言·微服务·gateway·mvc·开源软件·webflux
亚林瓜子3 天前
AWS API Gateway添加OAuth2请求头传递app id信息
云计算·gateway·aws·oauth2·请求头·principalid
悟空码字4 天前
Spring Cloud 集成 Nacos,全面的配置中心与服务发现解决方案
java·nacos·springcloud·编程技术·后端开发
daladongba5 天前
Spring Cloud Gateway
java·spring cloud·gateway
潞哥的博客8 天前
Ingress nginx退役,该怎么换,gateway api 上线
运维·gateway·k8s
Gold Steps.9 天前
K8s Gateway-API 标准化流量治理
容器·kubernetes·gateway
J_liaty10 天前
Spring Cloud Gateway与LoadBalancer深度整合实战:从基础到进阶
spring·spring cloud·gateway·loadbalancer
坐不住的爱码10 天前
Bootstrap和application.yml
springcloud
L***d67011 天前
SpringColoud GateWay 核心组件
gateway